##// END OF EJS Templates
debugignore: find out if a file is being ignored...
Laurent Charignon -
r27671:067d87fe default
parent child Browse files
Show More
@@ -1,7013 +1,7039 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 import commandserver
27 27
28 28 table = {}
29 29
30 30 command = cmdutil.command(table)
31 31
32 32 # Space delimited list of commands that don't require local repositories.
33 33 # This should be populated by passing norepo=True into the @command decorator.
34 34 norepo = ''
35 35 # Space delimited list of commands that optionally require local repositories.
36 36 # This should be populated by passing optionalrepo=True into the @command
37 37 # decorator.
38 38 optionalrepo = ''
39 39 # Space delimited list of commands that will examine arguments looking for
40 40 # a repository. This should be populated by passing inferrepo=True into the
41 41 # @command decorator.
42 42 inferrepo = ''
43 43
44 44 # label constants
45 45 # until 3.5, bookmarks.current was the advertised name, not
46 46 # bookmarks.active, so we must use both to avoid breaking old
47 47 # custom styles
48 48 activebookmarklabel = 'bookmarks.active bookmarks.current'
49 49
50 50 # common command options
51 51
52 52 globalopts = [
53 53 ('R', 'repository', '',
54 54 _('repository root directory or name of overlay bundle file'),
55 55 _('REPO')),
56 56 ('', 'cwd', '',
57 57 _('change working directory'), _('DIR')),
58 58 ('y', 'noninteractive', None,
59 59 _('do not prompt, automatically pick the first choice for all prompts')),
60 60 ('q', 'quiet', None, _('suppress output')),
61 61 ('v', 'verbose', None, _('enable additional output')),
62 62 ('', 'config', [],
63 63 _('set/override config option (use \'section.name=value\')'),
64 64 _('CONFIG')),
65 65 ('', 'debug', None, _('enable debugging output')),
66 66 ('', 'debugger', None, _('start debugger')),
67 67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
68 68 _('ENCODE')),
69 69 ('', 'encodingmode', encoding.encodingmode,
70 70 _('set the charset encoding mode'), _('MODE')),
71 71 ('', 'traceback', None, _('always print a traceback on exception')),
72 72 ('', 'time', None, _('time how long the command takes')),
73 73 ('', 'profile', None, _('print command execution profile')),
74 74 ('', 'version', None, _('output version information and exit')),
75 75 ('h', 'help', None, _('display help and exit')),
76 76 ('', 'hidden', False, _('consider hidden changesets')),
77 77 ]
78 78
79 79 dryrunopts = [('n', 'dry-run', None,
80 80 _('do not perform actions, just print output'))]
81 81
82 82 remoteopts = [
83 83 ('e', 'ssh', '',
84 84 _('specify ssh command to use'), _('CMD')),
85 85 ('', 'remotecmd', '',
86 86 _('specify hg command to run on the remote side'), _('CMD')),
87 87 ('', 'insecure', None,
88 88 _('do not verify server certificate (ignoring web.cacerts config)')),
89 89 ]
90 90
91 91 walkopts = [
92 92 ('I', 'include', [],
93 93 _('include names matching the given patterns'), _('PATTERN')),
94 94 ('X', 'exclude', [],
95 95 _('exclude names matching the given patterns'), _('PATTERN')),
96 96 ]
97 97
98 98 commitopts = [
99 99 ('m', 'message', '',
100 100 _('use text as commit message'), _('TEXT')),
101 101 ('l', 'logfile', '',
102 102 _('read commit message from file'), _('FILE')),
103 103 ]
104 104
105 105 commitopts2 = [
106 106 ('d', 'date', '',
107 107 _('record the specified date as commit date'), _('DATE')),
108 108 ('u', 'user', '',
109 109 _('record the specified user as committer'), _('USER')),
110 110 ]
111 111
112 112 # hidden for now
113 113 formatteropts = [
114 114 ('T', 'template', '',
115 115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
116 116 ]
117 117
118 118 templateopts = [
119 119 ('', 'style', '',
120 120 _('display using template map file (DEPRECATED)'), _('STYLE')),
121 121 ('T', 'template', '',
122 122 _('display with template'), _('TEMPLATE')),
123 123 ]
124 124
125 125 logopts = [
126 126 ('p', 'patch', None, _('show patch')),
127 127 ('g', 'git', None, _('use git extended diff format')),
128 128 ('l', 'limit', '',
129 129 _('limit number of changes displayed'), _('NUM')),
130 130 ('M', 'no-merges', None, _('do not show merges')),
131 131 ('', 'stat', None, _('output diffstat-style summary of changes')),
132 132 ('G', 'graph', None, _("show the revision DAG")),
133 133 ] + templateopts
134 134
135 135 diffopts = [
136 136 ('a', 'text', None, _('treat all files as text')),
137 137 ('g', 'git', None, _('use git extended diff format')),
138 138 ('', 'nodates', None, _('omit dates from diff headers'))
139 139 ]
140 140
141 141 diffwsopts = [
142 142 ('w', 'ignore-all-space', None,
143 143 _('ignore white space when comparing lines')),
144 144 ('b', 'ignore-space-change', None,
145 145 _('ignore changes in the amount of white space')),
146 146 ('B', 'ignore-blank-lines', None,
147 147 _('ignore changes whose lines are all blank')),
148 148 ]
149 149
150 150 diffopts2 = [
151 151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
152 152 ('p', 'show-function', None, _('show which function each change is in')),
153 153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
154 154 ] + diffwsopts + [
155 155 ('U', 'unified', '',
156 156 _('number of lines of context to show'), _('NUM')),
157 157 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
159 159 ]
160 160
161 161 mergetoolopts = [
162 162 ('t', 'tool', '', _('specify merge tool')),
163 163 ]
164 164
165 165 similarityopts = [
166 166 ('s', 'similarity', '',
167 167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
168 168 ]
169 169
170 170 subrepoopts = [
171 171 ('S', 'subrepos', None,
172 172 _('recurse into subrepositories'))
173 173 ]
174 174
175 175 debugrevlogopts = [
176 176 ('c', 'changelog', False, _('open changelog')),
177 177 ('m', 'manifest', False, _('open manifest')),
178 178 ('', 'dir', False, _('open directory manifest')),
179 179 ]
180 180
181 181 # Commands start here, listed alphabetically
182 182
183 183 @command('^add',
184 184 walkopts + subrepoopts + dryrunopts,
185 185 _('[OPTION]... [FILE]...'),
186 186 inferrepo=True)
187 187 def add(ui, repo, *pats, **opts):
188 188 """add the specified files on the next commit
189 189
190 190 Schedule files to be version controlled and added to the
191 191 repository.
192 192
193 193 The files will be added to the repository at the next commit. To
194 194 undo an add before that, see :hg:`forget`.
195 195
196 196 If no names are given, add all files to the repository (except
197 197 files matching ``.hgignore``).
198 198
199 199 .. container:: verbose
200 200
201 201 Examples:
202 202
203 203 - New (unknown) files are added
204 204 automatically by :hg:`add`::
205 205
206 206 $ ls
207 207 foo.c
208 208 $ hg status
209 209 ? foo.c
210 210 $ hg add
211 211 adding foo.c
212 212 $ hg status
213 213 A foo.c
214 214
215 215 - Specific files to be added can be specified::
216 216
217 217 $ ls
218 218 bar.c foo.c
219 219 $ hg status
220 220 ? bar.c
221 221 ? foo.c
222 222 $ hg add bar.c
223 223 $ hg status
224 224 A bar.c
225 225 ? foo.c
226 226
227 227 Returns 0 if all files are successfully added.
228 228 """
229 229
230 230 m = scmutil.match(repo[None], pats, opts)
231 231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
232 232 return rejected and 1 or 0
233 233
234 234 @command('addremove',
235 235 similarityopts + subrepoopts + walkopts + dryrunopts,
236 236 _('[OPTION]... [FILE]...'),
237 237 inferrepo=True)
238 238 def addremove(ui, repo, *pats, **opts):
239 239 """add all new files, delete all missing files
240 240
241 241 Add all new files and remove all missing files from the
242 242 repository.
243 243
244 244 Unless names are given, new files are ignored if they match any of
245 245 the patterns in ``.hgignore``. As with add, these changes take
246 246 effect at the next commit.
247 247
248 248 Use the -s/--similarity option to detect renamed files. This
249 249 option takes a percentage between 0 (disabled) and 100 (files must
250 250 be identical) as its parameter. With a parameter greater than 0,
251 251 this compares every removed file with every added file and records
252 252 those similar enough as renames. Detecting renamed files this way
253 253 can be expensive. After using this option, :hg:`status -C` can be
254 254 used to check which files were identified as moved or renamed. If
255 255 not specified, -s/--similarity defaults to 100 and only renames of
256 256 identical files are detected.
257 257
258 258 .. container:: verbose
259 259
260 260 Examples:
261 261
262 262 - A number of files (bar.c and foo.c) are new,
263 263 while foobar.c has been removed (without using :hg:`remove`)
264 264 from the repository::
265 265
266 266 $ ls
267 267 bar.c foo.c
268 268 $ hg status
269 269 ! foobar.c
270 270 ? bar.c
271 271 ? foo.c
272 272 $ hg addremove
273 273 adding bar.c
274 274 adding foo.c
275 275 removing foobar.c
276 276 $ hg status
277 277 A bar.c
278 278 A foo.c
279 279 R foobar.c
280 280
281 281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
282 282 Afterwards, it was edited slightly::
283 283
284 284 $ ls
285 285 foo.c
286 286 $ hg status
287 287 ! foobar.c
288 288 ? foo.c
289 289 $ hg addremove --similarity 90
290 290 removing foobar.c
291 291 adding foo.c
292 292 recording removal of foobar.c as rename to foo.c (94% similar)
293 293 $ hg status -C
294 294 A foo.c
295 295 foobar.c
296 296 R foobar.c
297 297
298 298 Returns 0 if all files are successfully added.
299 299 """
300 300 try:
301 301 sim = float(opts.get('similarity') or 100)
302 302 except ValueError:
303 303 raise error.Abort(_('similarity must be a number'))
304 304 if sim < 0 or sim > 100:
305 305 raise error.Abort(_('similarity must be between 0 and 100'))
306 306 matcher = scmutil.match(repo[None], pats, opts)
307 307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
308 308
309 309 @command('^annotate|blame',
310 310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
311 311 ('', 'follow', None,
312 312 _('follow copies/renames and list the filename (DEPRECATED)')),
313 313 ('', 'no-follow', None, _("don't follow copies and renames")),
314 314 ('a', 'text', None, _('treat all files as text')),
315 315 ('u', 'user', None, _('list the author (long with -v)')),
316 316 ('f', 'file', None, _('list the filename')),
317 317 ('d', 'date', None, _('list the date (short with -q)')),
318 318 ('n', 'number', None, _('list the revision number (default)')),
319 319 ('c', 'changeset', None, _('list the changeset')),
320 320 ('l', 'line-number', None, _('show line number at the first appearance'))
321 321 ] + diffwsopts + walkopts + formatteropts,
322 322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
323 323 inferrepo=True)
324 324 def annotate(ui, repo, *pats, **opts):
325 325 """show changeset information by line for each file
326 326
327 327 List changes in files, showing the revision id responsible for
328 328 each line.
329 329
330 330 This command is useful for discovering when a change was made and
331 331 by whom.
332 332
333 333 If you include --file, --user, or --date, the revision number is
334 334 suppressed unless you also include --number.
335 335
336 336 Without the -a/--text option, annotate will avoid processing files
337 337 it detects as binary. With -a, annotate will annotate the file
338 338 anyway, although the results will probably be neither useful
339 339 nor desirable.
340 340
341 341 Returns 0 on success.
342 342 """
343 343 if not pats:
344 344 raise error.Abort(_('at least one filename or pattern is required'))
345 345
346 346 if opts.get('follow'):
347 347 # --follow is deprecated and now just an alias for -f/--file
348 348 # to mimic the behavior of Mercurial before version 1.5
349 349 opts['file'] = True
350 350
351 351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352 352
353 353 fm = ui.formatter('annotate', opts)
354 354 if ui.quiet:
355 355 datefunc = util.shortdate
356 356 else:
357 357 datefunc = util.datestr
358 358 if ctx.rev() is None:
359 359 def hexfn(node):
360 360 if node is None:
361 361 return None
362 362 else:
363 363 return fm.hexfunc(node)
364 364 if opts.get('changeset'):
365 365 # omit "+" suffix which is appended to node hex
366 366 def formatrev(rev):
367 367 if rev is None:
368 368 return '%d' % ctx.p1().rev()
369 369 else:
370 370 return '%d' % rev
371 371 else:
372 372 def formatrev(rev):
373 373 if rev is None:
374 374 return '%d+' % ctx.p1().rev()
375 375 else:
376 376 return '%d ' % rev
377 377 def formathex(hex):
378 378 if hex is None:
379 379 return '%s+' % fm.hexfunc(ctx.p1().node())
380 380 else:
381 381 return '%s ' % hex
382 382 else:
383 383 hexfn = fm.hexfunc
384 384 formatrev = formathex = str
385 385
386 386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
387 387 ('number', ' ', lambda x: x[0].rev(), formatrev),
388 388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
389 389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
390 390 ('file', ' ', lambda x: x[0].path(), str),
391 391 ('line_number', ':', lambda x: x[1], str),
392 392 ]
393 393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
394 394
395 395 if (not opts.get('user') and not opts.get('changeset')
396 396 and not opts.get('date') and not opts.get('file')):
397 397 opts['number'] = True
398 398
399 399 linenumber = opts.get('line_number') is not None
400 400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
401 401 raise error.Abort(_('at least one of -n/-c is required for -l'))
402 402
403 403 if fm:
404 404 def makefunc(get, fmt):
405 405 return get
406 406 else:
407 407 def makefunc(get, fmt):
408 408 return lambda x: fmt(get(x))
409 409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
410 410 if opts.get(op)]
411 411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
412 412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
413 413 if opts.get(op))
414 414
415 415 def bad(x, y):
416 416 raise error.Abort("%s: %s" % (x, y))
417 417
418 418 m = scmutil.match(ctx, pats, opts, badfn=bad)
419 419
420 420 follow = not opts.get('no_follow')
421 421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
422 422 whitespace=True)
423 423 for abs in ctx.walk(m):
424 424 fctx = ctx[abs]
425 425 if not opts.get('text') and util.binary(fctx.data()):
426 426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
427 427 continue
428 428
429 429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
430 430 diffopts=diffopts)
431 431 formats = []
432 432 pieces = []
433 433
434 434 for f, sep in funcmap:
435 435 l = [f(n) for n, dummy in lines]
436 436 if l:
437 437 if fm:
438 438 formats.append(['%s' for x in l])
439 439 else:
440 440 sizes = [encoding.colwidth(x) for x in l]
441 441 ml = max(sizes)
442 442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
443 443 pieces.append(l)
444 444
445 445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
446 446 fm.startitem()
447 447 fm.write(fields, "".join(f), *p)
448 448 fm.write('line', ": %s", l[1])
449 449
450 450 if lines and not lines[-1][1].endswith('\n'):
451 451 fm.plain('\n')
452 452
453 453 fm.end()
454 454
455 455 @command('archive',
456 456 [('', 'no-decode', None, _('do not pass files through decoders')),
457 457 ('p', 'prefix', '', _('directory prefix for files in archive'),
458 458 _('PREFIX')),
459 459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
460 460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
461 461 ] + subrepoopts + walkopts,
462 462 _('[OPTION]... DEST'))
463 463 def archive(ui, repo, dest, **opts):
464 464 '''create an unversioned archive of a repository revision
465 465
466 466 By default, the revision used is the parent of the working
467 467 directory; use -r/--rev to specify a different revision.
468 468
469 469 The archive type is automatically detected based on file
470 470 extension (to override, use -t/--type).
471 471
472 472 .. container:: verbose
473 473
474 474 Examples:
475 475
476 476 - create a zip file containing the 1.0 release::
477 477
478 478 hg archive -r 1.0 project-1.0.zip
479 479
480 480 - create a tarball excluding .hg files::
481 481
482 482 hg archive project.tar.gz -X ".hg*"
483 483
484 484 Valid types are:
485 485
486 486 :``files``: a directory full of files (default)
487 487 :``tar``: tar archive, uncompressed
488 488 :``tbz2``: tar archive, compressed using bzip2
489 489 :``tgz``: tar archive, compressed using gzip
490 490 :``uzip``: zip archive, uncompressed
491 491 :``zip``: zip archive, compressed using deflate
492 492
493 493 The exact name of the destination archive or directory is given
494 494 using a format string; see :hg:`help export` for details.
495 495
496 496 Each member added to an archive file has a directory prefix
497 497 prepended. Use -p/--prefix to specify a format string for the
498 498 prefix. The default is the basename of the archive, with suffixes
499 499 removed.
500 500
501 501 Returns 0 on success.
502 502 '''
503 503
504 504 ctx = scmutil.revsingle(repo, opts.get('rev'))
505 505 if not ctx:
506 506 raise error.Abort(_('no working directory: please specify a revision'))
507 507 node = ctx.node()
508 508 dest = cmdutil.makefilename(repo, dest, node)
509 509 if os.path.realpath(dest) == repo.root:
510 510 raise error.Abort(_('repository root cannot be destination'))
511 511
512 512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
513 513 prefix = opts.get('prefix')
514 514
515 515 if dest == '-':
516 516 if kind == 'files':
517 517 raise error.Abort(_('cannot archive plain files to stdout'))
518 518 dest = cmdutil.makefileobj(repo, dest)
519 519 if not prefix:
520 520 prefix = os.path.basename(repo.root) + '-%h'
521 521
522 522 prefix = cmdutil.makefilename(repo, prefix, node)
523 523 matchfn = scmutil.match(ctx, [], opts)
524 524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
525 525 matchfn, prefix, subrepos=opts.get('subrepos'))
526 526
527 527 @command('backout',
528 528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
529 529 ('', 'commit', None, _('commit if no conflicts were encountered')),
530 530 ('', 'parent', '',
531 531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
532 532 ('r', 'rev', '', _('revision to backout'), _('REV')),
533 533 ('e', 'edit', False, _('invoke editor on commit messages')),
534 534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
535 535 _('[OPTION]... [-r] REV'))
536 536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
537 537 '''reverse effect of earlier changeset
538 538
539 539 Prepare a new changeset with the effect of REV undone in the
540 540 current working directory.
541 541
542 542 If REV is the parent of the working directory, then this new changeset
543 543 is committed automatically. Otherwise, hg needs to merge the
544 544 changes and the merged result is left uncommitted.
545 545
546 546 .. note::
547 547
548 548 :hg:`backout` cannot be used to fix either an unwanted or
549 549 incorrect merge.
550 550
551 551 .. container:: verbose
552 552
553 553 Examples:
554 554
555 555 - Reverse the effect of the parent of the working directory.
556 556 This backout will be committed immediately::
557 557
558 558 hg backout -r .
559 559
560 560 - Reverse the effect of previous bad revision 23::
561 561
562 562 hg backout -r 23
563 563 hg commit -m "Backout revision 23"
564 564
565 565 - Reverse the effect of previous bad revision 23 and
566 566 commit the backout immediately::
567 567
568 568 hg backout -r 23 --commit
569 569
570 570 By default, the pending changeset will have one parent,
571 571 maintaining a linear history. With --merge, the pending
572 572 changeset will instead have two parents: the old parent of the
573 573 working directory and a new child of REV that simply undoes REV.
574 574
575 575 Before version 1.7, the behavior without --merge was equivalent
576 576 to specifying --merge followed by :hg:`update --clean .` to
577 577 cancel the merge and leave the child of REV as a head to be
578 578 merged separately.
579 579
580 580 See :hg:`help dates` for a list of formats valid for -d/--date.
581 581
582 582 See :hg:`help revert` for a way to restore files to the state
583 583 of another revision.
584 584
585 585 Returns 0 on success, 1 if nothing to backout or there are unresolved
586 586 files.
587 587 '''
588 588 wlock = lock = None
589 589 try:
590 590 wlock = repo.wlock()
591 591 lock = repo.lock()
592 592 return _dobackout(ui, repo, node, rev, commit, **opts)
593 593 finally:
594 594 release(lock, wlock)
595 595
596 596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
597 597 if rev and node:
598 598 raise error.Abort(_("please specify just one revision"))
599 599
600 600 if not rev:
601 601 rev = node
602 602
603 603 if not rev:
604 604 raise error.Abort(_("please specify a revision to backout"))
605 605
606 606 date = opts.get('date')
607 607 if date:
608 608 opts['date'] = util.parsedate(date)
609 609
610 610 cmdutil.checkunfinished(repo)
611 611 cmdutil.bailifchanged(repo)
612 612 node = scmutil.revsingle(repo, rev).node()
613 613
614 614 op1, op2 = repo.dirstate.parents()
615 615 if not repo.changelog.isancestor(node, op1):
616 616 raise error.Abort(_('cannot backout change that is not an ancestor'))
617 617
618 618 p1, p2 = repo.changelog.parents(node)
619 619 if p1 == nullid:
620 620 raise error.Abort(_('cannot backout a change with no parents'))
621 621 if p2 != nullid:
622 622 if not opts.get('parent'):
623 623 raise error.Abort(_('cannot backout a merge changeset'))
624 624 p = repo.lookup(opts['parent'])
625 625 if p not in (p1, p2):
626 626 raise error.Abort(_('%s is not a parent of %s') %
627 627 (short(p), short(node)))
628 628 parent = p
629 629 else:
630 630 if opts.get('parent'):
631 631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
632 632 parent = p1
633 633
634 634 # the backout should appear on the same branch
635 635 try:
636 636 branch = repo.dirstate.branch()
637 637 bheads = repo.branchheads(branch)
638 638 rctx = scmutil.revsingle(repo, hex(parent))
639 639 if not opts.get('merge') and op1 != node:
640 640 dsguard = cmdutil.dirstateguard(repo, 'backout')
641 641 try:
642 642 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
643 643 'backout')
644 644 stats = mergemod.update(repo, parent, True, True, node, False)
645 645 repo.setparents(op1, op2)
646 646 dsguard.close()
647 647 hg._showstats(repo, stats)
648 648 if stats[3]:
649 649 repo.ui.status(_("use 'hg resolve' to retry unresolved "
650 650 "file merges\n"))
651 651 return 1
652 652 elif not commit:
653 653 msg = _("changeset %s backed out, "
654 654 "don't forget to commit.\n")
655 655 ui.status(msg % short(node))
656 656 return 0
657 657 finally:
658 658 ui.setconfig('ui', 'forcemerge', '', '')
659 659 lockmod.release(dsguard)
660 660 else:
661 661 hg.clean(repo, node, show_stats=False)
662 662 repo.dirstate.setbranch(branch)
663 663 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
664 664
665 665
666 666 def commitfunc(ui, repo, message, match, opts):
667 667 editform = 'backout'
668 668 e = cmdutil.getcommiteditor(editform=editform, **opts)
669 669 if not message:
670 670 # we don't translate commit messages
671 671 message = "Backed out changeset %s" % short(node)
672 672 e = cmdutil.getcommiteditor(edit=True, editform=editform)
673 673 return repo.commit(message, opts.get('user'), opts.get('date'),
674 674 match, editor=e)
675 675 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
676 676 if not newnode:
677 677 ui.status(_("nothing changed\n"))
678 678 return 1
679 679 cmdutil.commitstatus(repo, newnode, branch, bheads)
680 680
681 681 def nice(node):
682 682 return '%d:%s' % (repo.changelog.rev(node), short(node))
683 683 ui.status(_('changeset %s backs out changeset %s\n') %
684 684 (nice(repo.changelog.tip()), nice(node)))
685 685 if opts.get('merge') and op1 != node:
686 686 hg.clean(repo, op1, show_stats=False)
687 687 ui.status(_('merging with changeset %s\n')
688 688 % nice(repo.changelog.tip()))
689 689 try:
690 690 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
691 691 'backout')
692 692 return hg.merge(repo, hex(repo.changelog.tip()))
693 693 finally:
694 694 ui.setconfig('ui', 'forcemerge', '', '')
695 695 finally:
696 696 # TODO: get rid of this meaningless try/finally enclosing.
697 697 # this is kept only to reduce changes in a patch.
698 698 pass
699 699 return 0
700 700
701 701 @command('bisect',
702 702 [('r', 'reset', False, _('reset bisect state')),
703 703 ('g', 'good', False, _('mark changeset good')),
704 704 ('b', 'bad', False, _('mark changeset bad')),
705 705 ('s', 'skip', False, _('skip testing changeset')),
706 706 ('e', 'extend', False, _('extend the bisect range')),
707 707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
708 708 ('U', 'noupdate', False, _('do not update to target'))],
709 709 _("[-gbsr] [-U] [-c CMD] [REV]"))
710 710 def bisect(ui, repo, rev=None, extra=None, command=None,
711 711 reset=None, good=None, bad=None, skip=None, extend=None,
712 712 noupdate=None):
713 713 """subdivision search of changesets
714 714
715 715 This command helps to find changesets which introduce problems. To
716 716 use, mark the earliest changeset you know exhibits the problem as
717 717 bad, then mark the latest changeset which is free from the problem
718 718 as good. Bisect will update your working directory to a revision
719 719 for testing (unless the -U/--noupdate option is specified). Once
720 720 you have performed tests, mark the working directory as good or
721 721 bad, and bisect will either update to another candidate changeset
722 722 or announce that it has found the bad revision.
723 723
724 724 As a shortcut, you can also use the revision argument to mark a
725 725 revision as good or bad without checking it out first.
726 726
727 727 If you supply a command, it will be used for automatic bisection.
728 728 The environment variable HG_NODE will contain the ID of the
729 729 changeset being tested. The exit status of the command will be
730 730 used to mark revisions as good or bad: status 0 means good, 125
731 731 means to skip the revision, 127 (command not found) will abort the
732 732 bisection, and any other non-zero exit status means the revision
733 733 is bad.
734 734
735 735 .. container:: verbose
736 736
737 737 Some examples:
738 738
739 739 - start a bisection with known bad revision 34, and good revision 12::
740 740
741 741 hg bisect --bad 34
742 742 hg bisect --good 12
743 743
744 744 - advance the current bisection by marking current revision as good or
745 745 bad::
746 746
747 747 hg bisect --good
748 748 hg bisect --bad
749 749
750 750 - mark the current revision, or a known revision, to be skipped (e.g. if
751 751 that revision is not usable because of another issue)::
752 752
753 753 hg bisect --skip
754 754 hg bisect --skip 23
755 755
756 756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
757 757
758 758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
759 759
760 760 - forget the current bisection::
761 761
762 762 hg bisect --reset
763 763
764 764 - use 'make && make tests' to automatically find the first broken
765 765 revision::
766 766
767 767 hg bisect --reset
768 768 hg bisect --bad 34
769 769 hg bisect --good 12
770 770 hg bisect --command "make && make tests"
771 771
772 772 - see all changesets whose states are already known in the current
773 773 bisection::
774 774
775 775 hg log -r "bisect(pruned)"
776 776
777 777 - see the changeset currently being bisected (especially useful
778 778 if running with -U/--noupdate)::
779 779
780 780 hg log -r "bisect(current)"
781 781
782 782 - see all changesets that took part in the current bisection::
783 783
784 784 hg log -r "bisect(range)"
785 785
786 786 - you can even get a nice graph::
787 787
788 788 hg log --graph -r "bisect(range)"
789 789
790 790 See :hg:`help revsets` for more about the `bisect()` keyword.
791 791
792 792 Returns 0 on success.
793 793 """
794 794 def extendbisectrange(nodes, good):
795 795 # bisect is incomplete when it ends on a merge node and
796 796 # one of the parent was not checked.
797 797 parents = repo[nodes[0]].parents()
798 798 if len(parents) > 1:
799 799 if good:
800 800 side = state['bad']
801 801 else:
802 802 side = state['good']
803 803 num = len(set(i.node() for i in parents) & set(side))
804 804 if num == 1:
805 805 return parents[0].ancestor(parents[1])
806 806 return None
807 807
808 808 def print_result(nodes, good):
809 809 displayer = cmdutil.show_changeset(ui, repo, {})
810 810 if len(nodes) == 1:
811 811 # narrowed it down to a single revision
812 812 if good:
813 813 ui.write(_("The first good revision is:\n"))
814 814 else:
815 815 ui.write(_("The first bad revision is:\n"))
816 816 displayer.show(repo[nodes[0]])
817 817 extendnode = extendbisectrange(nodes, good)
818 818 if extendnode is not None:
819 819 ui.write(_('Not all ancestors of this changeset have been'
820 820 ' checked.\nUse bisect --extend to continue the '
821 821 'bisection from\nthe common ancestor, %s.\n')
822 822 % extendnode)
823 823 else:
824 824 # multiple possible revisions
825 825 if good:
826 826 ui.write(_("Due to skipped revisions, the first "
827 827 "good revision could be any of:\n"))
828 828 else:
829 829 ui.write(_("Due to skipped revisions, the first "
830 830 "bad revision could be any of:\n"))
831 831 for n in nodes:
832 832 displayer.show(repo[n])
833 833 displayer.close()
834 834
835 835 def check_state(state, interactive=True):
836 836 if not state['good'] or not state['bad']:
837 837 if (good or bad or skip or reset) and interactive:
838 838 return
839 839 if not state['good']:
840 840 raise error.Abort(_('cannot bisect (no known good revisions)'))
841 841 else:
842 842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
843 843 return True
844 844
845 845 # backward compatibility
846 846 if rev in "good bad reset init".split():
847 847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
848 848 cmd, rev, extra = rev, extra, None
849 849 if cmd == "good":
850 850 good = True
851 851 elif cmd == "bad":
852 852 bad = True
853 853 else:
854 854 reset = True
855 855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
856 856 raise error.Abort(_('incompatible arguments'))
857 857
858 858 cmdutil.checkunfinished(repo)
859 859
860 860 if reset:
861 861 p = repo.join("bisect.state")
862 862 if os.path.exists(p):
863 863 os.unlink(p)
864 864 return
865 865
866 866 state = hbisect.load_state(repo)
867 867
868 868 if command:
869 869 changesets = 1
870 870 if noupdate:
871 871 try:
872 872 node = state['current'][0]
873 873 except LookupError:
874 874 raise error.Abort(_('current bisect revision is unknown - '
875 875 'start a new bisect to fix'))
876 876 else:
877 877 node, p2 = repo.dirstate.parents()
878 878 if p2 != nullid:
879 879 raise error.Abort(_('current bisect revision is a merge'))
880 880 try:
881 881 while changesets:
882 882 # update state
883 883 state['current'] = [node]
884 884 hbisect.save_state(repo, state)
885 885 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 886 if status == 125:
887 887 transition = "skip"
888 888 elif status == 0:
889 889 transition = "good"
890 890 # status < 0 means process was killed
891 891 elif status == 127:
892 892 raise error.Abort(_("failed to execute %s") % command)
893 893 elif status < 0:
894 894 raise error.Abort(_("%s killed") % command)
895 895 else:
896 896 transition = "bad"
897 897 ctx = scmutil.revsingle(repo, rev, node)
898 898 rev = None # clear for future iterations
899 899 state[transition].append(ctx.node())
900 900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
901 901 check_state(state, interactive=False)
902 902 # bisect
903 903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
904 904 # update to next check
905 905 node = nodes[0]
906 906 if not noupdate:
907 907 cmdutil.bailifchanged(repo)
908 908 hg.clean(repo, node, show_stats=False)
909 909 finally:
910 910 state['current'] = [node]
911 911 hbisect.save_state(repo, state)
912 912 print_result(nodes, bgood)
913 913 return
914 914
915 915 # update state
916 916
917 917 if rev:
918 918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
919 919 else:
920 920 nodes = [repo.lookup('.')]
921 921
922 922 if good or bad or skip:
923 923 if good:
924 924 state['good'] += nodes
925 925 elif bad:
926 926 state['bad'] += nodes
927 927 elif skip:
928 928 state['skip'] += nodes
929 929 hbisect.save_state(repo, state)
930 930
931 931 if not check_state(state):
932 932 return
933 933
934 934 # actually bisect
935 935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
936 936 if extend:
937 937 if not changesets:
938 938 extendnode = extendbisectrange(nodes, good)
939 939 if extendnode is not None:
940 940 ui.write(_("Extending search to changeset %d:%s\n")
941 941 % (extendnode.rev(), extendnode))
942 942 state['current'] = [extendnode.node()]
943 943 hbisect.save_state(repo, state)
944 944 if noupdate:
945 945 return
946 946 cmdutil.bailifchanged(repo)
947 947 return hg.clean(repo, extendnode.node())
948 948 raise error.Abort(_("nothing to extend"))
949 949
950 950 if changesets == 0:
951 951 print_result(nodes, good)
952 952 else:
953 953 assert len(nodes) == 1 # only a single node can be tested next
954 954 node = nodes[0]
955 955 # compute the approximate number of remaining tests
956 956 tests, size = 0, 2
957 957 while size <= changesets:
958 958 tests, size = tests + 1, size * 2
959 959 rev = repo.changelog.rev(node)
960 960 ui.write(_("Testing changeset %d:%s "
961 961 "(%d changesets remaining, ~%d tests)\n")
962 962 % (rev, short(node), changesets, tests))
963 963 state['current'] = [node]
964 964 hbisect.save_state(repo, state)
965 965 if not noupdate:
966 966 cmdutil.bailifchanged(repo)
967 967 return hg.clean(repo, node)
968 968
969 969 @command('bookmarks|bookmark',
970 970 [('f', 'force', False, _('force')),
971 971 ('r', 'rev', '', _('revision'), _('REV')),
972 972 ('d', 'delete', False, _('delete a given bookmark')),
973 973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
974 974 ('i', 'inactive', False, _('mark a bookmark inactive')),
975 975 ] + formatteropts,
976 976 _('hg bookmarks [OPTIONS]... [NAME]...'))
977 977 def bookmark(ui, repo, *names, **opts):
978 978 '''create a new bookmark or list existing bookmarks
979 979
980 980 Bookmarks are labels on changesets to help track lines of development.
981 981 Bookmarks are unversioned and can be moved, renamed and deleted.
982 982 Deleting or moving a bookmark has no effect on the associated changesets.
983 983
984 984 Creating or updating to a bookmark causes it to be marked as 'active'.
985 985 The active bookmark is indicated with a '*'.
986 986 When a commit is made, the active bookmark will advance to the new commit.
987 987 A plain :hg:`update` will also advance an active bookmark, if possible.
988 988 Updating away from a bookmark will cause it to be deactivated.
989 989
990 990 Bookmarks can be pushed and pulled between repositories (see
991 991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
992 992 diverged, a new 'divergent bookmark' of the form 'name@path' will
993 993 be created. Using :hg:`merge` will resolve the divergence.
994 994
995 995 A bookmark named '@' has the special property that :hg:`clone` will
996 996 check it out by default if it exists.
997 997
998 998 .. container:: verbose
999 999
1000 1000 Examples:
1001 1001
1002 1002 - create an active bookmark for a new line of development::
1003 1003
1004 1004 hg book new-feature
1005 1005
1006 1006 - create an inactive bookmark as a place marker::
1007 1007
1008 1008 hg book -i reviewed
1009 1009
1010 1010 - create an inactive bookmark on another changeset::
1011 1011
1012 1012 hg book -r .^ tested
1013 1013
1014 1014 - rename bookmark turkey to dinner::
1015 1015
1016 1016 hg book -m turkey dinner
1017 1017
1018 1018 - move the '@' bookmark from another branch::
1019 1019
1020 1020 hg book -f @
1021 1021 '''
1022 1022 force = opts.get('force')
1023 1023 rev = opts.get('rev')
1024 1024 delete = opts.get('delete')
1025 1025 rename = opts.get('rename')
1026 1026 inactive = opts.get('inactive')
1027 1027
1028 1028 def checkformat(mark):
1029 1029 mark = mark.strip()
1030 1030 if not mark:
1031 1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1032 1032 "whitespace"))
1033 1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1034 1034 return mark
1035 1035
1036 1036 def checkconflict(repo, mark, cur, force=False, target=None):
1037 1037 if mark in marks and not force:
1038 1038 if target:
1039 1039 if marks[mark] == target and target == cur:
1040 1040 # re-activating a bookmark
1041 1041 return
1042 1042 anc = repo.changelog.ancestors([repo[target].rev()])
1043 1043 bmctx = repo[marks[mark]]
1044 1044 divs = [repo[b].node() for b in marks
1045 1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1046 1046
1047 1047 # allow resolving a single divergent bookmark even if moving
1048 1048 # the bookmark across branches when a revision is specified
1049 1049 # that contains a divergent bookmark
1050 1050 if bmctx.rev() not in anc and target in divs:
1051 1051 bookmarks.deletedivergent(repo, [target], mark)
1052 1052 return
1053 1053
1054 1054 deletefrom = [b for b in divs
1055 1055 if repo[b].rev() in anc or b == target]
1056 1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1057 1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1058 1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1059 1059 (mark, short(bmctx.node())))
1060 1060 return
1061 1061 raise error.Abort(_("bookmark '%s' already exists "
1062 1062 "(use -f to force)") % mark)
1063 1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1064 1064 and not force):
1065 1065 raise error.Abort(
1066 1066 _("a bookmark cannot have the name of an existing branch"))
1067 1067
1068 1068 if delete and rename:
1069 1069 raise error.Abort(_("--delete and --rename are incompatible"))
1070 1070 if delete and rev:
1071 1071 raise error.Abort(_("--rev is incompatible with --delete"))
1072 1072 if rename and rev:
1073 1073 raise error.Abort(_("--rev is incompatible with --rename"))
1074 1074 if not names and (delete or rev):
1075 1075 raise error.Abort(_("bookmark name required"))
1076 1076
1077 1077 if delete or rename or names or inactive:
1078 1078 wlock = lock = tr = None
1079 1079 try:
1080 1080 wlock = repo.wlock()
1081 1081 lock = repo.lock()
1082 1082 cur = repo.changectx('.').node()
1083 1083 marks = repo._bookmarks
1084 1084 if delete:
1085 1085 tr = repo.transaction('bookmark')
1086 1086 for mark in names:
1087 1087 if mark not in marks:
1088 1088 raise error.Abort(_("bookmark '%s' does not exist") %
1089 1089 mark)
1090 1090 if mark == repo._activebookmark:
1091 1091 bookmarks.deactivate(repo)
1092 1092 del marks[mark]
1093 1093
1094 1094 elif rename:
1095 1095 tr = repo.transaction('bookmark')
1096 1096 if not names:
1097 1097 raise error.Abort(_("new bookmark name required"))
1098 1098 elif len(names) > 1:
1099 1099 raise error.Abort(_("only one new bookmark name allowed"))
1100 1100 mark = checkformat(names[0])
1101 1101 if rename not in marks:
1102 1102 raise error.Abort(_("bookmark '%s' does not exist")
1103 1103 % rename)
1104 1104 checkconflict(repo, mark, cur, force)
1105 1105 marks[mark] = marks[rename]
1106 1106 if repo._activebookmark == rename and not inactive:
1107 1107 bookmarks.activate(repo, mark)
1108 1108 del marks[rename]
1109 1109 elif names:
1110 1110 tr = repo.transaction('bookmark')
1111 1111 newact = None
1112 1112 for mark in names:
1113 1113 mark = checkformat(mark)
1114 1114 if newact is None:
1115 1115 newact = mark
1116 1116 if inactive and mark == repo._activebookmark:
1117 1117 bookmarks.deactivate(repo)
1118 1118 return
1119 1119 tgt = cur
1120 1120 if rev:
1121 1121 tgt = scmutil.revsingle(repo, rev).node()
1122 1122 checkconflict(repo, mark, cur, force, tgt)
1123 1123 marks[mark] = tgt
1124 1124 if not inactive and cur == marks[newact] and not rev:
1125 1125 bookmarks.activate(repo, newact)
1126 1126 elif cur != tgt and newact == repo._activebookmark:
1127 1127 bookmarks.deactivate(repo)
1128 1128 elif inactive:
1129 1129 if len(marks) == 0:
1130 1130 ui.status(_("no bookmarks set\n"))
1131 1131 elif not repo._activebookmark:
1132 1132 ui.status(_("no active bookmark\n"))
1133 1133 else:
1134 1134 bookmarks.deactivate(repo)
1135 1135 if tr is not None:
1136 1136 marks.recordchange(tr)
1137 1137 tr.close()
1138 1138 finally:
1139 1139 lockmod.release(tr, lock, wlock)
1140 1140 else: # show bookmarks
1141 1141 fm = ui.formatter('bookmarks', opts)
1142 1142 hexfn = fm.hexfunc
1143 1143 marks = repo._bookmarks
1144 1144 if len(marks) == 0 and not fm:
1145 1145 ui.status(_("no bookmarks set\n"))
1146 1146 for bmark, n in sorted(marks.iteritems()):
1147 1147 active = repo._activebookmark
1148 1148 if bmark == active:
1149 1149 prefix, label = '*', activebookmarklabel
1150 1150 else:
1151 1151 prefix, label = ' ', ''
1152 1152
1153 1153 fm.startitem()
1154 1154 if not ui.quiet:
1155 1155 fm.plain(' %s ' % prefix, label=label)
1156 1156 fm.write('bookmark', '%s', bmark, label=label)
1157 1157 pad = " " * (25 - encoding.colwidth(bmark))
1158 1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1159 1159 repo.changelog.rev(n), hexfn(n), label=label)
1160 1160 fm.data(active=(bmark == active))
1161 1161 fm.plain('\n')
1162 1162 fm.end()
1163 1163
1164 1164 @command('branch',
1165 1165 [('f', 'force', None,
1166 1166 _('set branch name even if it shadows an existing branch')),
1167 1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1168 1168 _('[-fC] [NAME]'))
1169 1169 def branch(ui, repo, label=None, **opts):
1170 1170 """set or show the current branch name
1171 1171
1172 1172 .. note::
1173 1173
1174 1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1175 1175 light-weight bookmark instead. See :hg:`help glossary` for more
1176 1176 information about named branches and bookmarks.
1177 1177
1178 1178 With no argument, show the current branch name. With one argument,
1179 1179 set the working directory branch name (the branch will not exist
1180 1180 in the repository until the next commit). Standard practice
1181 1181 recommends that primary development take place on the 'default'
1182 1182 branch.
1183 1183
1184 1184 Unless -f/--force is specified, branch will not let you set a
1185 1185 branch name that already exists.
1186 1186
1187 1187 Use -C/--clean to reset the working directory branch to that of
1188 1188 the parent of the working directory, negating a previous branch
1189 1189 change.
1190 1190
1191 1191 Use the command :hg:`update` to switch to an existing branch. Use
1192 1192 :hg:`commit --close-branch` to mark this branch head as closed.
1193 1193 When all heads of a branch are closed, the branch will be
1194 1194 considered closed.
1195 1195
1196 1196 Returns 0 on success.
1197 1197 """
1198 1198 if label:
1199 1199 label = label.strip()
1200 1200
1201 1201 if not opts.get('clean') and not label:
1202 1202 ui.write("%s\n" % repo.dirstate.branch())
1203 1203 return
1204 1204
1205 1205 wlock = repo.wlock()
1206 1206 try:
1207 1207 if opts.get('clean'):
1208 1208 label = repo[None].p1().branch()
1209 1209 repo.dirstate.setbranch(label)
1210 1210 ui.status(_('reset working directory to branch %s\n') % label)
1211 1211 elif label:
1212 1212 if not opts.get('force') and label in repo.branchmap():
1213 1213 if label not in [p.branch() for p in repo[None].parents()]:
1214 1214 raise error.Abort(_('a branch of the same name already'
1215 1215 ' exists'),
1216 1216 # i18n: "it" refers to an existing branch
1217 1217 hint=_("use 'hg update' to switch to it"))
1218 1218 scmutil.checknewlabel(repo, label, 'branch')
1219 1219 repo.dirstate.setbranch(label)
1220 1220 ui.status(_('marked working directory as branch %s\n') % label)
1221 1221
1222 1222 # find any open named branches aside from default
1223 1223 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1224 1224 if n != "default" and not c]
1225 1225 if not others:
1226 1226 ui.status(_('(branches are permanent and global, '
1227 1227 'did you want a bookmark?)\n'))
1228 1228 finally:
1229 1229 wlock.release()
1230 1230
1231 1231 @command('branches',
1232 1232 [('a', 'active', False,
1233 1233 _('show only branches that have unmerged heads (DEPRECATED)')),
1234 1234 ('c', 'closed', False, _('show normal and closed branches')),
1235 1235 ] + formatteropts,
1236 1236 _('[-ac]'))
1237 1237 def branches(ui, repo, active=False, closed=False, **opts):
1238 1238 """list repository named branches
1239 1239
1240 1240 List the repository's named branches, indicating which ones are
1241 1241 inactive. If -c/--closed is specified, also list branches which have
1242 1242 been marked closed (see :hg:`commit --close-branch`).
1243 1243
1244 1244 Use the command :hg:`update` to switch to an existing branch.
1245 1245
1246 1246 Returns 0.
1247 1247 """
1248 1248
1249 1249 fm = ui.formatter('branches', opts)
1250 1250 hexfunc = fm.hexfunc
1251 1251
1252 1252 allheads = set(repo.heads())
1253 1253 branches = []
1254 1254 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1255 1255 isactive = not isclosed and bool(set(heads) & allheads)
1256 1256 branches.append((tag, repo[tip], isactive, not isclosed))
1257 1257 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1258 1258 reverse=True)
1259 1259
1260 1260 for tag, ctx, isactive, isopen in branches:
1261 1261 if active and not isactive:
1262 1262 continue
1263 1263 if isactive:
1264 1264 label = 'branches.active'
1265 1265 notice = ''
1266 1266 elif not isopen:
1267 1267 if not closed:
1268 1268 continue
1269 1269 label = 'branches.closed'
1270 1270 notice = _(' (closed)')
1271 1271 else:
1272 1272 label = 'branches.inactive'
1273 1273 notice = _(' (inactive)')
1274 1274 current = (tag == repo.dirstate.branch())
1275 1275 if current:
1276 1276 label = 'branches.current'
1277 1277
1278 1278 fm.startitem()
1279 1279 fm.write('branch', '%s', tag, label=label)
1280 1280 rev = ctx.rev()
1281 1281 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1282 1282 fmt = ' ' * padsize + ' %d:%s'
1283 1283 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1284 1284 label='log.changeset changeset.%s' % ctx.phasestr())
1285 1285 fm.data(active=isactive, closed=not isopen, current=current)
1286 1286 if not ui.quiet:
1287 1287 fm.plain(notice)
1288 1288 fm.plain('\n')
1289 1289 fm.end()
1290 1290
1291 1291 @command('bundle',
1292 1292 [('f', 'force', None, _('run even when the destination is unrelated')),
1293 1293 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1294 1294 _('REV')),
1295 1295 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1296 1296 _('BRANCH')),
1297 1297 ('', 'base', [],
1298 1298 _('a base changeset assumed to be available at the destination'),
1299 1299 _('REV')),
1300 1300 ('a', 'all', None, _('bundle all changesets in the repository')),
1301 1301 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1302 1302 ] + remoteopts,
1303 1303 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1304 1304 def bundle(ui, repo, fname, dest=None, **opts):
1305 1305 """create a changegroup file
1306 1306
1307 1307 Generate a changegroup file collecting changesets to be added
1308 1308 to a repository.
1309 1309
1310 1310 To create a bundle containing all changesets, use -a/--all
1311 1311 (or --base null). Otherwise, hg assumes the destination will have
1312 1312 all the nodes you specify with --base parameters. Otherwise, hg
1313 1313 will assume the repository has all the nodes in destination, or
1314 1314 default-push/default if no destination is specified.
1315 1315
1316 1316 You can change bundle format with the -t/--type option. You can
1317 1317 specify a compression, a bundle version or both using a dash
1318 1318 (comp-version). The available compression methods are: none, bzip2,
1319 1319 and gzip (by default, bundles are compressed using bzip2). The
1320 1320 available formats are: v1, v2 (default to most suitable).
1321 1321
1322 1322 The bundle file can then be transferred using conventional means
1323 1323 and applied to another repository with the unbundle or pull
1324 1324 command. This is useful when direct push and pull are not
1325 1325 available or when exporting an entire repository is undesirable.
1326 1326
1327 1327 Applying bundles preserves all changeset contents including
1328 1328 permissions, copy/rename information, and revision history.
1329 1329
1330 1330 Returns 0 on success, 1 if no changes found.
1331 1331 """
1332 1332 revs = None
1333 1333 if 'rev' in opts:
1334 1334 revs = scmutil.revrange(repo, opts['rev'])
1335 1335
1336 1336 bundletype = opts.get('type', 'bzip2').lower()
1337 1337 try:
1338 1338 bcompression, cgversion, params = exchange.parsebundlespec(
1339 1339 repo, bundletype, strict=False)
1340 1340 except error.UnsupportedBundleSpecification as e:
1341 1341 raise error.Abort(str(e),
1342 1342 hint=_('see "hg help bundle" for supported '
1343 1343 'values for --type'))
1344 1344
1345 1345 # Packed bundles are a pseudo bundle format for now.
1346 1346 if cgversion == 's1':
1347 1347 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1348 1348 hint=_('use "hg debugcreatestreamclonebundle"'))
1349 1349
1350 1350 if opts.get('all'):
1351 1351 if dest:
1352 1352 raise error.Abort(_("--all is incompatible with specifying "
1353 1353 "a destination"))
1354 1354 if opts.get('base'):
1355 1355 ui.warn(_("ignoring --base because --all was specified\n"))
1356 1356 base = ['null']
1357 1357 else:
1358 1358 base = scmutil.revrange(repo, opts.get('base'))
1359 1359 # TODO: get desired bundlecaps from command line.
1360 1360 bundlecaps = None
1361 1361 if base:
1362 1362 if dest:
1363 1363 raise error.Abort(_("--base is incompatible with specifying "
1364 1364 "a destination"))
1365 1365 common = [repo.lookup(rev) for rev in base]
1366 1366 heads = revs and map(repo.lookup, revs) or revs
1367 1367 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1368 1368 common=common, bundlecaps=bundlecaps,
1369 1369 version=cgversion)
1370 1370 outgoing = None
1371 1371 else:
1372 1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1373 1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1374 1374 other = hg.peer(repo, opts, dest)
1375 1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1376 1376 heads = revs and map(repo.lookup, revs) or revs
1377 1377 outgoing = discovery.findcommonoutgoing(repo, other,
1378 1378 onlyheads=heads,
1379 1379 force=opts.get('force'),
1380 1380 portable=True)
1381 1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1382 1382 bundlecaps, version=cgversion)
1383 1383 if not cg:
1384 1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1385 1385 return 1
1386 1386
1387 1387 if cgversion == '01': #bundle1
1388 1388 if bcompression is None:
1389 1389 bcompression = 'UN'
1390 1390 bversion = 'HG10' + bcompression
1391 1391 bcompression = None
1392 1392 else:
1393 1393 assert cgversion == '02'
1394 1394 bversion = 'HG20'
1395 1395
1396 1396
1397 1397 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1398 1398
1399 1399 @command('cat',
1400 1400 [('o', 'output', '',
1401 1401 _('print output to file with formatted name'), _('FORMAT')),
1402 1402 ('r', 'rev', '', _('print the given revision'), _('REV')),
1403 1403 ('', 'decode', None, _('apply any matching decode filter')),
1404 1404 ] + walkopts,
1405 1405 _('[OPTION]... FILE...'),
1406 1406 inferrepo=True)
1407 1407 def cat(ui, repo, file1, *pats, **opts):
1408 1408 """output the current or given revision of files
1409 1409
1410 1410 Print the specified files as they were at the given revision. If
1411 1411 no revision is given, the parent of the working directory is used.
1412 1412
1413 1413 Output may be to a file, in which case the name of the file is
1414 1414 given using a format string. The formatting rules as follows:
1415 1415
1416 1416 :``%%``: literal "%" character
1417 1417 :``%s``: basename of file being printed
1418 1418 :``%d``: dirname of file being printed, or '.' if in repository root
1419 1419 :``%p``: root-relative path name of file being printed
1420 1420 :``%H``: changeset hash (40 hexadecimal digits)
1421 1421 :``%R``: changeset revision number
1422 1422 :``%h``: short-form changeset hash (12 hexadecimal digits)
1423 1423 :``%r``: zero-padded changeset revision number
1424 1424 :``%b``: basename of the exporting repository
1425 1425
1426 1426 Returns 0 on success.
1427 1427 """
1428 1428 ctx = scmutil.revsingle(repo, opts.get('rev'))
1429 1429 m = scmutil.match(ctx, (file1,) + pats, opts)
1430 1430
1431 1431 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1432 1432
1433 1433 @command('^clone',
1434 1434 [('U', 'noupdate', None, _('the clone will include an empty working '
1435 1435 'directory (only a repository)')),
1436 1436 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1437 1437 _('REV')),
1438 1438 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1439 1439 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1440 1440 ('', 'pull', None, _('use pull protocol to copy metadata')),
1441 1441 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1442 1442 ] + remoteopts,
1443 1443 _('[OPTION]... SOURCE [DEST]'),
1444 1444 norepo=True)
1445 1445 def clone(ui, source, dest=None, **opts):
1446 1446 """make a copy of an existing repository
1447 1447
1448 1448 Create a copy of an existing repository in a new directory.
1449 1449
1450 1450 If no destination directory name is specified, it defaults to the
1451 1451 basename of the source.
1452 1452
1453 1453 The location of the source is added to the new repository's
1454 1454 ``.hg/hgrc`` file, as the default to be used for future pulls.
1455 1455
1456 1456 Only local paths and ``ssh://`` URLs are supported as
1457 1457 destinations. For ``ssh://`` destinations, no working directory or
1458 1458 ``.hg/hgrc`` will be created on the remote side.
1459 1459
1460 1460 If the source repository has a bookmark called '@' set, that
1461 1461 revision will be checked out in the new repository by default.
1462 1462
1463 1463 To check out a particular version, use -u/--update, or
1464 1464 -U/--noupdate to create a clone with no working directory.
1465 1465
1466 1466 To pull only a subset of changesets, specify one or more revisions
1467 1467 identifiers with -r/--rev or branches with -b/--branch. The
1468 1468 resulting clone will contain only the specified changesets and
1469 1469 their ancestors. These options (or 'clone src#rev dest') imply
1470 1470 --pull, even for local source repositories.
1471 1471
1472 1472 .. note::
1473 1473
1474 1474 Specifying a tag will include the tagged changeset but not the
1475 1475 changeset containing the tag.
1476 1476
1477 1477 .. container:: verbose
1478 1478
1479 1479 For efficiency, hardlinks are used for cloning whenever the
1480 1480 source and destination are on the same filesystem (note this
1481 1481 applies only to the repository data, not to the working
1482 1482 directory). Some filesystems, such as AFS, implement hardlinking
1483 1483 incorrectly, but do not report errors. In these cases, use the
1484 1484 --pull option to avoid hardlinking.
1485 1485
1486 1486 In some cases, you can clone repositories and the working
1487 1487 directory using full hardlinks with ::
1488 1488
1489 1489 $ cp -al REPO REPOCLONE
1490 1490
1491 1491 This is the fastest way to clone, but it is not always safe. The
1492 1492 operation is not atomic (making sure REPO is not modified during
1493 1493 the operation is up to you) and you have to make sure your
1494 1494 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1495 1495 so). Also, this is not compatible with certain extensions that
1496 1496 place their metadata under the .hg directory, such as mq.
1497 1497
1498 1498 Mercurial will update the working directory to the first applicable
1499 1499 revision from this list:
1500 1500
1501 1501 a) null if -U or the source repository has no changesets
1502 1502 b) if -u . and the source repository is local, the first parent of
1503 1503 the source repository's working directory
1504 1504 c) the changeset specified with -u (if a branch name, this means the
1505 1505 latest head of that branch)
1506 1506 d) the changeset specified with -r
1507 1507 e) the tipmost head specified with -b
1508 1508 f) the tipmost head specified with the url#branch source syntax
1509 1509 g) the revision marked with the '@' bookmark, if present
1510 1510 h) the tipmost head of the default branch
1511 1511 i) tip
1512 1512
1513 1513 Examples:
1514 1514
1515 1515 - clone a remote repository to a new directory named hg/::
1516 1516
1517 1517 hg clone http://selenic.com/hg
1518 1518
1519 1519 - create a lightweight local clone::
1520 1520
1521 1521 hg clone project/ project-feature/
1522 1522
1523 1523 - clone from an absolute path on an ssh server (note double-slash)::
1524 1524
1525 1525 hg clone ssh://user@server//home/projects/alpha/
1526 1526
1527 1527 - do a high-speed clone over a LAN while checking out a
1528 1528 specified version::
1529 1529
1530 1530 hg clone --uncompressed http://server/repo -u 1.5
1531 1531
1532 1532 - create a repository without changesets after a particular revision::
1533 1533
1534 1534 hg clone -r 04e544 experimental/ good/
1535 1535
1536 1536 - clone (and track) a particular named branch::
1537 1537
1538 1538 hg clone http://selenic.com/hg#stable
1539 1539
1540 1540 See :hg:`help urls` for details on specifying URLs.
1541 1541
1542 1542 Returns 0 on success.
1543 1543 """
1544 1544 if opts.get('noupdate') and opts.get('updaterev'):
1545 1545 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1546 1546
1547 1547 r = hg.clone(ui, opts, source, dest,
1548 1548 pull=opts.get('pull'),
1549 1549 stream=opts.get('uncompressed'),
1550 1550 rev=opts.get('rev'),
1551 1551 update=opts.get('updaterev') or not opts.get('noupdate'),
1552 1552 branch=opts.get('branch'),
1553 1553 shareopts=opts.get('shareopts'))
1554 1554
1555 1555 return r is None
1556 1556
1557 1557 @command('^commit|ci',
1558 1558 [('A', 'addremove', None,
1559 1559 _('mark new/missing files as added/removed before committing')),
1560 1560 ('', 'close-branch', None,
1561 1561 _('mark a branch head as closed')),
1562 1562 ('', 'amend', None, _('amend the parent of the working directory')),
1563 1563 ('s', 'secret', None, _('use the secret phase for committing')),
1564 1564 ('e', 'edit', None, _('invoke editor on commit messages')),
1565 1565 ('i', 'interactive', None, _('use interactive mode')),
1566 1566 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1567 1567 _('[OPTION]... [FILE]...'),
1568 1568 inferrepo=True)
1569 1569 def commit(ui, repo, *pats, **opts):
1570 1570 """commit the specified files or all outstanding changes
1571 1571
1572 1572 Commit changes to the given files into the repository. Unlike a
1573 1573 centralized SCM, this operation is a local operation. See
1574 1574 :hg:`push` for a way to actively distribute your changes.
1575 1575
1576 1576 If a list of files is omitted, all changes reported by :hg:`status`
1577 1577 will be committed.
1578 1578
1579 1579 If you are committing the result of a merge, do not provide any
1580 1580 filenames or -I/-X filters.
1581 1581
1582 1582 If no commit message is specified, Mercurial starts your
1583 1583 configured editor where you can enter a message. In case your
1584 1584 commit fails, you will find a backup of your message in
1585 1585 ``.hg/last-message.txt``.
1586 1586
1587 1587 The --close-branch flag can be used to mark the current branch
1588 1588 head closed. When all heads of a branch are closed, the branch
1589 1589 will be considered closed and no longer listed.
1590 1590
1591 1591 The --amend flag can be used to amend the parent of the
1592 1592 working directory with a new commit that contains the changes
1593 1593 in the parent in addition to those currently reported by :hg:`status`,
1594 1594 if there are any. The old commit is stored in a backup bundle in
1595 1595 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1596 1596 on how to restore it).
1597 1597
1598 1598 Message, user and date are taken from the amended commit unless
1599 1599 specified. When a message isn't specified on the command line,
1600 1600 the editor will open with the message of the amended commit.
1601 1601
1602 1602 It is not possible to amend public changesets (see :hg:`help phases`)
1603 1603 or changesets that have children.
1604 1604
1605 1605 See :hg:`help dates` for a list of formats valid for -d/--date.
1606 1606
1607 1607 Returns 0 on success, 1 if nothing changed.
1608 1608
1609 1609 .. container:: verbose
1610 1610
1611 1611 Examples:
1612 1612
1613 1613 - commit all files ending in .py::
1614 1614
1615 1615 hg commit --include "set:**.py"
1616 1616
1617 1617 - commit all non-binary files::
1618 1618
1619 1619 hg commit --exclude "set:binary()"
1620 1620
1621 1621 - amend the current commit and set the date to now::
1622 1622
1623 1623 hg commit --amend --date now
1624 1624 """
1625 1625 wlock = lock = None
1626 1626 try:
1627 1627 wlock = repo.wlock()
1628 1628 lock = repo.lock()
1629 1629 return _docommit(ui, repo, *pats, **opts)
1630 1630 finally:
1631 1631 release(lock, wlock)
1632 1632
1633 1633 def _docommit(ui, repo, *pats, **opts):
1634 1634 if opts.get('interactive'):
1635 1635 opts.pop('interactive')
1636 1636 cmdutil.dorecord(ui, repo, commit, None, False,
1637 1637 cmdutil.recordfilter, *pats, **opts)
1638 1638 return
1639 1639
1640 1640 if opts.get('subrepos'):
1641 1641 if opts.get('amend'):
1642 1642 raise error.Abort(_('cannot amend with --subrepos'))
1643 1643 # Let --subrepos on the command line override config setting.
1644 1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1645 1645
1646 1646 cmdutil.checkunfinished(repo, commit=True)
1647 1647
1648 1648 branch = repo[None].branch()
1649 1649 bheads = repo.branchheads(branch)
1650 1650
1651 1651 extra = {}
1652 1652 if opts.get('close_branch'):
1653 1653 extra['close'] = 1
1654 1654
1655 1655 if not bheads:
1656 1656 raise error.Abort(_('can only close branch heads'))
1657 1657 elif opts.get('amend'):
1658 1658 if repo[None].parents()[0].p1().branch() != branch and \
1659 1659 repo[None].parents()[0].p2().branch() != branch:
1660 1660 raise error.Abort(_('can only close branch heads'))
1661 1661
1662 1662 if opts.get('amend'):
1663 1663 if ui.configbool('ui', 'commitsubrepos'):
1664 1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1665 1665
1666 1666 old = repo['.']
1667 1667 if not old.mutable():
1668 1668 raise error.Abort(_('cannot amend public changesets'))
1669 1669 if len(repo[None].parents()) > 1:
1670 1670 raise error.Abort(_('cannot amend while merging'))
1671 1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1672 1672 if not allowunstable and old.children():
1673 1673 raise error.Abort(_('cannot amend changeset with children'))
1674 1674
1675 1675 newextra = extra.copy()
1676 1676 newextra['branch'] = branch
1677 1677 extra = newextra
1678 1678 # commitfunc is used only for temporary amend commit by cmdutil.amend
1679 1679 def commitfunc(ui, repo, message, match, opts):
1680 1680 return repo.commit(message,
1681 1681 opts.get('user') or old.user(),
1682 1682 opts.get('date') or old.date(),
1683 1683 match,
1684 1684 extra=extra)
1685 1685
1686 1686 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1687 1687 if node == old.node():
1688 1688 ui.status(_("nothing changed\n"))
1689 1689 return 1
1690 1690 else:
1691 1691 def commitfunc(ui, repo, message, match, opts):
1692 1692 backup = ui.backupconfig('phases', 'new-commit')
1693 1693 baseui = repo.baseui
1694 1694 basebackup = baseui.backupconfig('phases', 'new-commit')
1695 1695 try:
1696 1696 if opts.get('secret'):
1697 1697 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1698 1698 # Propagate to subrepos
1699 1699 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1700 1700
1701 1701 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1702 1702 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1703 1703 return repo.commit(message, opts.get('user'), opts.get('date'),
1704 1704 match,
1705 1705 editor=editor,
1706 1706 extra=extra)
1707 1707 finally:
1708 1708 ui.restoreconfig(backup)
1709 1709 repo.baseui.restoreconfig(basebackup)
1710 1710
1711 1711
1712 1712 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1713 1713
1714 1714 if not node:
1715 1715 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1716 1716 if stat[3]:
1717 1717 ui.status(_("nothing changed (%d missing files, see "
1718 1718 "'hg status')\n") % len(stat[3]))
1719 1719 else:
1720 1720 ui.status(_("nothing changed\n"))
1721 1721 return 1
1722 1722
1723 1723 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1724 1724
1725 1725 @command('config|showconfig|debugconfig',
1726 1726 [('u', 'untrusted', None, _('show untrusted configuration options')),
1727 1727 ('e', 'edit', None, _('edit user config')),
1728 1728 ('l', 'local', None, _('edit repository config')),
1729 1729 ('g', 'global', None, _('edit global config'))],
1730 1730 _('[-u] [NAME]...'),
1731 1731 optionalrepo=True)
1732 1732 def config(ui, repo, *values, **opts):
1733 1733 """show combined config settings from all hgrc files
1734 1734
1735 1735 With no arguments, print names and values of all config items.
1736 1736
1737 1737 With one argument of the form section.name, print just the value
1738 1738 of that config item.
1739 1739
1740 1740 With multiple arguments, print names and values of all config
1741 1741 items with matching section names.
1742 1742
1743 1743 With --edit, start an editor on the user-level config file. With
1744 1744 --global, edit the system-wide config file. With --local, edit the
1745 1745 repository-level config file.
1746 1746
1747 1747 With --debug, the source (filename and line number) is printed
1748 1748 for each config item.
1749 1749
1750 1750 See :hg:`help config` for more information about config files.
1751 1751
1752 1752 Returns 0 on success, 1 if NAME does not exist.
1753 1753
1754 1754 """
1755 1755
1756 1756 if opts.get('edit') or opts.get('local') or opts.get('global'):
1757 1757 if opts.get('local') and opts.get('global'):
1758 1758 raise error.Abort(_("can't use --local and --global together"))
1759 1759
1760 1760 if opts.get('local'):
1761 1761 if not repo:
1762 1762 raise error.Abort(_("can't use --local outside a repository"))
1763 1763 paths = [repo.join('hgrc')]
1764 1764 elif opts.get('global'):
1765 1765 paths = scmutil.systemrcpath()
1766 1766 else:
1767 1767 paths = scmutil.userrcpath()
1768 1768
1769 1769 for f in paths:
1770 1770 if os.path.exists(f):
1771 1771 break
1772 1772 else:
1773 1773 if opts.get('global'):
1774 1774 samplehgrc = uimod.samplehgrcs['global']
1775 1775 elif opts.get('local'):
1776 1776 samplehgrc = uimod.samplehgrcs['local']
1777 1777 else:
1778 1778 samplehgrc = uimod.samplehgrcs['user']
1779 1779
1780 1780 f = paths[0]
1781 1781 fp = open(f, "w")
1782 1782 fp.write(samplehgrc)
1783 1783 fp.close()
1784 1784
1785 1785 editor = ui.geteditor()
1786 1786 ui.system("%s \"%s\"" % (editor, f),
1787 1787 onerr=error.Abort, errprefix=_("edit failed"))
1788 1788 return
1789 1789
1790 1790 for f in scmutil.rcpath():
1791 1791 ui.debug('read config from: %s\n' % f)
1792 1792 untrusted = bool(opts.get('untrusted'))
1793 1793 if values:
1794 1794 sections = [v for v in values if '.' not in v]
1795 1795 items = [v for v in values if '.' in v]
1796 1796 if len(items) > 1 or items and sections:
1797 1797 raise error.Abort(_('only one config item permitted'))
1798 1798 matched = False
1799 1799 for section, name, value in ui.walkconfig(untrusted=untrusted):
1800 1800 value = str(value).replace('\n', '\\n')
1801 1801 sectname = section + '.' + name
1802 1802 if values:
1803 1803 for v in values:
1804 1804 if v == section:
1805 1805 ui.debug('%s: ' %
1806 1806 ui.configsource(section, name, untrusted))
1807 1807 ui.write('%s=%s\n' % (sectname, value))
1808 1808 matched = True
1809 1809 elif v == sectname:
1810 1810 ui.debug('%s: ' %
1811 1811 ui.configsource(section, name, untrusted))
1812 1812 ui.write(value, '\n')
1813 1813 matched = True
1814 1814 else:
1815 1815 ui.debug('%s: ' %
1816 1816 ui.configsource(section, name, untrusted))
1817 1817 ui.write('%s=%s\n' % (sectname, value))
1818 1818 matched = True
1819 1819 if matched:
1820 1820 return 0
1821 1821 return 1
1822 1822
1823 1823 @command('copy|cp',
1824 1824 [('A', 'after', None, _('record a copy that has already occurred')),
1825 1825 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1826 1826 ] + walkopts + dryrunopts,
1827 1827 _('[OPTION]... [SOURCE]... DEST'))
1828 1828 def copy(ui, repo, *pats, **opts):
1829 1829 """mark files as copied for the next commit
1830 1830
1831 1831 Mark dest as having copies of source files. If dest is a
1832 1832 directory, copies are put in that directory. If dest is a file,
1833 1833 the source must be a single file.
1834 1834
1835 1835 By default, this command copies the contents of files as they
1836 1836 exist in the working directory. If invoked with -A/--after, the
1837 1837 operation is recorded, but no copying is performed.
1838 1838
1839 1839 This command takes effect with the next commit. To undo a copy
1840 1840 before that, see :hg:`revert`.
1841 1841
1842 1842 Returns 0 on success, 1 if errors are encountered.
1843 1843 """
1844 1844 wlock = repo.wlock(False)
1845 1845 try:
1846 1846 return cmdutil.copy(ui, repo, pats, opts)
1847 1847 finally:
1848 1848 wlock.release()
1849 1849
1850 1850 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1851 1851 def debugancestor(ui, repo, *args):
1852 1852 """find the ancestor revision of two revisions in a given index"""
1853 1853 if len(args) == 3:
1854 1854 index, rev1, rev2 = args
1855 1855 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1856 1856 lookup = r.lookup
1857 1857 elif len(args) == 2:
1858 1858 if not repo:
1859 1859 raise error.Abort(_("there is no Mercurial repository here "
1860 1860 "(.hg not found)"))
1861 1861 rev1, rev2 = args
1862 1862 r = repo.changelog
1863 1863 lookup = repo.lookup
1864 1864 else:
1865 1865 raise error.Abort(_('either two or three arguments required'))
1866 1866 a = r.ancestor(lookup(rev1), lookup(rev2))
1867 1867 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1868 1868
1869 1869 @command('debugbuilddag',
1870 1870 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1871 1871 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1872 1872 ('n', 'new-file', None, _('add new file at each rev'))],
1873 1873 _('[OPTION]... [TEXT]'))
1874 1874 def debugbuilddag(ui, repo, text=None,
1875 1875 mergeable_file=False,
1876 1876 overwritten_file=False,
1877 1877 new_file=False):
1878 1878 """builds a repo with a given DAG from scratch in the current empty repo
1879 1879
1880 1880 The description of the DAG is read from stdin if not given on the
1881 1881 command line.
1882 1882
1883 1883 Elements:
1884 1884
1885 1885 - "+n" is a linear run of n nodes based on the current default parent
1886 1886 - "." is a single node based on the current default parent
1887 1887 - "$" resets the default parent to null (implied at the start);
1888 1888 otherwise the default parent is always the last node created
1889 1889 - "<p" sets the default parent to the backref p
1890 1890 - "*p" is a fork at parent p, which is a backref
1891 1891 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1892 1892 - "/p2" is a merge of the preceding node and p2
1893 1893 - ":tag" defines a local tag for the preceding node
1894 1894 - "@branch" sets the named branch for subsequent nodes
1895 1895 - "#...\\n" is a comment up to the end of the line
1896 1896
1897 1897 Whitespace between the above elements is ignored.
1898 1898
1899 1899 A backref is either
1900 1900
1901 1901 - a number n, which references the node curr-n, where curr is the current
1902 1902 node, or
1903 1903 - the name of a local tag you placed earlier using ":tag", or
1904 1904 - empty to denote the default parent.
1905 1905
1906 1906 All string valued-elements are either strictly alphanumeric, or must
1907 1907 be enclosed in double quotes ("..."), with "\\" as escape character.
1908 1908 """
1909 1909
1910 1910 if text is None:
1911 1911 ui.status(_("reading DAG from stdin\n"))
1912 1912 text = ui.fin.read()
1913 1913
1914 1914 cl = repo.changelog
1915 1915 if len(cl) > 0:
1916 1916 raise error.Abort(_('repository is not empty'))
1917 1917
1918 1918 # determine number of revs in DAG
1919 1919 total = 0
1920 1920 for type, data in dagparser.parsedag(text):
1921 1921 if type == 'n':
1922 1922 total += 1
1923 1923
1924 1924 if mergeable_file:
1925 1925 linesperrev = 2
1926 1926 # make a file with k lines per rev
1927 1927 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1928 1928 initialmergedlines.append("")
1929 1929
1930 1930 tags = []
1931 1931
1932 1932 lock = tr = None
1933 1933 try:
1934 1934 lock = repo.lock()
1935 1935 tr = repo.transaction("builddag")
1936 1936
1937 1937 at = -1
1938 1938 atbranch = 'default'
1939 1939 nodeids = []
1940 1940 id = 0
1941 1941 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1942 1942 for type, data in dagparser.parsedag(text):
1943 1943 if type == 'n':
1944 1944 ui.note(('node %s\n' % str(data)))
1945 1945 id, ps = data
1946 1946
1947 1947 files = []
1948 1948 fctxs = {}
1949 1949
1950 1950 p2 = None
1951 1951 if mergeable_file:
1952 1952 fn = "mf"
1953 1953 p1 = repo[ps[0]]
1954 1954 if len(ps) > 1:
1955 1955 p2 = repo[ps[1]]
1956 1956 pa = p1.ancestor(p2)
1957 1957 base, local, other = [x[fn].data() for x in (pa, p1,
1958 1958 p2)]
1959 1959 m3 = simplemerge.Merge3Text(base, local, other)
1960 1960 ml = [l.strip() for l in m3.merge_lines()]
1961 1961 ml.append("")
1962 1962 elif at > 0:
1963 1963 ml = p1[fn].data().split("\n")
1964 1964 else:
1965 1965 ml = initialmergedlines
1966 1966 ml[id * linesperrev] += " r%i" % id
1967 1967 mergedtext = "\n".join(ml)
1968 1968 files.append(fn)
1969 1969 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1970 1970
1971 1971 if overwritten_file:
1972 1972 fn = "of"
1973 1973 files.append(fn)
1974 1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1975 1975
1976 1976 if new_file:
1977 1977 fn = "nf%i" % id
1978 1978 files.append(fn)
1979 1979 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1980 1980 if len(ps) > 1:
1981 1981 if not p2:
1982 1982 p2 = repo[ps[1]]
1983 1983 for fn in p2:
1984 1984 if fn.startswith("nf"):
1985 1985 files.append(fn)
1986 1986 fctxs[fn] = p2[fn]
1987 1987
1988 1988 def fctxfn(repo, cx, path):
1989 1989 return fctxs.get(path)
1990 1990
1991 1991 if len(ps) == 0 or ps[0] < 0:
1992 1992 pars = [None, None]
1993 1993 elif len(ps) == 1:
1994 1994 pars = [nodeids[ps[0]], None]
1995 1995 else:
1996 1996 pars = [nodeids[p] for p in ps]
1997 1997 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1998 1998 date=(id, 0),
1999 1999 user="debugbuilddag",
2000 2000 extra={'branch': atbranch})
2001 2001 nodeid = repo.commitctx(cx)
2002 2002 nodeids.append(nodeid)
2003 2003 at = id
2004 2004 elif type == 'l':
2005 2005 id, name = data
2006 2006 ui.note(('tag %s\n' % name))
2007 2007 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2008 2008 elif type == 'a':
2009 2009 ui.note(('branch %s\n' % data))
2010 2010 atbranch = data
2011 2011 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2012 2012 tr.close()
2013 2013
2014 2014 if tags:
2015 2015 repo.vfs.write("localtags", "".join(tags))
2016 2016 finally:
2017 2017 ui.progress(_('building'), None)
2018 2018 release(tr, lock)
2019 2019
2020 2020 @command('debugbundle',
2021 2021 [('a', 'all', None, _('show all details'))],
2022 2022 _('FILE'),
2023 2023 norepo=True)
2024 2024 def debugbundle(ui, bundlepath, all=None, **opts):
2025 2025 """lists the contents of a bundle"""
2026 2026 f = hg.openpath(ui, bundlepath)
2027 2027 try:
2028 2028 gen = exchange.readbundle(ui, f, bundlepath)
2029 2029 if isinstance(gen, bundle2.unbundle20):
2030 2030 return _debugbundle2(ui, gen, all=all, **opts)
2031 2031 if all:
2032 2032 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2033 2033
2034 2034 def showchunks(named):
2035 2035 ui.write("\n%s\n" % named)
2036 2036 chain = None
2037 2037 while True:
2038 2038 chunkdata = gen.deltachunk(chain)
2039 2039 if not chunkdata:
2040 2040 break
2041 2041 node = chunkdata['node']
2042 2042 p1 = chunkdata['p1']
2043 2043 p2 = chunkdata['p2']
2044 2044 cs = chunkdata['cs']
2045 2045 deltabase = chunkdata['deltabase']
2046 2046 delta = chunkdata['delta']
2047 2047 ui.write("%s %s %s %s %s %s\n" %
2048 2048 (hex(node), hex(p1), hex(p2),
2049 2049 hex(cs), hex(deltabase), len(delta)))
2050 2050 chain = node
2051 2051
2052 2052 chunkdata = gen.changelogheader()
2053 2053 showchunks("changelog")
2054 2054 chunkdata = gen.manifestheader()
2055 2055 showchunks("manifest")
2056 2056 while True:
2057 2057 chunkdata = gen.filelogheader()
2058 2058 if not chunkdata:
2059 2059 break
2060 2060 fname = chunkdata['filename']
2061 2061 showchunks(fname)
2062 2062 else:
2063 2063 if isinstance(gen, bundle2.unbundle20):
2064 2064 raise error.Abort(_('use debugbundle2 for this file'))
2065 2065 chunkdata = gen.changelogheader()
2066 2066 chain = None
2067 2067 while True:
2068 2068 chunkdata = gen.deltachunk(chain)
2069 2069 if not chunkdata:
2070 2070 break
2071 2071 node = chunkdata['node']
2072 2072 ui.write("%s\n" % hex(node))
2073 2073 chain = node
2074 2074 finally:
2075 2075 f.close()
2076 2076
2077 2077 def _debugbundle2(ui, gen, **opts):
2078 2078 """lists the contents of a bundle2"""
2079 2079 if not isinstance(gen, bundle2.unbundle20):
2080 2080 raise error.Abort(_('not a bundle2 file'))
2081 2081 ui.write(('Stream params: %s\n' % repr(gen.params)))
2082 2082 for part in gen.iterparts():
2083 2083 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2084 2084 if part.type == 'changegroup':
2085 2085 version = part.params.get('version', '01')
2086 2086 cg = changegroup.packermap[version][1](part, 'UN')
2087 2087 chunkdata = cg.changelogheader()
2088 2088 chain = None
2089 2089 while True:
2090 2090 chunkdata = cg.deltachunk(chain)
2091 2091 if not chunkdata:
2092 2092 break
2093 2093 node = chunkdata['node']
2094 2094 ui.write(" %s\n" % hex(node))
2095 2095 chain = node
2096 2096
2097 2097 @command('debugcreatestreamclonebundle', [], 'FILE')
2098 2098 def debugcreatestreamclonebundle(ui, repo, fname):
2099 2099 """create a stream clone bundle file
2100 2100
2101 2101 Stream bundles are special bundles that are essentially archives of
2102 2102 revlog files. They are commonly used for cloning very quickly.
2103 2103 """
2104 2104 requirements, gen = streamclone.generatebundlev1(repo)
2105 2105 changegroup.writechunks(ui, gen, fname)
2106 2106
2107 2107 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2108 2108
2109 2109 @command('debugapplystreamclonebundle', [], 'FILE')
2110 2110 def debugapplystreamclonebundle(ui, repo, fname):
2111 2111 """apply a stream clone bundle file"""
2112 2112 f = hg.openpath(ui, fname)
2113 2113 gen = exchange.readbundle(ui, f, fname)
2114 2114 gen.apply(repo)
2115 2115
2116 2116 @command('debugcheckstate', [], '')
2117 2117 def debugcheckstate(ui, repo):
2118 2118 """validate the correctness of the current dirstate"""
2119 2119 parent1, parent2 = repo.dirstate.parents()
2120 2120 m1 = repo[parent1].manifest()
2121 2121 m2 = repo[parent2].manifest()
2122 2122 errors = 0
2123 2123 for f in repo.dirstate:
2124 2124 state = repo.dirstate[f]
2125 2125 if state in "nr" and f not in m1:
2126 2126 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2127 2127 errors += 1
2128 2128 if state in "a" and f in m1:
2129 2129 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2130 2130 errors += 1
2131 2131 if state in "m" and f not in m1 and f not in m2:
2132 2132 ui.warn(_("%s in state %s, but not in either manifest\n") %
2133 2133 (f, state))
2134 2134 errors += 1
2135 2135 for f in m1:
2136 2136 state = repo.dirstate[f]
2137 2137 if state not in "nrm":
2138 2138 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2139 2139 errors += 1
2140 2140 if errors:
2141 2141 error = _(".hg/dirstate inconsistent with current parent's manifest")
2142 2142 raise error.Abort(error)
2143 2143
2144 2144 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2145 2145 def debugcommands(ui, cmd='', *args):
2146 2146 """list all available commands and options"""
2147 2147 for cmd, vals in sorted(table.iteritems()):
2148 2148 cmd = cmd.split('|')[0].strip('^')
2149 2149 opts = ', '.join([i[1] for i in vals[1]])
2150 2150 ui.write('%s: %s\n' % (cmd, opts))
2151 2151
2152 2152 @command('debugcomplete',
2153 2153 [('o', 'options', None, _('show the command options'))],
2154 2154 _('[-o] CMD'),
2155 2155 norepo=True)
2156 2156 def debugcomplete(ui, cmd='', **opts):
2157 2157 """returns the completion list associated with the given command"""
2158 2158
2159 2159 if opts.get('options'):
2160 2160 options = []
2161 2161 otables = [globalopts]
2162 2162 if cmd:
2163 2163 aliases, entry = cmdutil.findcmd(cmd, table, False)
2164 2164 otables.append(entry[1])
2165 2165 for t in otables:
2166 2166 for o in t:
2167 2167 if "(DEPRECATED)" in o[3]:
2168 2168 continue
2169 2169 if o[0]:
2170 2170 options.append('-%s' % o[0])
2171 2171 options.append('--%s' % o[1])
2172 2172 ui.write("%s\n" % "\n".join(options))
2173 2173 return
2174 2174
2175 2175 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2176 2176 if ui.verbose:
2177 2177 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2178 2178 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2179 2179
2180 2180 @command('debugdag',
2181 2181 [('t', 'tags', None, _('use tags as labels')),
2182 2182 ('b', 'branches', None, _('annotate with branch names')),
2183 2183 ('', 'dots', None, _('use dots for runs')),
2184 2184 ('s', 'spaces', None, _('separate elements by spaces'))],
2185 2185 _('[OPTION]... [FILE [REV]...]'),
2186 2186 optionalrepo=True)
2187 2187 def debugdag(ui, repo, file_=None, *revs, **opts):
2188 2188 """format the changelog or an index DAG as a concise textual description
2189 2189
2190 2190 If you pass a revlog index, the revlog's DAG is emitted. If you list
2191 2191 revision numbers, they get labeled in the output as rN.
2192 2192
2193 2193 Otherwise, the changelog DAG of the current repo is emitted.
2194 2194 """
2195 2195 spaces = opts.get('spaces')
2196 2196 dots = opts.get('dots')
2197 2197 if file_:
2198 2198 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2199 2199 revs = set((int(r) for r in revs))
2200 2200 def events():
2201 2201 for r in rlog:
2202 2202 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2203 2203 if p != -1))
2204 2204 if r in revs:
2205 2205 yield 'l', (r, "r%i" % r)
2206 2206 elif repo:
2207 2207 cl = repo.changelog
2208 2208 tags = opts.get('tags')
2209 2209 branches = opts.get('branches')
2210 2210 if tags:
2211 2211 labels = {}
2212 2212 for l, n in repo.tags().items():
2213 2213 labels.setdefault(cl.rev(n), []).append(l)
2214 2214 def events():
2215 2215 b = "default"
2216 2216 for r in cl:
2217 2217 if branches:
2218 2218 newb = cl.read(cl.node(r))[5]['branch']
2219 2219 if newb != b:
2220 2220 yield 'a', newb
2221 2221 b = newb
2222 2222 yield 'n', (r, list(p for p in cl.parentrevs(r)
2223 2223 if p != -1))
2224 2224 if tags:
2225 2225 ls = labels.get(r)
2226 2226 if ls:
2227 2227 for l in ls:
2228 2228 yield 'l', (r, l)
2229 2229 else:
2230 2230 raise error.Abort(_('need repo for changelog dag'))
2231 2231
2232 2232 for line in dagparser.dagtextlines(events(),
2233 2233 addspaces=spaces,
2234 2234 wraplabels=True,
2235 2235 wrapannotations=True,
2236 2236 wrapnonlinear=dots,
2237 2237 usedots=dots,
2238 2238 maxlinewidth=70):
2239 2239 ui.write(line)
2240 2240 ui.write("\n")
2241 2241
2242 2242 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2243 2243 def debugdata(ui, repo, file_, rev=None, **opts):
2244 2244 """dump the contents of a data file revision"""
2245 2245 if opts.get('changelog') or opts.get('manifest'):
2246 2246 file_, rev = None, file_
2247 2247 elif rev is None:
2248 2248 raise error.CommandError('debugdata', _('invalid arguments'))
2249 2249 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2250 2250 try:
2251 2251 ui.write(r.revision(r.lookup(rev)))
2252 2252 except KeyError:
2253 2253 raise error.Abort(_('invalid revision identifier %s') % rev)
2254 2254
2255 2255 @command('debugdate',
2256 2256 [('e', 'extended', None, _('try extended date formats'))],
2257 2257 _('[-e] DATE [RANGE]'),
2258 2258 norepo=True, optionalrepo=True)
2259 2259 def debugdate(ui, date, range=None, **opts):
2260 2260 """parse and display a date"""
2261 2261 if opts["extended"]:
2262 2262 d = util.parsedate(date, util.extendeddateformats)
2263 2263 else:
2264 2264 d = util.parsedate(date)
2265 2265 ui.write(("internal: %s %s\n") % d)
2266 2266 ui.write(("standard: %s\n") % util.datestr(d))
2267 2267 if range:
2268 2268 m = util.matchdate(range)
2269 2269 ui.write(("match: %s\n") % m(d[0]))
2270 2270
2271 2271 @command('debugdiscovery',
2272 2272 [('', 'old', None, _('use old-style discovery')),
2273 2273 ('', 'nonheads', None,
2274 2274 _('use old-style discovery with non-heads included')),
2275 2275 ] + remoteopts,
2276 2276 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2277 2277 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2278 2278 """runs the changeset discovery protocol in isolation"""
2279 2279 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2280 2280 opts.get('branch'))
2281 2281 remote = hg.peer(repo, opts, remoteurl)
2282 2282 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2283 2283
2284 2284 # make sure tests are repeatable
2285 2285 random.seed(12323)
2286 2286
2287 2287 def doit(localheads, remoteheads, remote=remote):
2288 2288 if opts.get('old'):
2289 2289 if localheads:
2290 2290 raise error.Abort('cannot use localheads with old style '
2291 2291 'discovery')
2292 2292 if not util.safehasattr(remote, 'branches'):
2293 2293 # enable in-client legacy support
2294 2294 remote = localrepo.locallegacypeer(remote.local())
2295 2295 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2296 2296 force=True)
2297 2297 common = set(common)
2298 2298 if not opts.get('nonheads'):
2299 2299 ui.write(("unpruned common: %s\n") %
2300 2300 " ".join(sorted(short(n) for n in common)))
2301 2301 dag = dagutil.revlogdag(repo.changelog)
2302 2302 all = dag.ancestorset(dag.internalizeall(common))
2303 2303 common = dag.externalizeall(dag.headsetofconnecteds(all))
2304 2304 else:
2305 2305 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2306 2306 common = set(common)
2307 2307 rheads = set(hds)
2308 2308 lheads = set(repo.heads())
2309 2309 ui.write(("common heads: %s\n") %
2310 2310 " ".join(sorted(short(n) for n in common)))
2311 2311 if lheads <= common:
2312 2312 ui.write(("local is subset\n"))
2313 2313 elif rheads <= common:
2314 2314 ui.write(("remote is subset\n"))
2315 2315
2316 2316 serverlogs = opts.get('serverlog')
2317 2317 if serverlogs:
2318 2318 for filename in serverlogs:
2319 2319 logfile = open(filename, 'r')
2320 2320 try:
2321 2321 line = logfile.readline()
2322 2322 while line:
2323 2323 parts = line.strip().split(';')
2324 2324 op = parts[1]
2325 2325 if op == 'cg':
2326 2326 pass
2327 2327 elif op == 'cgss':
2328 2328 doit(parts[2].split(' '), parts[3].split(' '))
2329 2329 elif op == 'unb':
2330 2330 doit(parts[3].split(' '), parts[2].split(' '))
2331 2331 line = logfile.readline()
2332 2332 finally:
2333 2333 logfile.close()
2334 2334
2335 2335 else:
2336 2336 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2337 2337 opts.get('remote_head'))
2338 2338 localrevs = opts.get('local_head')
2339 2339 doit(localrevs, remoterevs)
2340 2340
2341 2341 @command('debugextensions', formatteropts, [], norepo=True)
2342 2342 def debugextensions(ui, **opts):
2343 2343 '''show information about active extensions'''
2344 2344 exts = extensions.extensions(ui)
2345 2345 fm = ui.formatter('debugextensions', opts)
2346 2346 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2347 2347 extsource = extmod.__file__
2348 2348 exttestedwith = getattr(extmod, 'testedwith', None)
2349 2349 if exttestedwith is not None:
2350 2350 exttestedwith = exttestedwith.split()
2351 2351 extbuglink = getattr(extmod, 'buglink', None)
2352 2352
2353 2353 fm.startitem()
2354 2354
2355 2355 if ui.quiet or ui.verbose:
2356 2356 fm.write('name', '%s\n', extname)
2357 2357 else:
2358 2358 fm.write('name', '%s', extname)
2359 2359 if not exttestedwith:
2360 2360 fm.plain(_(' (untested!)\n'))
2361 2361 else:
2362 2362 if exttestedwith == ['internal'] or \
2363 2363 util.version() in exttestedwith:
2364 2364 fm.plain('\n')
2365 2365 else:
2366 2366 lasttestedversion = exttestedwith[-1]
2367 2367 fm.plain(' (%s!)\n' % lasttestedversion)
2368 2368
2369 2369 fm.condwrite(ui.verbose and extsource, 'source',
2370 2370 _(' location: %s\n'), extsource or "")
2371 2371
2372 2372 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2373 2373 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2374 2374
2375 2375 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2376 2376 _(' bug reporting: %s\n'), extbuglink or "")
2377 2377
2378 2378 fm.end()
2379 2379
2380 2380 @command('debugfileset',
2381 2381 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2382 2382 _('[-r REV] FILESPEC'))
2383 2383 def debugfileset(ui, repo, expr, **opts):
2384 2384 '''parse and apply a fileset specification'''
2385 2385 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2386 2386 if ui.verbose:
2387 2387 tree = fileset.parse(expr)
2388 2388 ui.note(fileset.prettyformat(tree), "\n")
2389 2389
2390 2390 for f in ctx.getfileset(expr):
2391 2391 ui.write("%s\n" % f)
2392 2392
2393 2393 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2394 2394 def debugfsinfo(ui, path="."):
2395 2395 """show information detected about current filesystem"""
2396 2396 util.writefile('.debugfsinfo', '')
2397 2397 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2398 2398 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2399 2399 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2400 2400 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2401 2401 and 'yes' or 'no'))
2402 2402 os.unlink('.debugfsinfo')
2403 2403
2404 2404 @command('debuggetbundle',
2405 2405 [('H', 'head', [], _('id of head node'), _('ID')),
2406 2406 ('C', 'common', [], _('id of common node'), _('ID')),
2407 2407 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2408 2408 _('REPO FILE [-H|-C ID]...'),
2409 2409 norepo=True)
2410 2410 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2411 2411 """retrieves a bundle from a repo
2412 2412
2413 2413 Every ID must be a full-length hex node id string. Saves the bundle to the
2414 2414 given file.
2415 2415 """
2416 2416 repo = hg.peer(ui, opts, repopath)
2417 2417 if not repo.capable('getbundle'):
2418 2418 raise error.Abort("getbundle() not supported by target repository")
2419 2419 args = {}
2420 2420 if common:
2421 2421 args['common'] = [bin(s) for s in common]
2422 2422 if head:
2423 2423 args['heads'] = [bin(s) for s in head]
2424 2424 # TODO: get desired bundlecaps from command line.
2425 2425 args['bundlecaps'] = None
2426 2426 bundle = repo.getbundle('debug', **args)
2427 2427
2428 2428 bundletype = opts.get('type', 'bzip2').lower()
2429 2429 btypes = {'none': 'HG10UN',
2430 2430 'bzip2': 'HG10BZ',
2431 2431 'gzip': 'HG10GZ',
2432 2432 'bundle2': 'HG20'}
2433 2433 bundletype = btypes.get(bundletype)
2434 2434 if bundletype not in changegroup.bundletypes:
2435 2435 raise error.Abort(_('unknown bundle type specified with --type'))
2436 2436 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2437 2437
2438 @command('debugignore', [], '')
2439 def debugignore(ui, repo, *values, **opts):
2440 """display the combined ignore pattern"""
2438 @command('debugignore', [], '[FILE]')
2439 def debugignore(ui, repo, *files, **opts):
2440 """display the combined ignore pattern and information about ignored files
2441
2442 With no argument display the combined ignore pattern.
2443
2444 Given space separated file names, shows if the given file is ignored.
2445 """
2441 2446 ignore = repo.dirstate._ignore
2442 includepat = getattr(ignore, 'includepat', None)
2443 if includepat is not None:
2444 ui.write("%s\n" % includepat)
2447 if not files:
2448 # Show all the patterns
2449 includepat = getattr(ignore, 'includepat', None)
2450 if includepat is not None:
2451 ui.write("%s\n" % includepat)
2452 else:
2453 raise error.Abort(_("no ignore patterns found"))
2445 2454 else:
2446 raise error.Abort(_("no ignore patterns found"))
2455 for f in files:
2456 ignored = None
2457 if f != '.':
2458 if ignore(f):
2459 ignored = f
2460 else:
2461 for p in util.finddirs(f):
2462 if ignore(p):
2463 ignored = p
2464 break
2465 if ignored:
2466 if ignored == f:
2467 ui.write("%s is ignored\n" % f)
2468 else:
2469 ui.write("%s is ignored because of containing folder %s\n"
2470 % (f, ignored))
2471 else:
2472 ui.write("%s is not ignored\n" % f)
2447 2473
2448 2474 @command('debugindex', debugrevlogopts +
2449 2475 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2450 2476 _('[-f FORMAT] -c|-m|FILE'),
2451 2477 optionalrepo=True)
2452 2478 def debugindex(ui, repo, file_=None, **opts):
2453 2479 """dump the contents of an index file"""
2454 2480 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2455 2481 format = opts.get('format', 0)
2456 2482 if format not in (0, 1):
2457 2483 raise error.Abort(_("unknown format %d") % format)
2458 2484
2459 2485 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2460 2486 if generaldelta:
2461 2487 basehdr = ' delta'
2462 2488 else:
2463 2489 basehdr = ' base'
2464 2490
2465 2491 if ui.debugflag:
2466 2492 shortfn = hex
2467 2493 else:
2468 2494 shortfn = short
2469 2495
2470 2496 # There might not be anything in r, so have a sane default
2471 2497 idlen = 12
2472 2498 for i in r:
2473 2499 idlen = len(shortfn(r.node(i)))
2474 2500 break
2475 2501
2476 2502 if format == 0:
2477 2503 ui.write(" rev offset length " + basehdr + " linkrev"
2478 2504 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2479 2505 elif format == 1:
2480 2506 ui.write(" rev flag offset length"
2481 2507 " size " + basehdr + " link p1 p2"
2482 2508 " %s\n" % "nodeid".rjust(idlen))
2483 2509
2484 2510 for i in r:
2485 2511 node = r.node(i)
2486 2512 if generaldelta:
2487 2513 base = r.deltaparent(i)
2488 2514 else:
2489 2515 base = r.chainbase(i)
2490 2516 if format == 0:
2491 2517 try:
2492 2518 pp = r.parents(node)
2493 2519 except Exception:
2494 2520 pp = [nullid, nullid]
2495 2521 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2496 2522 i, r.start(i), r.length(i), base, r.linkrev(i),
2497 2523 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2498 2524 elif format == 1:
2499 2525 pr = r.parentrevs(i)
2500 2526 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2501 2527 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2502 2528 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2503 2529
2504 2530 @command('debugindexdot', debugrevlogopts,
2505 2531 _('-c|-m|FILE'), optionalrepo=True)
2506 2532 def debugindexdot(ui, repo, file_=None, **opts):
2507 2533 """dump an index DAG as a graphviz dot file"""
2508 2534 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2509 2535 ui.write(("digraph G {\n"))
2510 2536 for i in r:
2511 2537 node = r.node(i)
2512 2538 pp = r.parents(node)
2513 2539 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2514 2540 if pp[1] != nullid:
2515 2541 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2516 2542 ui.write("}\n")
2517 2543
2518 2544 @command('debugdeltachain',
2519 2545 debugrevlogopts + formatteropts,
2520 2546 _('-c|-m|FILE'),
2521 2547 optionalrepo=True)
2522 2548 def debugdeltachain(ui, repo, file_=None, **opts):
2523 2549 """dump information about delta chains in a revlog
2524 2550
2525 2551 Output can be templatized. Available template keywords are:
2526 2552
2527 2553 rev revision number
2528 2554 chainid delta chain identifier (numbered by unique base)
2529 2555 chainlen delta chain length to this revision
2530 2556 prevrev previous revision in delta chain
2531 2557 deltatype role of delta / how it was computed
2532 2558 compsize compressed size of revision
2533 2559 uncompsize uncompressed size of revision
2534 2560 chainsize total size of compressed revisions in chain
2535 2561 chainratio total chain size divided by uncompressed revision size
2536 2562 (new delta chains typically start at ratio 2.00)
2537 2563 lindist linear distance from base revision in delta chain to end
2538 2564 of this revision
2539 2565 extradist total size of revisions not part of this delta chain from
2540 2566 base of delta chain to end of this revision; a measurement
2541 2567 of how much extra data we need to read/seek across to read
2542 2568 the delta chain for this revision
2543 2569 extraratio extradist divided by chainsize; another representation of
2544 2570 how much unrelated data is needed to load this delta chain
2545 2571 """
2546 2572 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2547 2573 index = r.index
2548 2574 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2549 2575
2550 2576 def revinfo(rev):
2551 2577 e = index[rev]
2552 2578 compsize = e[1]
2553 2579 uncompsize = e[2]
2554 2580 chainsize = 0
2555 2581
2556 2582 if generaldelta:
2557 2583 if e[3] == e[5]:
2558 2584 deltatype = 'p1'
2559 2585 elif e[3] == e[6]:
2560 2586 deltatype = 'p2'
2561 2587 elif e[3] == rev - 1:
2562 2588 deltatype = 'prev'
2563 2589 elif e[3] == rev:
2564 2590 deltatype = 'base'
2565 2591 else:
2566 2592 deltatype = 'other'
2567 2593 else:
2568 2594 if e[3] == rev:
2569 2595 deltatype = 'base'
2570 2596 else:
2571 2597 deltatype = 'prev'
2572 2598
2573 2599 chain = r._deltachain(rev)[0]
2574 2600 for iterrev in chain:
2575 2601 e = index[iterrev]
2576 2602 chainsize += e[1]
2577 2603
2578 2604 return compsize, uncompsize, deltatype, chain, chainsize
2579 2605
2580 2606 fm = ui.formatter('debugdeltachain', opts)
2581 2607
2582 2608 fm.plain(' rev chain# chainlen prev delta '
2583 2609 'size rawsize chainsize ratio lindist extradist '
2584 2610 'extraratio\n')
2585 2611
2586 2612 chainbases = {}
2587 2613 for rev in r:
2588 2614 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2589 2615 chainbase = chain[0]
2590 2616 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2591 2617 basestart = r.start(chainbase)
2592 2618 revstart = r.start(rev)
2593 2619 lineardist = revstart + comp - basestart
2594 2620 extradist = lineardist - chainsize
2595 2621 try:
2596 2622 prevrev = chain[-2]
2597 2623 except IndexError:
2598 2624 prevrev = -1
2599 2625
2600 2626 chainratio = float(chainsize) / float(uncomp)
2601 2627 extraratio = float(extradist) / float(chainsize)
2602 2628
2603 2629 fm.startitem()
2604 2630 fm.write('rev chainid chainlen prevrev deltatype compsize '
2605 2631 'uncompsize chainsize chainratio lindist extradist '
2606 2632 'extraratio',
2607 2633 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2608 2634 rev, chainid, len(chain), prevrev, deltatype, comp,
2609 2635 uncomp, chainsize, chainratio, lineardist, extradist,
2610 2636 extraratio,
2611 2637 rev=rev, chainid=chainid, chainlen=len(chain),
2612 2638 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2613 2639 uncompsize=uncomp, chainsize=chainsize,
2614 2640 chainratio=chainratio, lindist=lineardist,
2615 2641 extradist=extradist, extraratio=extraratio)
2616 2642
2617 2643 fm.end()
2618 2644
2619 2645 @command('debuginstall', [], '', norepo=True)
2620 2646 def debuginstall(ui):
2621 2647 '''test Mercurial installation
2622 2648
2623 2649 Returns 0 on success.
2624 2650 '''
2625 2651
2626 2652 def writetemp(contents):
2627 2653 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2628 2654 f = os.fdopen(fd, "wb")
2629 2655 f.write(contents)
2630 2656 f.close()
2631 2657 return name
2632 2658
2633 2659 problems = 0
2634 2660
2635 2661 # encoding
2636 2662 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2637 2663 try:
2638 2664 encoding.fromlocal("test")
2639 2665 except error.Abort as inst:
2640 2666 ui.write(" %s\n" % inst)
2641 2667 ui.write(_(" (check that your locale is properly set)\n"))
2642 2668 problems += 1
2643 2669
2644 2670 # Python
2645 2671 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2646 2672 ui.status(_("checking Python version (%s)\n")
2647 2673 % ("%s.%s.%s" % sys.version_info[:3]))
2648 2674 ui.status(_("checking Python lib (%s)...\n")
2649 2675 % os.path.dirname(os.__file__))
2650 2676
2651 2677 # compiled modules
2652 2678 ui.status(_("checking installed modules (%s)...\n")
2653 2679 % os.path.dirname(__file__))
2654 2680 try:
2655 2681 import bdiff, mpatch, base85, osutil
2656 2682 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2657 2683 except Exception as inst:
2658 2684 ui.write(" %s\n" % inst)
2659 2685 ui.write(_(" One or more extensions could not be found"))
2660 2686 ui.write(_(" (check that you compiled the extensions)\n"))
2661 2687 problems += 1
2662 2688
2663 2689 # templates
2664 2690 import templater
2665 2691 p = templater.templatepaths()
2666 2692 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2667 2693 if p:
2668 2694 m = templater.templatepath("map-cmdline.default")
2669 2695 if m:
2670 2696 # template found, check if it is working
2671 2697 try:
2672 2698 templater.templater(m)
2673 2699 except Exception as inst:
2674 2700 ui.write(" %s\n" % inst)
2675 2701 p = None
2676 2702 else:
2677 2703 ui.write(_(" template 'default' not found\n"))
2678 2704 p = None
2679 2705 else:
2680 2706 ui.write(_(" no template directories found\n"))
2681 2707 if not p:
2682 2708 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2683 2709 problems += 1
2684 2710
2685 2711 # editor
2686 2712 ui.status(_("checking commit editor...\n"))
2687 2713 editor = ui.geteditor()
2688 2714 editor = util.expandpath(editor)
2689 2715 cmdpath = util.findexe(shlex.split(editor)[0])
2690 2716 if not cmdpath:
2691 2717 if editor == 'vi':
2692 2718 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2693 2719 ui.write(_(" (specify a commit editor in your configuration"
2694 2720 " file)\n"))
2695 2721 else:
2696 2722 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2697 2723 ui.write(_(" (specify a commit editor in your configuration"
2698 2724 " file)\n"))
2699 2725 problems += 1
2700 2726
2701 2727 # check username
2702 2728 ui.status(_("checking username...\n"))
2703 2729 try:
2704 2730 ui.username()
2705 2731 except error.Abort as e:
2706 2732 ui.write(" %s\n" % e)
2707 2733 ui.write(_(" (specify a username in your configuration file)\n"))
2708 2734 problems += 1
2709 2735
2710 2736 if not problems:
2711 2737 ui.status(_("no problems detected\n"))
2712 2738 else:
2713 2739 ui.write(_("%s problems detected,"
2714 2740 " please check your install!\n") % problems)
2715 2741
2716 2742 return problems
2717 2743
2718 2744 @command('debugknown', [], _('REPO ID...'), norepo=True)
2719 2745 def debugknown(ui, repopath, *ids, **opts):
2720 2746 """test whether node ids are known to a repo
2721 2747
2722 2748 Every ID must be a full-length hex node id string. Returns a list of 0s
2723 2749 and 1s indicating unknown/known.
2724 2750 """
2725 2751 repo = hg.peer(ui, opts, repopath)
2726 2752 if not repo.capable('known'):
2727 2753 raise error.Abort("known() not supported by target repository")
2728 2754 flags = repo.known([bin(s) for s in ids])
2729 2755 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2730 2756
2731 2757 @command('debuglabelcomplete', [], _('LABEL...'))
2732 2758 def debuglabelcomplete(ui, repo, *args):
2733 2759 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2734 2760 debugnamecomplete(ui, repo, *args)
2735 2761
2736 2762 @command('debugmergestate', [], '')
2737 2763 def debugmergestate(ui, repo, *args):
2738 2764 """print merge state
2739 2765
2740 2766 Use --verbose to print out information about whether v1 or v2 merge state
2741 2767 was chosen."""
2742 2768 def _hashornull(h):
2743 2769 if h == nullhex:
2744 2770 return 'null'
2745 2771 else:
2746 2772 return h
2747 2773
2748 2774 def printrecords(version):
2749 2775 ui.write(('* version %s records\n') % version)
2750 2776 if version == 1:
2751 2777 records = v1records
2752 2778 else:
2753 2779 records = v2records
2754 2780
2755 2781 for rtype, record in records:
2756 2782 # pretty print some record types
2757 2783 if rtype == 'L':
2758 2784 ui.write(('local: %s\n') % record)
2759 2785 elif rtype == 'O':
2760 2786 ui.write(('other: %s\n') % record)
2761 2787 elif rtype == 'm':
2762 2788 driver, mdstate = record.split('\0', 1)
2763 2789 ui.write(('merge driver: %s (state "%s")\n')
2764 2790 % (driver, mdstate))
2765 2791 elif rtype in 'FDC':
2766 2792 r = record.split('\0')
2767 2793 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2768 2794 if version == 1:
2769 2795 onode = 'not stored in v1 format'
2770 2796 flags = r[7]
2771 2797 else:
2772 2798 onode, flags = r[7:9]
2773 2799 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2774 2800 % (f, rtype, state, _hashornull(hash)))
2775 2801 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2776 2802 ui.write((' ancestor path: %s (node %s)\n')
2777 2803 % (afile, _hashornull(anode)))
2778 2804 ui.write((' other path: %s (node %s)\n')
2779 2805 % (ofile, _hashornull(onode)))
2780 2806 else:
2781 2807 ui.write(('unrecognized entry: %s\t%s\n')
2782 2808 % (rtype, record.replace('\0', '\t')))
2783 2809
2784 2810 # Avoid mergestate.read() since it may raise an exception for unsupported
2785 2811 # merge state records. We shouldn't be doing this, but this is OK since this
2786 2812 # command is pretty low-level.
2787 2813 ms = mergemod.mergestate(repo)
2788 2814
2789 2815 # sort so that reasonable information is on top
2790 2816 v1records = ms._readrecordsv1()
2791 2817 v2records = ms._readrecordsv2()
2792 2818 order = 'LOm'
2793 2819 def key(r):
2794 2820 idx = order.find(r[0])
2795 2821 if idx == -1:
2796 2822 return (1, r[1])
2797 2823 else:
2798 2824 return (0, idx)
2799 2825 v1records.sort(key=key)
2800 2826 v2records.sort(key=key)
2801 2827
2802 2828 if not v1records and not v2records:
2803 2829 ui.write(('no merge state found\n'))
2804 2830 elif not v2records:
2805 2831 ui.note(('no version 2 merge state\n'))
2806 2832 printrecords(1)
2807 2833 elif ms._v1v2match(v1records, v2records):
2808 2834 ui.note(('v1 and v2 states match: using v2\n'))
2809 2835 printrecords(2)
2810 2836 else:
2811 2837 ui.note(('v1 and v2 states mismatch: using v1\n'))
2812 2838 printrecords(1)
2813 2839 if ui.verbose:
2814 2840 printrecords(2)
2815 2841
2816 2842 @command('debugnamecomplete', [], _('NAME...'))
2817 2843 def debugnamecomplete(ui, repo, *args):
2818 2844 '''complete "names" - tags, open branch names, bookmark names'''
2819 2845
2820 2846 names = set()
2821 2847 # since we previously only listed open branches, we will handle that
2822 2848 # specially (after this for loop)
2823 2849 for name, ns in repo.names.iteritems():
2824 2850 if name != 'branches':
2825 2851 names.update(ns.listnames(repo))
2826 2852 names.update(tag for (tag, heads, tip, closed)
2827 2853 in repo.branchmap().iterbranches() if not closed)
2828 2854 completions = set()
2829 2855 if not args:
2830 2856 args = ['']
2831 2857 for a in args:
2832 2858 completions.update(n for n in names if n.startswith(a))
2833 2859 ui.write('\n'.join(sorted(completions)))
2834 2860 ui.write('\n')
2835 2861
2836 2862 @command('debuglocks',
2837 2863 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2838 2864 ('W', 'force-wlock', None,
2839 2865 _('free the working state lock (DANGEROUS)'))],
2840 2866 _('[OPTION]...'))
2841 2867 def debuglocks(ui, repo, **opts):
2842 2868 """show or modify state of locks
2843 2869
2844 2870 By default, this command will show which locks are held. This
2845 2871 includes the user and process holding the lock, the amount of time
2846 2872 the lock has been held, and the machine name where the process is
2847 2873 running if it's not local.
2848 2874
2849 2875 Locks protect the integrity of Mercurial's data, so should be
2850 2876 treated with care. System crashes or other interruptions may cause
2851 2877 locks to not be properly released, though Mercurial will usually
2852 2878 detect and remove such stale locks automatically.
2853 2879
2854 2880 However, detecting stale locks may not always be possible (for
2855 2881 instance, on a shared filesystem). Removing locks may also be
2856 2882 blocked by filesystem permissions.
2857 2883
2858 2884 Returns 0 if no locks are held.
2859 2885
2860 2886 """
2861 2887
2862 2888 if opts.get('force_lock'):
2863 2889 repo.svfs.unlink('lock')
2864 2890 if opts.get('force_wlock'):
2865 2891 repo.vfs.unlink('wlock')
2866 2892 if opts.get('force_lock') or opts.get('force_lock'):
2867 2893 return 0
2868 2894
2869 2895 now = time.time()
2870 2896 held = 0
2871 2897
2872 2898 def report(vfs, name, method):
2873 2899 # this causes stale locks to get reaped for more accurate reporting
2874 2900 try:
2875 2901 l = method(False)
2876 2902 except error.LockHeld:
2877 2903 l = None
2878 2904
2879 2905 if l:
2880 2906 l.release()
2881 2907 else:
2882 2908 try:
2883 2909 stat = vfs.lstat(name)
2884 2910 age = now - stat.st_mtime
2885 2911 user = util.username(stat.st_uid)
2886 2912 locker = vfs.readlock(name)
2887 2913 if ":" in locker:
2888 2914 host, pid = locker.split(':')
2889 2915 if host == socket.gethostname():
2890 2916 locker = 'user %s, process %s' % (user, pid)
2891 2917 else:
2892 2918 locker = 'user %s, process %s, host %s' \
2893 2919 % (user, pid, host)
2894 2920 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2895 2921 return 1
2896 2922 except OSError as e:
2897 2923 if e.errno != errno.ENOENT:
2898 2924 raise
2899 2925
2900 2926 ui.write("%-6s free\n" % (name + ":"))
2901 2927 return 0
2902 2928
2903 2929 held += report(repo.svfs, "lock", repo.lock)
2904 2930 held += report(repo.vfs, "wlock", repo.wlock)
2905 2931
2906 2932 return held
2907 2933
2908 2934 @command('debugobsolete',
2909 2935 [('', 'flags', 0, _('markers flag')),
2910 2936 ('', 'record-parents', False,
2911 2937 _('record parent information for the precursor')),
2912 2938 ('r', 'rev', [], _('display markers relevant to REV')),
2913 2939 ] + commitopts2,
2914 2940 _('[OBSOLETED [REPLACEMENT ...]]'))
2915 2941 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2916 2942 """create arbitrary obsolete marker
2917 2943
2918 2944 With no arguments, displays the list of obsolescence markers."""
2919 2945
2920 2946 def parsenodeid(s):
2921 2947 try:
2922 2948 # We do not use revsingle/revrange functions here to accept
2923 2949 # arbitrary node identifiers, possibly not present in the
2924 2950 # local repository.
2925 2951 n = bin(s)
2926 2952 if len(n) != len(nullid):
2927 2953 raise TypeError()
2928 2954 return n
2929 2955 except TypeError:
2930 2956 raise error.Abort('changeset references must be full hexadecimal '
2931 2957 'node identifiers')
2932 2958
2933 2959 if precursor is not None:
2934 2960 if opts['rev']:
2935 2961 raise error.Abort('cannot select revision when creating marker')
2936 2962 metadata = {}
2937 2963 metadata['user'] = opts['user'] or ui.username()
2938 2964 succs = tuple(parsenodeid(succ) for succ in successors)
2939 2965 l = repo.lock()
2940 2966 try:
2941 2967 tr = repo.transaction('debugobsolete')
2942 2968 try:
2943 2969 date = opts.get('date')
2944 2970 if date:
2945 2971 date = util.parsedate(date)
2946 2972 else:
2947 2973 date = None
2948 2974 prec = parsenodeid(precursor)
2949 2975 parents = None
2950 2976 if opts['record_parents']:
2951 2977 if prec not in repo.unfiltered():
2952 2978 raise error.Abort('cannot used --record-parents on '
2953 2979 'unknown changesets')
2954 2980 parents = repo.unfiltered()[prec].parents()
2955 2981 parents = tuple(p.node() for p in parents)
2956 2982 repo.obsstore.create(tr, prec, succs, opts['flags'],
2957 2983 parents=parents, date=date,
2958 2984 metadata=metadata)
2959 2985 tr.close()
2960 2986 except ValueError as exc:
2961 2987 raise error.Abort(_('bad obsmarker input: %s') % exc)
2962 2988 finally:
2963 2989 tr.release()
2964 2990 finally:
2965 2991 l.release()
2966 2992 else:
2967 2993 if opts['rev']:
2968 2994 revs = scmutil.revrange(repo, opts['rev'])
2969 2995 nodes = [repo[r].node() for r in revs]
2970 2996 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2971 2997 markers.sort(key=lambda x: x._data)
2972 2998 else:
2973 2999 markers = obsolete.getmarkers(repo)
2974 3000
2975 3001 for m in markers:
2976 3002 cmdutil.showmarker(ui, m)
2977 3003
2978 3004 @command('debugpathcomplete',
2979 3005 [('f', 'full', None, _('complete an entire path')),
2980 3006 ('n', 'normal', None, _('show only normal files')),
2981 3007 ('a', 'added', None, _('show only added files')),
2982 3008 ('r', 'removed', None, _('show only removed files'))],
2983 3009 _('FILESPEC...'))
2984 3010 def debugpathcomplete(ui, repo, *specs, **opts):
2985 3011 '''complete part or all of a tracked path
2986 3012
2987 3013 This command supports shells that offer path name completion. It
2988 3014 currently completes only files already known to the dirstate.
2989 3015
2990 3016 Completion extends only to the next path segment unless
2991 3017 --full is specified, in which case entire paths are used.'''
2992 3018
2993 3019 def complete(path, acceptable):
2994 3020 dirstate = repo.dirstate
2995 3021 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2996 3022 rootdir = repo.root + os.sep
2997 3023 if spec != repo.root and not spec.startswith(rootdir):
2998 3024 return [], []
2999 3025 if os.path.isdir(spec):
3000 3026 spec += '/'
3001 3027 spec = spec[len(rootdir):]
3002 3028 fixpaths = os.sep != '/'
3003 3029 if fixpaths:
3004 3030 spec = spec.replace(os.sep, '/')
3005 3031 speclen = len(spec)
3006 3032 fullpaths = opts['full']
3007 3033 files, dirs = set(), set()
3008 3034 adddir, addfile = dirs.add, files.add
3009 3035 for f, st in dirstate.iteritems():
3010 3036 if f.startswith(spec) and st[0] in acceptable:
3011 3037 if fixpaths:
3012 3038 f = f.replace('/', os.sep)
3013 3039 if fullpaths:
3014 3040 addfile(f)
3015 3041 continue
3016 3042 s = f.find(os.sep, speclen)
3017 3043 if s >= 0:
3018 3044 adddir(f[:s])
3019 3045 else:
3020 3046 addfile(f)
3021 3047 return files, dirs
3022 3048
3023 3049 acceptable = ''
3024 3050 if opts['normal']:
3025 3051 acceptable += 'nm'
3026 3052 if opts['added']:
3027 3053 acceptable += 'a'
3028 3054 if opts['removed']:
3029 3055 acceptable += 'r'
3030 3056 cwd = repo.getcwd()
3031 3057 if not specs:
3032 3058 specs = ['.']
3033 3059
3034 3060 files, dirs = set(), set()
3035 3061 for spec in specs:
3036 3062 f, d = complete(spec, acceptable or 'nmar')
3037 3063 files.update(f)
3038 3064 dirs.update(d)
3039 3065 files.update(dirs)
3040 3066 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3041 3067 ui.write('\n')
3042 3068
3043 3069 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3044 3070 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3045 3071 '''access the pushkey key/value protocol
3046 3072
3047 3073 With two args, list the keys in the given namespace.
3048 3074
3049 3075 With five args, set a key to new if it currently is set to old.
3050 3076 Reports success or failure.
3051 3077 '''
3052 3078
3053 3079 target = hg.peer(ui, {}, repopath)
3054 3080 if keyinfo:
3055 3081 key, old, new = keyinfo
3056 3082 r = target.pushkey(namespace, key, old, new)
3057 3083 ui.status(str(r) + '\n')
3058 3084 return not r
3059 3085 else:
3060 3086 for k, v in sorted(target.listkeys(namespace).iteritems()):
3061 3087 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3062 3088 v.encode('string-escape')))
3063 3089
3064 3090 @command('debugpvec', [], _('A B'))
3065 3091 def debugpvec(ui, repo, a, b=None):
3066 3092 ca = scmutil.revsingle(repo, a)
3067 3093 cb = scmutil.revsingle(repo, b)
3068 3094 pa = pvec.ctxpvec(ca)
3069 3095 pb = pvec.ctxpvec(cb)
3070 3096 if pa == pb:
3071 3097 rel = "="
3072 3098 elif pa > pb:
3073 3099 rel = ">"
3074 3100 elif pa < pb:
3075 3101 rel = "<"
3076 3102 elif pa | pb:
3077 3103 rel = "|"
3078 3104 ui.write(_("a: %s\n") % pa)
3079 3105 ui.write(_("b: %s\n") % pb)
3080 3106 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3081 3107 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3082 3108 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3083 3109 pa.distance(pb), rel))
3084 3110
3085 3111 @command('debugrebuilddirstate|debugrebuildstate',
3086 3112 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3087 3113 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3088 3114 'the working copy parent')),
3089 3115 ],
3090 3116 _('[-r REV]'))
3091 3117 def debugrebuilddirstate(ui, repo, rev, **opts):
3092 3118 """rebuild the dirstate as it would look like for the given revision
3093 3119
3094 3120 If no revision is specified the first current parent will be used.
3095 3121
3096 3122 The dirstate will be set to the files of the given revision.
3097 3123 The actual working directory content or existing dirstate
3098 3124 information such as adds or removes is not considered.
3099 3125
3100 3126 ``minimal`` will only rebuild the dirstate status for files that claim to be
3101 3127 tracked but are not in the parent manifest, or that exist in the parent
3102 3128 manifest but are not in the dirstate. It will not change adds, removes, or
3103 3129 modified files that are in the working copy parent.
3104 3130
3105 3131 One use of this command is to make the next :hg:`status` invocation
3106 3132 check the actual file content.
3107 3133 """
3108 3134 ctx = scmutil.revsingle(repo, rev)
3109 3135 wlock = repo.wlock()
3110 3136 try:
3111 3137 dirstate = repo.dirstate
3112 3138 changedfiles = None
3113 3139 # See command doc for what minimal does.
3114 3140 if opts.get('minimal'):
3115 3141 manifestfiles = set(ctx.manifest().keys())
3116 3142 dirstatefiles = set(dirstate)
3117 3143 manifestonly = manifestfiles - dirstatefiles
3118 3144 dsonly = dirstatefiles - manifestfiles
3119 3145 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3120 3146 changedfiles = manifestonly | dsnotadded
3121 3147
3122 3148 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3123 3149 finally:
3124 3150 wlock.release()
3125 3151
3126 3152 @command('debugrebuildfncache', [], '')
3127 3153 def debugrebuildfncache(ui, repo):
3128 3154 """rebuild the fncache file"""
3129 3155 repair.rebuildfncache(ui, repo)
3130 3156
3131 3157 @command('debugrename',
3132 3158 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3133 3159 _('[-r REV] FILE'))
3134 3160 def debugrename(ui, repo, file1, *pats, **opts):
3135 3161 """dump rename information"""
3136 3162
3137 3163 ctx = scmutil.revsingle(repo, opts.get('rev'))
3138 3164 m = scmutil.match(ctx, (file1,) + pats, opts)
3139 3165 for abs in ctx.walk(m):
3140 3166 fctx = ctx[abs]
3141 3167 o = fctx.filelog().renamed(fctx.filenode())
3142 3168 rel = m.rel(abs)
3143 3169 if o:
3144 3170 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3145 3171 else:
3146 3172 ui.write(_("%s not renamed\n") % rel)
3147 3173
3148 3174 @command('debugrevlog', debugrevlogopts +
3149 3175 [('d', 'dump', False, _('dump index data'))],
3150 3176 _('-c|-m|FILE'),
3151 3177 optionalrepo=True)
3152 3178 def debugrevlog(ui, repo, file_=None, **opts):
3153 3179 """show data and statistics about a revlog"""
3154 3180 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3155 3181
3156 3182 if opts.get("dump"):
3157 3183 numrevs = len(r)
3158 3184 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3159 3185 " rawsize totalsize compression heads chainlen\n")
3160 3186 ts = 0
3161 3187 heads = set()
3162 3188
3163 3189 for rev in xrange(numrevs):
3164 3190 dbase = r.deltaparent(rev)
3165 3191 if dbase == -1:
3166 3192 dbase = rev
3167 3193 cbase = r.chainbase(rev)
3168 3194 clen = r.chainlen(rev)
3169 3195 p1, p2 = r.parentrevs(rev)
3170 3196 rs = r.rawsize(rev)
3171 3197 ts = ts + rs
3172 3198 heads -= set(r.parentrevs(rev))
3173 3199 heads.add(rev)
3174 3200 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3175 3201 "%11d %5d %8d\n" %
3176 3202 (rev, p1, p2, r.start(rev), r.end(rev),
3177 3203 r.start(dbase), r.start(cbase),
3178 3204 r.start(p1), r.start(p2),
3179 3205 rs, ts, ts / r.end(rev), len(heads), clen))
3180 3206 return 0
3181 3207
3182 3208 v = r.version
3183 3209 format = v & 0xFFFF
3184 3210 flags = []
3185 3211 gdelta = False
3186 3212 if v & revlog.REVLOGNGINLINEDATA:
3187 3213 flags.append('inline')
3188 3214 if v & revlog.REVLOGGENERALDELTA:
3189 3215 gdelta = True
3190 3216 flags.append('generaldelta')
3191 3217 if not flags:
3192 3218 flags = ['(none)']
3193 3219
3194 3220 nummerges = 0
3195 3221 numfull = 0
3196 3222 numprev = 0
3197 3223 nump1 = 0
3198 3224 nump2 = 0
3199 3225 numother = 0
3200 3226 nump1prev = 0
3201 3227 nump2prev = 0
3202 3228 chainlengths = []
3203 3229
3204 3230 datasize = [None, 0, 0L]
3205 3231 fullsize = [None, 0, 0L]
3206 3232 deltasize = [None, 0, 0L]
3207 3233
3208 3234 def addsize(size, l):
3209 3235 if l[0] is None or size < l[0]:
3210 3236 l[0] = size
3211 3237 if size > l[1]:
3212 3238 l[1] = size
3213 3239 l[2] += size
3214 3240
3215 3241 numrevs = len(r)
3216 3242 for rev in xrange(numrevs):
3217 3243 p1, p2 = r.parentrevs(rev)
3218 3244 delta = r.deltaparent(rev)
3219 3245 if format > 0:
3220 3246 addsize(r.rawsize(rev), datasize)
3221 3247 if p2 != nullrev:
3222 3248 nummerges += 1
3223 3249 size = r.length(rev)
3224 3250 if delta == nullrev:
3225 3251 chainlengths.append(0)
3226 3252 numfull += 1
3227 3253 addsize(size, fullsize)
3228 3254 else:
3229 3255 chainlengths.append(chainlengths[delta] + 1)
3230 3256 addsize(size, deltasize)
3231 3257 if delta == rev - 1:
3232 3258 numprev += 1
3233 3259 if delta == p1:
3234 3260 nump1prev += 1
3235 3261 elif delta == p2:
3236 3262 nump2prev += 1
3237 3263 elif delta == p1:
3238 3264 nump1 += 1
3239 3265 elif delta == p2:
3240 3266 nump2 += 1
3241 3267 elif delta != nullrev:
3242 3268 numother += 1
3243 3269
3244 3270 # Adjust size min value for empty cases
3245 3271 for size in (datasize, fullsize, deltasize):
3246 3272 if size[0] is None:
3247 3273 size[0] = 0
3248 3274
3249 3275 numdeltas = numrevs - numfull
3250 3276 numoprev = numprev - nump1prev - nump2prev
3251 3277 totalrawsize = datasize[2]
3252 3278 datasize[2] /= numrevs
3253 3279 fulltotal = fullsize[2]
3254 3280 fullsize[2] /= numfull
3255 3281 deltatotal = deltasize[2]
3256 3282 if numrevs - numfull > 0:
3257 3283 deltasize[2] /= numrevs - numfull
3258 3284 totalsize = fulltotal + deltatotal
3259 3285 avgchainlen = sum(chainlengths) / numrevs
3260 3286 maxchainlen = max(chainlengths)
3261 3287 compratio = 1
3262 3288 if totalsize:
3263 3289 compratio = totalrawsize / totalsize
3264 3290
3265 3291 basedfmtstr = '%%%dd\n'
3266 3292 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3267 3293
3268 3294 def dfmtstr(max):
3269 3295 return basedfmtstr % len(str(max))
3270 3296 def pcfmtstr(max, padding=0):
3271 3297 return basepcfmtstr % (len(str(max)), ' ' * padding)
3272 3298
3273 3299 def pcfmt(value, total):
3274 3300 if total:
3275 3301 return (value, 100 * float(value) / total)
3276 3302 else:
3277 3303 return value, 100.0
3278 3304
3279 3305 ui.write(('format : %d\n') % format)
3280 3306 ui.write(('flags : %s\n') % ', '.join(flags))
3281 3307
3282 3308 ui.write('\n')
3283 3309 fmt = pcfmtstr(totalsize)
3284 3310 fmt2 = dfmtstr(totalsize)
3285 3311 ui.write(('revisions : ') + fmt2 % numrevs)
3286 3312 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3287 3313 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3288 3314 ui.write(('revisions : ') + fmt2 % numrevs)
3289 3315 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3290 3316 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3291 3317 ui.write(('revision size : ') + fmt2 % totalsize)
3292 3318 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3293 3319 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3294 3320
3295 3321 ui.write('\n')
3296 3322 fmt = dfmtstr(max(avgchainlen, compratio))
3297 3323 ui.write(('avg chain length : ') + fmt % avgchainlen)
3298 3324 ui.write(('max chain length : ') + fmt % maxchainlen)
3299 3325 ui.write(('compression ratio : ') + fmt % compratio)
3300 3326
3301 3327 if format > 0:
3302 3328 ui.write('\n')
3303 3329 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3304 3330 % tuple(datasize))
3305 3331 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3306 3332 % tuple(fullsize))
3307 3333 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3308 3334 % tuple(deltasize))
3309 3335
3310 3336 if numdeltas > 0:
3311 3337 ui.write('\n')
3312 3338 fmt = pcfmtstr(numdeltas)
3313 3339 fmt2 = pcfmtstr(numdeltas, 4)
3314 3340 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3315 3341 if numprev > 0:
3316 3342 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3317 3343 numprev))
3318 3344 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3319 3345 numprev))
3320 3346 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3321 3347 numprev))
3322 3348 if gdelta:
3323 3349 ui.write(('deltas against p1 : ')
3324 3350 + fmt % pcfmt(nump1, numdeltas))
3325 3351 ui.write(('deltas against p2 : ')
3326 3352 + fmt % pcfmt(nump2, numdeltas))
3327 3353 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3328 3354 numdeltas))
3329 3355
3330 3356 @command('debugrevspec',
3331 3357 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3332 3358 ('REVSPEC'))
3333 3359 def debugrevspec(ui, repo, expr, **opts):
3334 3360 """parse and apply a revision specification
3335 3361
3336 3362 Use --verbose to print the parsed tree before and after aliases
3337 3363 expansion.
3338 3364 """
3339 3365 if ui.verbose:
3340 3366 tree = revset.parse(expr, lookup=repo.__contains__)
3341 3367 ui.note(revset.prettyformat(tree), "\n")
3342 3368 newtree = revset.findaliases(ui, tree)
3343 3369 if newtree != tree:
3344 3370 ui.note(revset.prettyformat(newtree), "\n")
3345 3371 tree = newtree
3346 3372 newtree = revset.foldconcat(tree)
3347 3373 if newtree != tree:
3348 3374 ui.note(revset.prettyformat(newtree), "\n")
3349 3375 if opts["optimize"]:
3350 3376 weight, optimizedtree = revset.optimize(newtree, True)
3351 3377 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3352 3378 func = revset.match(ui, expr, repo)
3353 3379 revs = func(repo)
3354 3380 if ui.verbose:
3355 3381 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3356 3382 for c in revs:
3357 3383 ui.write("%s\n" % c)
3358 3384
3359 3385 @command('debugsetparents', [], _('REV1 [REV2]'))
3360 3386 def debugsetparents(ui, repo, rev1, rev2=None):
3361 3387 """manually set the parents of the current working directory
3362 3388
3363 3389 This is useful for writing repository conversion tools, but should
3364 3390 be used with care. For example, neither the working directory nor the
3365 3391 dirstate is updated, so file status may be incorrect after running this
3366 3392 command.
3367 3393
3368 3394 Returns 0 on success.
3369 3395 """
3370 3396
3371 3397 r1 = scmutil.revsingle(repo, rev1).node()
3372 3398 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3373 3399
3374 3400 wlock = repo.wlock()
3375 3401 try:
3376 3402 repo.dirstate.beginparentchange()
3377 3403 repo.setparents(r1, r2)
3378 3404 repo.dirstate.endparentchange()
3379 3405 finally:
3380 3406 wlock.release()
3381 3407
3382 3408 @command('debugdirstate|debugstate',
3383 3409 [('', 'nodates', None, _('do not display the saved mtime')),
3384 3410 ('', 'datesort', None, _('sort by saved mtime'))],
3385 3411 _('[OPTION]...'))
3386 3412 def debugstate(ui, repo, **opts):
3387 3413 """show the contents of the current dirstate"""
3388 3414
3389 3415 nodates = opts.get('nodates')
3390 3416 datesort = opts.get('datesort')
3391 3417
3392 3418 timestr = ""
3393 3419 if datesort:
3394 3420 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3395 3421 else:
3396 3422 keyfunc = None # sort by filename
3397 3423 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3398 3424 if ent[3] == -1:
3399 3425 timestr = 'unset '
3400 3426 elif nodates:
3401 3427 timestr = 'set '
3402 3428 else:
3403 3429 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3404 3430 time.localtime(ent[3]))
3405 3431 if ent[1] & 0o20000:
3406 3432 mode = 'lnk'
3407 3433 else:
3408 3434 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3409 3435 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3410 3436 for f in repo.dirstate.copies():
3411 3437 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3412 3438
3413 3439 @command('debugsub',
3414 3440 [('r', 'rev', '',
3415 3441 _('revision to check'), _('REV'))],
3416 3442 _('[-r REV] [REV]'))
3417 3443 def debugsub(ui, repo, rev=None):
3418 3444 ctx = scmutil.revsingle(repo, rev, None)
3419 3445 for k, v in sorted(ctx.substate.items()):
3420 3446 ui.write(('path %s\n') % k)
3421 3447 ui.write((' source %s\n') % v[0])
3422 3448 ui.write((' revision %s\n') % v[1])
3423 3449
3424 3450 @command('debugsuccessorssets',
3425 3451 [],
3426 3452 _('[REV]'))
3427 3453 def debugsuccessorssets(ui, repo, *revs):
3428 3454 """show set of successors for revision
3429 3455
3430 3456 A successors set of changeset A is a consistent group of revisions that
3431 3457 succeed A. It contains non-obsolete changesets only.
3432 3458
3433 3459 In most cases a changeset A has a single successors set containing a single
3434 3460 successor (changeset A replaced by A').
3435 3461
3436 3462 A changeset that is made obsolete with no successors are called "pruned".
3437 3463 Such changesets have no successors sets at all.
3438 3464
3439 3465 A changeset that has been "split" will have a successors set containing
3440 3466 more than one successor.
3441 3467
3442 3468 A changeset that has been rewritten in multiple different ways is called
3443 3469 "divergent". Such changesets have multiple successor sets (each of which
3444 3470 may also be split, i.e. have multiple successors).
3445 3471
3446 3472 Results are displayed as follows::
3447 3473
3448 3474 <rev1>
3449 3475 <successors-1A>
3450 3476 <rev2>
3451 3477 <successors-2A>
3452 3478 <successors-2B1> <successors-2B2> <successors-2B3>
3453 3479
3454 3480 Here rev2 has two possible (i.e. divergent) successors sets. The first
3455 3481 holds one element, whereas the second holds three (i.e. the changeset has
3456 3482 been split).
3457 3483 """
3458 3484 # passed to successorssets caching computation from one call to another
3459 3485 cache = {}
3460 3486 ctx2str = str
3461 3487 node2str = short
3462 3488 if ui.debug():
3463 3489 def ctx2str(ctx):
3464 3490 return ctx.hex()
3465 3491 node2str = hex
3466 3492 for rev in scmutil.revrange(repo, revs):
3467 3493 ctx = repo[rev]
3468 3494 ui.write('%s\n'% ctx2str(ctx))
3469 3495 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3470 3496 if succsset:
3471 3497 ui.write(' ')
3472 3498 ui.write(node2str(succsset[0]))
3473 3499 for node in succsset[1:]:
3474 3500 ui.write(' ')
3475 3501 ui.write(node2str(node))
3476 3502 ui.write('\n')
3477 3503
3478 3504 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3479 3505 def debugwalk(ui, repo, *pats, **opts):
3480 3506 """show how files match on given patterns"""
3481 3507 m = scmutil.match(repo[None], pats, opts)
3482 3508 items = list(repo.walk(m))
3483 3509 if not items:
3484 3510 return
3485 3511 f = lambda fn: fn
3486 3512 if ui.configbool('ui', 'slash') and os.sep != '/':
3487 3513 f = lambda fn: util.normpath(fn)
3488 3514 fmt = 'f %%-%ds %%-%ds %%s' % (
3489 3515 max([len(abs) for abs in items]),
3490 3516 max([len(m.rel(abs)) for abs in items]))
3491 3517 for abs in items:
3492 3518 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3493 3519 ui.write("%s\n" % line.rstrip())
3494 3520
3495 3521 @command('debugwireargs',
3496 3522 [('', 'three', '', 'three'),
3497 3523 ('', 'four', '', 'four'),
3498 3524 ('', 'five', '', 'five'),
3499 3525 ] + remoteopts,
3500 3526 _('REPO [OPTIONS]... [ONE [TWO]]'),
3501 3527 norepo=True)
3502 3528 def debugwireargs(ui, repopath, *vals, **opts):
3503 3529 repo = hg.peer(ui, opts, repopath)
3504 3530 for opt in remoteopts:
3505 3531 del opts[opt[1]]
3506 3532 args = {}
3507 3533 for k, v in opts.iteritems():
3508 3534 if v:
3509 3535 args[k] = v
3510 3536 # run twice to check that we don't mess up the stream for the next command
3511 3537 res1 = repo.debugwireargs(*vals, **args)
3512 3538 res2 = repo.debugwireargs(*vals, **args)
3513 3539 ui.write("%s\n" % res1)
3514 3540 if res1 != res2:
3515 3541 ui.warn("%s\n" % res2)
3516 3542
3517 3543 @command('^diff',
3518 3544 [('r', 'rev', [], _('revision'), _('REV')),
3519 3545 ('c', 'change', '', _('change made by revision'), _('REV'))
3520 3546 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3521 3547 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3522 3548 inferrepo=True)
3523 3549 def diff(ui, repo, *pats, **opts):
3524 3550 """diff repository (or selected files)
3525 3551
3526 3552 Show differences between revisions for the specified files.
3527 3553
3528 3554 Differences between files are shown using the unified diff format.
3529 3555
3530 3556 .. note::
3531 3557
3532 3558 :hg:`diff` may generate unexpected results for merges, as it will
3533 3559 default to comparing against the working directory's first
3534 3560 parent changeset if no revisions are specified.
3535 3561
3536 3562 When two revision arguments are given, then changes are shown
3537 3563 between those revisions. If only one revision is specified then
3538 3564 that revision is compared to the working directory, and, when no
3539 3565 revisions are specified, the working directory files are compared
3540 3566 to its first parent.
3541 3567
3542 3568 Alternatively you can specify -c/--change with a revision to see
3543 3569 the changes in that changeset relative to its first parent.
3544 3570
3545 3571 Without the -a/--text option, diff will avoid generating diffs of
3546 3572 files it detects as binary. With -a, diff will generate a diff
3547 3573 anyway, probably with undesirable results.
3548 3574
3549 3575 Use the -g/--git option to generate diffs in the git extended diff
3550 3576 format. For more information, read :hg:`help diffs`.
3551 3577
3552 3578 .. container:: verbose
3553 3579
3554 3580 Examples:
3555 3581
3556 3582 - compare a file in the current working directory to its parent::
3557 3583
3558 3584 hg diff foo.c
3559 3585
3560 3586 - compare two historical versions of a directory, with rename info::
3561 3587
3562 3588 hg diff --git -r 1.0:1.2 lib/
3563 3589
3564 3590 - get change stats relative to the last change on some date::
3565 3591
3566 3592 hg diff --stat -r "date('may 2')"
3567 3593
3568 3594 - diff all newly-added files that contain a keyword::
3569 3595
3570 3596 hg diff "set:added() and grep(GNU)"
3571 3597
3572 3598 - compare a revision and its parents::
3573 3599
3574 3600 hg diff -c 9353 # compare against first parent
3575 3601 hg diff -r 9353^:9353 # same using revset syntax
3576 3602 hg diff -r 9353^2:9353 # compare against the second parent
3577 3603
3578 3604 Returns 0 on success.
3579 3605 """
3580 3606
3581 3607 revs = opts.get('rev')
3582 3608 change = opts.get('change')
3583 3609 stat = opts.get('stat')
3584 3610 reverse = opts.get('reverse')
3585 3611
3586 3612 if revs and change:
3587 3613 msg = _('cannot specify --rev and --change at the same time')
3588 3614 raise error.Abort(msg)
3589 3615 elif change:
3590 3616 node2 = scmutil.revsingle(repo, change, None).node()
3591 3617 node1 = repo[node2].p1().node()
3592 3618 else:
3593 3619 node1, node2 = scmutil.revpair(repo, revs)
3594 3620
3595 3621 if reverse:
3596 3622 node1, node2 = node2, node1
3597 3623
3598 3624 diffopts = patch.diffallopts(ui, opts)
3599 3625 m = scmutil.match(repo[node2], pats, opts)
3600 3626 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3601 3627 listsubrepos=opts.get('subrepos'),
3602 3628 root=opts.get('root'))
3603 3629
3604 3630 @command('^export',
3605 3631 [('o', 'output', '',
3606 3632 _('print output to file with formatted name'), _('FORMAT')),
3607 3633 ('', 'switch-parent', None, _('diff against the second parent')),
3608 3634 ('r', 'rev', [], _('revisions to export'), _('REV')),
3609 3635 ] + diffopts,
3610 3636 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3611 3637 def export(ui, repo, *changesets, **opts):
3612 3638 """dump the header and diffs for one or more changesets
3613 3639
3614 3640 Print the changeset header and diffs for one or more revisions.
3615 3641 If no revision is given, the parent of the working directory is used.
3616 3642
3617 3643 The information shown in the changeset header is: author, date,
3618 3644 branch name (if non-default), changeset hash, parent(s) and commit
3619 3645 comment.
3620 3646
3621 3647 .. note::
3622 3648
3623 3649 :hg:`export` may generate unexpected diff output for merge
3624 3650 changesets, as it will compare the merge changeset against its
3625 3651 first parent only.
3626 3652
3627 3653 Output may be to a file, in which case the name of the file is
3628 3654 given using a format string. The formatting rules are as follows:
3629 3655
3630 3656 :``%%``: literal "%" character
3631 3657 :``%H``: changeset hash (40 hexadecimal digits)
3632 3658 :``%N``: number of patches being generated
3633 3659 :``%R``: changeset revision number
3634 3660 :``%b``: basename of the exporting repository
3635 3661 :``%h``: short-form changeset hash (12 hexadecimal digits)
3636 3662 :``%m``: first line of the commit message (only alphanumeric characters)
3637 3663 :``%n``: zero-padded sequence number, starting at 1
3638 3664 :``%r``: zero-padded changeset revision number
3639 3665
3640 3666 Without the -a/--text option, export will avoid generating diffs
3641 3667 of files it detects as binary. With -a, export will generate a
3642 3668 diff anyway, probably with undesirable results.
3643 3669
3644 3670 Use the -g/--git option to generate diffs in the git extended diff
3645 3671 format. See :hg:`help diffs` for more information.
3646 3672
3647 3673 With the --switch-parent option, the diff will be against the
3648 3674 second parent. It can be useful to review a merge.
3649 3675
3650 3676 .. container:: verbose
3651 3677
3652 3678 Examples:
3653 3679
3654 3680 - use export and import to transplant a bugfix to the current
3655 3681 branch::
3656 3682
3657 3683 hg export -r 9353 | hg import -
3658 3684
3659 3685 - export all the changesets between two revisions to a file with
3660 3686 rename information::
3661 3687
3662 3688 hg export --git -r 123:150 > changes.txt
3663 3689
3664 3690 - split outgoing changes into a series of patches with
3665 3691 descriptive names::
3666 3692
3667 3693 hg export -r "outgoing()" -o "%n-%m.patch"
3668 3694
3669 3695 Returns 0 on success.
3670 3696 """
3671 3697 changesets += tuple(opts.get('rev', []))
3672 3698 if not changesets:
3673 3699 changesets = ['.']
3674 3700 revs = scmutil.revrange(repo, changesets)
3675 3701 if not revs:
3676 3702 raise error.Abort(_("export requires at least one changeset"))
3677 3703 if len(revs) > 1:
3678 3704 ui.note(_('exporting patches:\n'))
3679 3705 else:
3680 3706 ui.note(_('exporting patch:\n'))
3681 3707 cmdutil.export(repo, revs, template=opts.get('output'),
3682 3708 switch_parent=opts.get('switch_parent'),
3683 3709 opts=patch.diffallopts(ui, opts))
3684 3710
3685 3711 @command('files',
3686 3712 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3687 3713 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3688 3714 ] + walkopts + formatteropts + subrepoopts,
3689 3715 _('[OPTION]... [PATTERN]...'))
3690 3716 def files(ui, repo, *pats, **opts):
3691 3717 """list tracked files
3692 3718
3693 3719 Print files under Mercurial control in the working directory or
3694 3720 specified revision whose names match the given patterns (excluding
3695 3721 removed files).
3696 3722
3697 3723 If no patterns are given to match, this command prints the names
3698 3724 of all files under Mercurial control in the working directory.
3699 3725
3700 3726 .. container:: verbose
3701 3727
3702 3728 Examples:
3703 3729
3704 3730 - list all files under the current directory::
3705 3731
3706 3732 hg files .
3707 3733
3708 3734 - shows sizes and flags for current revision::
3709 3735
3710 3736 hg files -vr .
3711 3737
3712 3738 - list all files named README::
3713 3739
3714 3740 hg files -I "**/README"
3715 3741
3716 3742 - list all binary files::
3717 3743
3718 3744 hg files "set:binary()"
3719 3745
3720 3746 - find files containing a regular expression::
3721 3747
3722 3748 hg files "set:grep('bob')"
3723 3749
3724 3750 - search tracked file contents with xargs and grep::
3725 3751
3726 3752 hg files -0 | xargs -0 grep foo
3727 3753
3728 3754 See :hg:`help patterns` and :hg:`help filesets` for more information
3729 3755 on specifying file patterns.
3730 3756
3731 3757 Returns 0 if a match is found, 1 otherwise.
3732 3758
3733 3759 """
3734 3760 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3735 3761
3736 3762 end = '\n'
3737 3763 if opts.get('print0'):
3738 3764 end = '\0'
3739 3765 fm = ui.formatter('files', opts)
3740 3766 fmt = '%s' + end
3741 3767
3742 3768 m = scmutil.match(ctx, pats, opts)
3743 3769 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3744 3770
3745 3771 fm.end()
3746 3772
3747 3773 return ret
3748 3774
3749 3775 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3750 3776 def forget(ui, repo, *pats, **opts):
3751 3777 """forget the specified files on the next commit
3752 3778
3753 3779 Mark the specified files so they will no longer be tracked
3754 3780 after the next commit.
3755 3781
3756 3782 This only removes files from the current branch, not from the
3757 3783 entire project history, and it does not delete them from the
3758 3784 working directory.
3759 3785
3760 3786 To delete the file from the working directory, see :hg:`remove`.
3761 3787
3762 3788 To undo a forget before the next commit, see :hg:`add`.
3763 3789
3764 3790 .. container:: verbose
3765 3791
3766 3792 Examples:
3767 3793
3768 3794 - forget newly-added binary files::
3769 3795
3770 3796 hg forget "set:added() and binary()"
3771 3797
3772 3798 - forget files that would be excluded by .hgignore::
3773 3799
3774 3800 hg forget "set:hgignore()"
3775 3801
3776 3802 Returns 0 on success.
3777 3803 """
3778 3804
3779 3805 if not pats:
3780 3806 raise error.Abort(_('no files specified'))
3781 3807
3782 3808 m = scmutil.match(repo[None], pats, opts)
3783 3809 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3784 3810 return rejected and 1 or 0
3785 3811
3786 3812 @command(
3787 3813 'graft',
3788 3814 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3789 3815 ('c', 'continue', False, _('resume interrupted graft')),
3790 3816 ('e', 'edit', False, _('invoke editor on commit messages')),
3791 3817 ('', 'log', None, _('append graft info to log message')),
3792 3818 ('f', 'force', False, _('force graft')),
3793 3819 ('D', 'currentdate', False,
3794 3820 _('record the current date as commit date')),
3795 3821 ('U', 'currentuser', False,
3796 3822 _('record the current user as committer'), _('DATE'))]
3797 3823 + commitopts2 + mergetoolopts + dryrunopts,
3798 3824 _('[OPTION]... [-r] REV...'))
3799 3825 def graft(ui, repo, *revs, **opts):
3800 3826 '''copy changes from other branches onto the current branch
3801 3827
3802 3828 This command uses Mercurial's merge logic to copy individual
3803 3829 changes from other branches without merging branches in the
3804 3830 history graph. This is sometimes known as 'backporting' or
3805 3831 'cherry-picking'. By default, graft will copy user, date, and
3806 3832 description from the source changesets.
3807 3833
3808 3834 Changesets that are ancestors of the current revision, that have
3809 3835 already been grafted, or that are merges will be skipped.
3810 3836
3811 3837 If --log is specified, log messages will have a comment appended
3812 3838 of the form::
3813 3839
3814 3840 (grafted from CHANGESETHASH)
3815 3841
3816 3842 If --force is specified, revisions will be grafted even if they
3817 3843 are already ancestors of or have been grafted to the destination.
3818 3844 This is useful when the revisions have since been backed out.
3819 3845
3820 3846 If a graft merge results in conflicts, the graft process is
3821 3847 interrupted so that the current merge can be manually resolved.
3822 3848 Once all conflicts are addressed, the graft process can be
3823 3849 continued with the -c/--continue option.
3824 3850
3825 3851 .. note::
3826 3852
3827 3853 The -c/--continue option does not reapply earlier options, except
3828 3854 for --force.
3829 3855
3830 3856 .. container:: verbose
3831 3857
3832 3858 Examples:
3833 3859
3834 3860 - copy a single change to the stable branch and edit its description::
3835 3861
3836 3862 hg update stable
3837 3863 hg graft --edit 9393
3838 3864
3839 3865 - graft a range of changesets with one exception, updating dates::
3840 3866
3841 3867 hg graft -D "2085::2093 and not 2091"
3842 3868
3843 3869 - continue a graft after resolving conflicts::
3844 3870
3845 3871 hg graft -c
3846 3872
3847 3873 - show the source of a grafted changeset::
3848 3874
3849 3875 hg log --debug -r .
3850 3876
3851 3877 - show revisions sorted by date::
3852 3878
3853 3879 hg log -r 'sort(all(), date)'
3854 3880
3855 3881 See :hg:`help revisions` and :hg:`help revsets` for more about
3856 3882 specifying revisions.
3857 3883
3858 3884 Returns 0 on successful completion.
3859 3885 '''
3860 3886 wlock = None
3861 3887 try:
3862 3888 wlock = repo.wlock()
3863 3889 return _dograft(ui, repo, *revs, **opts)
3864 3890 finally:
3865 3891 release(wlock)
3866 3892
3867 3893 def _dograft(ui, repo, *revs, **opts):
3868 3894 revs = list(revs)
3869 3895 revs.extend(opts['rev'])
3870 3896
3871 3897 if not opts.get('user') and opts.get('currentuser'):
3872 3898 opts['user'] = ui.username()
3873 3899 if not opts.get('date') and opts.get('currentdate'):
3874 3900 opts['date'] = "%d %d" % util.makedate()
3875 3901
3876 3902 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3877 3903
3878 3904 cont = False
3879 3905 if opts['continue']:
3880 3906 cont = True
3881 3907 if revs:
3882 3908 raise error.Abort(_("can't specify --continue and revisions"))
3883 3909 # read in unfinished revisions
3884 3910 try:
3885 3911 nodes = repo.vfs.read('graftstate').splitlines()
3886 3912 revs = [repo[node].rev() for node in nodes]
3887 3913 except IOError as inst:
3888 3914 if inst.errno != errno.ENOENT:
3889 3915 raise
3890 3916 raise error.Abort(_("no graft state found, can't continue"))
3891 3917 else:
3892 3918 cmdutil.checkunfinished(repo)
3893 3919 cmdutil.bailifchanged(repo)
3894 3920 if not revs:
3895 3921 raise error.Abort(_('no revisions specified'))
3896 3922 revs = scmutil.revrange(repo, revs)
3897 3923
3898 3924 skipped = set()
3899 3925 # check for merges
3900 3926 for rev in repo.revs('%ld and merge()', revs):
3901 3927 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3902 3928 skipped.add(rev)
3903 3929 revs = [r for r in revs if r not in skipped]
3904 3930 if not revs:
3905 3931 return -1
3906 3932
3907 3933 # Don't check in the --continue case, in effect retaining --force across
3908 3934 # --continues. That's because without --force, any revisions we decided to
3909 3935 # skip would have been filtered out here, so they wouldn't have made their
3910 3936 # way to the graftstate. With --force, any revisions we would have otherwise
3911 3937 # skipped would not have been filtered out, and if they hadn't been applied
3912 3938 # already, they'd have been in the graftstate.
3913 3939 if not (cont or opts.get('force')):
3914 3940 # check for ancestors of dest branch
3915 3941 crev = repo['.'].rev()
3916 3942 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3917 3943 # Cannot use x.remove(y) on smart set, this has to be a list.
3918 3944 # XXX make this lazy in the future
3919 3945 revs = list(revs)
3920 3946 # don't mutate while iterating, create a copy
3921 3947 for rev in list(revs):
3922 3948 if rev in ancestors:
3923 3949 ui.warn(_('skipping ancestor revision %d:%s\n') %
3924 3950 (rev, repo[rev]))
3925 3951 # XXX remove on list is slow
3926 3952 revs.remove(rev)
3927 3953 if not revs:
3928 3954 return -1
3929 3955
3930 3956 # analyze revs for earlier grafts
3931 3957 ids = {}
3932 3958 for ctx in repo.set("%ld", revs):
3933 3959 ids[ctx.hex()] = ctx.rev()
3934 3960 n = ctx.extra().get('source')
3935 3961 if n:
3936 3962 ids[n] = ctx.rev()
3937 3963
3938 3964 # check ancestors for earlier grafts
3939 3965 ui.debug('scanning for duplicate grafts\n')
3940 3966
3941 3967 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3942 3968 ctx = repo[rev]
3943 3969 n = ctx.extra().get('source')
3944 3970 if n in ids:
3945 3971 try:
3946 3972 r = repo[n].rev()
3947 3973 except error.RepoLookupError:
3948 3974 r = None
3949 3975 if r in revs:
3950 3976 ui.warn(_('skipping revision %d:%s '
3951 3977 '(already grafted to %d:%s)\n')
3952 3978 % (r, repo[r], rev, ctx))
3953 3979 revs.remove(r)
3954 3980 elif ids[n] in revs:
3955 3981 if r is None:
3956 3982 ui.warn(_('skipping already grafted revision %d:%s '
3957 3983 '(%d:%s also has unknown origin %s)\n')
3958 3984 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3959 3985 else:
3960 3986 ui.warn(_('skipping already grafted revision %d:%s '
3961 3987 '(%d:%s also has origin %d:%s)\n')
3962 3988 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3963 3989 revs.remove(ids[n])
3964 3990 elif ctx.hex() in ids:
3965 3991 r = ids[ctx.hex()]
3966 3992 ui.warn(_('skipping already grafted revision %d:%s '
3967 3993 '(was grafted from %d:%s)\n') %
3968 3994 (r, repo[r], rev, ctx))
3969 3995 revs.remove(r)
3970 3996 if not revs:
3971 3997 return -1
3972 3998
3973 3999 try:
3974 4000 for pos, ctx in enumerate(repo.set("%ld", revs)):
3975 4001 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3976 4002 ctx.description().split('\n', 1)[0])
3977 4003 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3978 4004 if names:
3979 4005 desc += ' (%s)' % ' '.join(names)
3980 4006 ui.status(_('grafting %s\n') % desc)
3981 4007 if opts.get('dry_run'):
3982 4008 continue
3983 4009
3984 4010 extra = ctx.extra().copy()
3985 4011 del extra['branch']
3986 4012 source = extra.get('source')
3987 4013 if source:
3988 4014 extra['intermediate-source'] = ctx.hex()
3989 4015 else:
3990 4016 extra['source'] = ctx.hex()
3991 4017 user = ctx.user()
3992 4018 if opts.get('user'):
3993 4019 user = opts['user']
3994 4020 date = ctx.date()
3995 4021 if opts.get('date'):
3996 4022 date = opts['date']
3997 4023 message = ctx.description()
3998 4024 if opts.get('log'):
3999 4025 message += '\n(grafted from %s)' % ctx.hex()
4000 4026
4001 4027 # we don't merge the first commit when continuing
4002 4028 if not cont:
4003 4029 # perform the graft merge with p1(rev) as 'ancestor'
4004 4030 try:
4005 4031 # ui.forcemerge is an internal variable, do not document
4006 4032 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4007 4033 'graft')
4008 4034 stats = mergemod.graft(repo, ctx, ctx.p1(),
4009 4035 ['local', 'graft'])
4010 4036 finally:
4011 4037 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4012 4038 # report any conflicts
4013 4039 if stats and stats[3] > 0:
4014 4040 # write out state for --continue
4015 4041 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4016 4042 repo.vfs.write('graftstate', ''.join(nodelines))
4017 4043 extra = ''
4018 4044 if opts.get('user'):
4019 4045 extra += ' --user %s' % opts['user']
4020 4046 if opts.get('date'):
4021 4047 extra += ' --date %s' % opts['date']
4022 4048 if opts.get('log'):
4023 4049 extra += ' --log'
4024 4050 hint=_('use hg resolve and hg graft --continue%s') % extra
4025 4051 raise error.Abort(
4026 4052 _("unresolved conflicts, can't continue"),
4027 4053 hint=hint)
4028 4054 else:
4029 4055 cont = False
4030 4056
4031 4057 # commit
4032 4058 node = repo.commit(text=message, user=user,
4033 4059 date=date, extra=extra, editor=editor)
4034 4060 if node is None:
4035 4061 ui.warn(
4036 4062 _('note: graft of %d:%s created no changes to commit\n') %
4037 4063 (ctx.rev(), ctx))
4038 4064 finally:
4039 4065 # TODO: get rid of this meaningless try/finally enclosing.
4040 4066 # this is kept only to reduce changes in a patch.
4041 4067 pass
4042 4068
4043 4069 # remove state when we complete successfully
4044 4070 if not opts.get('dry_run'):
4045 4071 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4046 4072
4047 4073 return 0
4048 4074
4049 4075 @command('grep',
4050 4076 [('0', 'print0', None, _('end fields with NUL')),
4051 4077 ('', 'all', None, _('print all revisions that match')),
4052 4078 ('a', 'text', None, _('treat all files as text')),
4053 4079 ('f', 'follow', None,
4054 4080 _('follow changeset history,'
4055 4081 ' or file history across copies and renames')),
4056 4082 ('i', 'ignore-case', None, _('ignore case when matching')),
4057 4083 ('l', 'files-with-matches', None,
4058 4084 _('print only filenames and revisions that match')),
4059 4085 ('n', 'line-number', None, _('print matching line numbers')),
4060 4086 ('r', 'rev', [],
4061 4087 _('only search files changed within revision range'), _('REV')),
4062 4088 ('u', 'user', None, _('list the author (long with -v)')),
4063 4089 ('d', 'date', None, _('list the date (short with -q)')),
4064 4090 ] + walkopts,
4065 4091 _('[OPTION]... PATTERN [FILE]...'),
4066 4092 inferrepo=True)
4067 4093 def grep(ui, repo, pattern, *pats, **opts):
4068 4094 """search for a pattern in specified files and revisions
4069 4095
4070 4096 Search revisions of files for a regular expression.
4071 4097
4072 4098 This command behaves differently than Unix grep. It only accepts
4073 4099 Python/Perl regexps. It searches repository history, not the
4074 4100 working directory. It always prints the revision number in which a
4075 4101 match appears.
4076 4102
4077 4103 By default, grep only prints output for the first revision of a
4078 4104 file in which it finds a match. To get it to print every revision
4079 4105 that contains a change in match status ("-" for a match that
4080 4106 becomes a non-match, or "+" for a non-match that becomes a match),
4081 4107 use the --all flag.
4082 4108
4083 4109 Returns 0 if a match is found, 1 otherwise.
4084 4110 """
4085 4111 reflags = re.M
4086 4112 if opts.get('ignore_case'):
4087 4113 reflags |= re.I
4088 4114 try:
4089 4115 regexp = util.re.compile(pattern, reflags)
4090 4116 except re.error as inst:
4091 4117 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4092 4118 return 1
4093 4119 sep, eol = ':', '\n'
4094 4120 if opts.get('print0'):
4095 4121 sep = eol = '\0'
4096 4122
4097 4123 getfile = util.lrucachefunc(repo.file)
4098 4124
4099 4125 def matchlines(body):
4100 4126 begin = 0
4101 4127 linenum = 0
4102 4128 while begin < len(body):
4103 4129 match = regexp.search(body, begin)
4104 4130 if not match:
4105 4131 break
4106 4132 mstart, mend = match.span()
4107 4133 linenum += body.count('\n', begin, mstart) + 1
4108 4134 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4109 4135 begin = body.find('\n', mend) + 1 or len(body) + 1
4110 4136 lend = begin - 1
4111 4137 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4112 4138
4113 4139 class linestate(object):
4114 4140 def __init__(self, line, linenum, colstart, colend):
4115 4141 self.line = line
4116 4142 self.linenum = linenum
4117 4143 self.colstart = colstart
4118 4144 self.colend = colend
4119 4145
4120 4146 def __hash__(self):
4121 4147 return hash((self.linenum, self.line))
4122 4148
4123 4149 def __eq__(self, other):
4124 4150 return self.line == other.line
4125 4151
4126 4152 def __iter__(self):
4127 4153 yield (self.line[:self.colstart], '')
4128 4154 yield (self.line[self.colstart:self.colend], 'grep.match')
4129 4155 rest = self.line[self.colend:]
4130 4156 while rest != '':
4131 4157 match = regexp.search(rest)
4132 4158 if not match:
4133 4159 yield (rest, '')
4134 4160 break
4135 4161 mstart, mend = match.span()
4136 4162 yield (rest[:mstart], '')
4137 4163 yield (rest[mstart:mend], 'grep.match')
4138 4164 rest = rest[mend:]
4139 4165
4140 4166 matches = {}
4141 4167 copies = {}
4142 4168 def grepbody(fn, rev, body):
4143 4169 matches[rev].setdefault(fn, [])
4144 4170 m = matches[rev][fn]
4145 4171 for lnum, cstart, cend, line in matchlines(body):
4146 4172 s = linestate(line, lnum, cstart, cend)
4147 4173 m.append(s)
4148 4174
4149 4175 def difflinestates(a, b):
4150 4176 sm = difflib.SequenceMatcher(None, a, b)
4151 4177 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4152 4178 if tag == 'insert':
4153 4179 for i in xrange(blo, bhi):
4154 4180 yield ('+', b[i])
4155 4181 elif tag == 'delete':
4156 4182 for i in xrange(alo, ahi):
4157 4183 yield ('-', a[i])
4158 4184 elif tag == 'replace':
4159 4185 for i in xrange(alo, ahi):
4160 4186 yield ('-', a[i])
4161 4187 for i in xrange(blo, bhi):
4162 4188 yield ('+', b[i])
4163 4189
4164 4190 def display(fn, ctx, pstates, states):
4165 4191 rev = ctx.rev()
4166 4192 if ui.quiet:
4167 4193 datefunc = util.shortdate
4168 4194 else:
4169 4195 datefunc = util.datestr
4170 4196 found = False
4171 4197 @util.cachefunc
4172 4198 def binary():
4173 4199 flog = getfile(fn)
4174 4200 return util.binary(flog.read(ctx.filenode(fn)))
4175 4201
4176 4202 if opts.get('all'):
4177 4203 iter = difflinestates(pstates, states)
4178 4204 else:
4179 4205 iter = [('', l) for l in states]
4180 4206 for change, l in iter:
4181 4207 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4182 4208
4183 4209 if opts.get('line_number'):
4184 4210 cols.append((str(l.linenum), 'grep.linenumber'))
4185 4211 if opts.get('all'):
4186 4212 cols.append((change, 'grep.change'))
4187 4213 if opts.get('user'):
4188 4214 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4189 4215 if opts.get('date'):
4190 4216 cols.append((datefunc(ctx.date()), 'grep.date'))
4191 4217 for col, label in cols[:-1]:
4192 4218 ui.write(col, label=label)
4193 4219 ui.write(sep, label='grep.sep')
4194 4220 ui.write(cols[-1][0], label=cols[-1][1])
4195 4221 if not opts.get('files_with_matches'):
4196 4222 ui.write(sep, label='grep.sep')
4197 4223 if not opts.get('text') and binary():
4198 4224 ui.write(" Binary file matches")
4199 4225 else:
4200 4226 for s, label in l:
4201 4227 ui.write(s, label=label)
4202 4228 ui.write(eol)
4203 4229 found = True
4204 4230 if opts.get('files_with_matches'):
4205 4231 break
4206 4232 return found
4207 4233
4208 4234 skip = {}
4209 4235 revfiles = {}
4210 4236 matchfn = scmutil.match(repo[None], pats, opts)
4211 4237 found = False
4212 4238 follow = opts.get('follow')
4213 4239
4214 4240 def prep(ctx, fns):
4215 4241 rev = ctx.rev()
4216 4242 pctx = ctx.p1()
4217 4243 parent = pctx.rev()
4218 4244 matches.setdefault(rev, {})
4219 4245 matches.setdefault(parent, {})
4220 4246 files = revfiles.setdefault(rev, [])
4221 4247 for fn in fns:
4222 4248 flog = getfile(fn)
4223 4249 try:
4224 4250 fnode = ctx.filenode(fn)
4225 4251 except error.LookupError:
4226 4252 continue
4227 4253
4228 4254 copied = flog.renamed(fnode)
4229 4255 copy = follow and copied and copied[0]
4230 4256 if copy:
4231 4257 copies.setdefault(rev, {})[fn] = copy
4232 4258 if fn in skip:
4233 4259 if copy:
4234 4260 skip[copy] = True
4235 4261 continue
4236 4262 files.append(fn)
4237 4263
4238 4264 if fn not in matches[rev]:
4239 4265 grepbody(fn, rev, flog.read(fnode))
4240 4266
4241 4267 pfn = copy or fn
4242 4268 if pfn not in matches[parent]:
4243 4269 try:
4244 4270 fnode = pctx.filenode(pfn)
4245 4271 grepbody(pfn, parent, flog.read(fnode))
4246 4272 except error.LookupError:
4247 4273 pass
4248 4274
4249 4275 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4250 4276 rev = ctx.rev()
4251 4277 parent = ctx.p1().rev()
4252 4278 for fn in sorted(revfiles.get(rev, [])):
4253 4279 states = matches[rev][fn]
4254 4280 copy = copies.get(rev, {}).get(fn)
4255 4281 if fn in skip:
4256 4282 if copy:
4257 4283 skip[copy] = True
4258 4284 continue
4259 4285 pstates = matches.get(parent, {}).get(copy or fn, [])
4260 4286 if pstates or states:
4261 4287 r = display(fn, ctx, pstates, states)
4262 4288 found = found or r
4263 4289 if r and not opts.get('all'):
4264 4290 skip[fn] = True
4265 4291 if copy:
4266 4292 skip[copy] = True
4267 4293 del matches[rev]
4268 4294 del revfiles[rev]
4269 4295
4270 4296 return not found
4271 4297
4272 4298 @command('heads',
4273 4299 [('r', 'rev', '',
4274 4300 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4275 4301 ('t', 'topo', False, _('show topological heads only')),
4276 4302 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4277 4303 ('c', 'closed', False, _('show normal and closed branch heads')),
4278 4304 ] + templateopts,
4279 4305 _('[-ct] [-r STARTREV] [REV]...'))
4280 4306 def heads(ui, repo, *branchrevs, **opts):
4281 4307 """show branch heads
4282 4308
4283 4309 With no arguments, show all open branch heads in the repository.
4284 4310 Branch heads are changesets that have no descendants on the
4285 4311 same branch. They are where development generally takes place and
4286 4312 are the usual targets for update and merge operations.
4287 4313
4288 4314 If one or more REVs are given, only open branch heads on the
4289 4315 branches associated with the specified changesets are shown. This
4290 4316 means that you can use :hg:`heads .` to see the heads on the
4291 4317 currently checked-out branch.
4292 4318
4293 4319 If -c/--closed is specified, also show branch heads marked closed
4294 4320 (see :hg:`commit --close-branch`).
4295 4321
4296 4322 If STARTREV is specified, only those heads that are descendants of
4297 4323 STARTREV will be displayed.
4298 4324
4299 4325 If -t/--topo is specified, named branch mechanics will be ignored and only
4300 4326 topological heads (changesets with no children) will be shown.
4301 4327
4302 4328 Returns 0 if matching heads are found, 1 if not.
4303 4329 """
4304 4330
4305 4331 start = None
4306 4332 if 'rev' in opts:
4307 4333 start = scmutil.revsingle(repo, opts['rev'], None).node()
4308 4334
4309 4335 if opts.get('topo'):
4310 4336 heads = [repo[h] for h in repo.heads(start)]
4311 4337 else:
4312 4338 heads = []
4313 4339 for branch in repo.branchmap():
4314 4340 heads += repo.branchheads(branch, start, opts.get('closed'))
4315 4341 heads = [repo[h] for h in heads]
4316 4342
4317 4343 if branchrevs:
4318 4344 branches = set(repo[br].branch() for br in branchrevs)
4319 4345 heads = [h for h in heads if h.branch() in branches]
4320 4346
4321 4347 if opts.get('active') and branchrevs:
4322 4348 dagheads = repo.heads(start)
4323 4349 heads = [h for h in heads if h.node() in dagheads]
4324 4350
4325 4351 if branchrevs:
4326 4352 haveheads = set(h.branch() for h in heads)
4327 4353 if branches - haveheads:
4328 4354 headless = ', '.join(b for b in branches - haveheads)
4329 4355 msg = _('no open branch heads found on branches %s')
4330 4356 if opts.get('rev'):
4331 4357 msg += _(' (started at %s)') % opts['rev']
4332 4358 ui.warn((msg + '\n') % headless)
4333 4359
4334 4360 if not heads:
4335 4361 return 1
4336 4362
4337 4363 heads = sorted(heads, key=lambda x: -x.rev())
4338 4364 displayer = cmdutil.show_changeset(ui, repo, opts)
4339 4365 for ctx in heads:
4340 4366 displayer.show(ctx)
4341 4367 displayer.close()
4342 4368
4343 4369 @command('help',
4344 4370 [('e', 'extension', None, _('show only help for extensions')),
4345 4371 ('c', 'command', None, _('show only help for commands')),
4346 4372 ('k', 'keyword', None, _('show topics matching keyword')),
4347 4373 ],
4348 4374 _('[-eck] [TOPIC]'),
4349 4375 norepo=True)
4350 4376 def help_(ui, name=None, **opts):
4351 4377 """show help for a given topic or a help overview
4352 4378
4353 4379 With no arguments, print a list of commands with short help messages.
4354 4380
4355 4381 Given a topic, extension, or command name, print help for that
4356 4382 topic.
4357 4383
4358 4384 Returns 0 if successful.
4359 4385 """
4360 4386
4361 4387 textwidth = min(ui.termwidth(), 80) - 2
4362 4388
4363 4389 keep = []
4364 4390 if ui.verbose:
4365 4391 keep.append('verbose')
4366 4392 if sys.platform.startswith('win'):
4367 4393 keep.append('windows')
4368 4394 elif sys.platform == 'OpenVMS':
4369 4395 keep.append('vms')
4370 4396 elif sys.platform == 'plan9':
4371 4397 keep.append('plan9')
4372 4398 else:
4373 4399 keep.append('unix')
4374 4400 keep.append(sys.platform.lower())
4375 4401
4376 4402 section = None
4377 4403 subtopic = None
4378 4404 if name and '.' in name:
4379 4405 name, section = name.split('.', 1)
4380 4406 section = section.lower()
4381 4407 if '.' in section:
4382 4408 subtopic, section = section.split('.', 1)
4383 4409 else:
4384 4410 subtopic = section
4385 4411
4386 4412 text = help.help_(ui, name, subtopic=subtopic, **opts)
4387 4413
4388 4414 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4389 4415 section=section)
4390 4416
4391 4417 # We could have been given a weird ".foo" section without a name
4392 4418 # to look for, or we could have simply failed to found "foo.bar"
4393 4419 # because bar isn't a section of foo
4394 4420 if section and not (formatted and name):
4395 4421 raise error.Abort(_("help section not found"))
4396 4422
4397 4423 if 'verbose' in pruned:
4398 4424 keep.append('omitted')
4399 4425 else:
4400 4426 keep.append('notomitted')
4401 4427 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4402 4428 section=section)
4403 4429 ui.write(formatted)
4404 4430
4405 4431
4406 4432 @command('identify|id',
4407 4433 [('r', 'rev', '',
4408 4434 _('identify the specified revision'), _('REV')),
4409 4435 ('n', 'num', None, _('show local revision number')),
4410 4436 ('i', 'id', None, _('show global revision id')),
4411 4437 ('b', 'branch', None, _('show branch')),
4412 4438 ('t', 'tags', None, _('show tags')),
4413 4439 ('B', 'bookmarks', None, _('show bookmarks')),
4414 4440 ] + remoteopts,
4415 4441 _('[-nibtB] [-r REV] [SOURCE]'),
4416 4442 optionalrepo=True)
4417 4443 def identify(ui, repo, source=None, rev=None,
4418 4444 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4419 4445 """identify the working directory or specified revision
4420 4446
4421 4447 Print a summary identifying the repository state at REV using one or
4422 4448 two parent hash identifiers, followed by a "+" if the working
4423 4449 directory has uncommitted changes, the branch name (if not default),
4424 4450 a list of tags, and a list of bookmarks.
4425 4451
4426 4452 When REV is not given, print a summary of the current state of the
4427 4453 repository.
4428 4454
4429 4455 Specifying a path to a repository root or Mercurial bundle will
4430 4456 cause lookup to operate on that repository/bundle.
4431 4457
4432 4458 .. container:: verbose
4433 4459
4434 4460 Examples:
4435 4461
4436 4462 - generate a build identifier for the working directory::
4437 4463
4438 4464 hg id --id > build-id.dat
4439 4465
4440 4466 - find the revision corresponding to a tag::
4441 4467
4442 4468 hg id -n -r 1.3
4443 4469
4444 4470 - check the most recent revision of a remote repository::
4445 4471
4446 4472 hg id -r tip http://selenic.com/hg/
4447 4473
4448 4474 See :hg:`log` for generating more information about specific revisions,
4449 4475 including full hash identifiers.
4450 4476
4451 4477 Returns 0 if successful.
4452 4478 """
4453 4479
4454 4480 if not repo and not source:
4455 4481 raise error.Abort(_("there is no Mercurial repository here "
4456 4482 "(.hg not found)"))
4457 4483
4458 4484 if ui.debugflag:
4459 4485 hexfunc = hex
4460 4486 else:
4461 4487 hexfunc = short
4462 4488 default = not (num or id or branch or tags or bookmarks)
4463 4489 output = []
4464 4490 revs = []
4465 4491
4466 4492 if source:
4467 4493 source, branches = hg.parseurl(ui.expandpath(source))
4468 4494 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4469 4495 repo = peer.local()
4470 4496 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4471 4497
4472 4498 if not repo:
4473 4499 if num or branch or tags:
4474 4500 raise error.Abort(
4475 4501 _("can't query remote revision number, branch, or tags"))
4476 4502 if not rev and revs:
4477 4503 rev = revs[0]
4478 4504 if not rev:
4479 4505 rev = "tip"
4480 4506
4481 4507 remoterev = peer.lookup(rev)
4482 4508 if default or id:
4483 4509 output = [hexfunc(remoterev)]
4484 4510
4485 4511 def getbms():
4486 4512 bms = []
4487 4513
4488 4514 if 'bookmarks' in peer.listkeys('namespaces'):
4489 4515 hexremoterev = hex(remoterev)
4490 4516 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4491 4517 if bmr == hexremoterev]
4492 4518
4493 4519 return sorted(bms)
4494 4520
4495 4521 if bookmarks:
4496 4522 output.extend(getbms())
4497 4523 elif default and not ui.quiet:
4498 4524 # multiple bookmarks for a single parent separated by '/'
4499 4525 bm = '/'.join(getbms())
4500 4526 if bm:
4501 4527 output.append(bm)
4502 4528 else:
4503 4529 ctx = scmutil.revsingle(repo, rev, None)
4504 4530
4505 4531 if ctx.rev() is None:
4506 4532 ctx = repo[None]
4507 4533 parents = ctx.parents()
4508 4534 taglist = []
4509 4535 for p in parents:
4510 4536 taglist.extend(p.tags())
4511 4537
4512 4538 changed = ""
4513 4539 if default or id or num:
4514 4540 if (any(repo.status())
4515 4541 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4516 4542 changed = '+'
4517 4543 if default or id:
4518 4544 output = ["%s%s" %
4519 4545 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4520 4546 if num:
4521 4547 output.append("%s%s" %
4522 4548 ('+'.join([str(p.rev()) for p in parents]), changed))
4523 4549 else:
4524 4550 if default or id:
4525 4551 output = [hexfunc(ctx.node())]
4526 4552 if num:
4527 4553 output.append(str(ctx.rev()))
4528 4554 taglist = ctx.tags()
4529 4555
4530 4556 if default and not ui.quiet:
4531 4557 b = ctx.branch()
4532 4558 if b != 'default':
4533 4559 output.append("(%s)" % b)
4534 4560
4535 4561 # multiple tags for a single parent separated by '/'
4536 4562 t = '/'.join(taglist)
4537 4563 if t:
4538 4564 output.append(t)
4539 4565
4540 4566 # multiple bookmarks for a single parent separated by '/'
4541 4567 bm = '/'.join(ctx.bookmarks())
4542 4568 if bm:
4543 4569 output.append(bm)
4544 4570 else:
4545 4571 if branch:
4546 4572 output.append(ctx.branch())
4547 4573
4548 4574 if tags:
4549 4575 output.extend(taglist)
4550 4576
4551 4577 if bookmarks:
4552 4578 output.extend(ctx.bookmarks())
4553 4579
4554 4580 ui.write("%s\n" % ' '.join(output))
4555 4581
4556 4582 @command('import|patch',
4557 4583 [('p', 'strip', 1,
4558 4584 _('directory strip option for patch. This has the same '
4559 4585 'meaning as the corresponding patch option'), _('NUM')),
4560 4586 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4561 4587 ('e', 'edit', False, _('invoke editor on commit messages')),
4562 4588 ('f', 'force', None,
4563 4589 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4564 4590 ('', 'no-commit', None,
4565 4591 _("don't commit, just update the working directory")),
4566 4592 ('', 'bypass', None,
4567 4593 _("apply patch without touching the working directory")),
4568 4594 ('', 'partial', None,
4569 4595 _('commit even if some hunks fail')),
4570 4596 ('', 'exact', None,
4571 4597 _('apply patch to the nodes from which it was generated')),
4572 4598 ('', 'prefix', '',
4573 4599 _('apply patch to subdirectory'), _('DIR')),
4574 4600 ('', 'import-branch', None,
4575 4601 _('use any branch information in patch (implied by --exact)'))] +
4576 4602 commitopts + commitopts2 + similarityopts,
4577 4603 _('[OPTION]... PATCH...'))
4578 4604 def import_(ui, repo, patch1=None, *patches, **opts):
4579 4605 """import an ordered set of patches
4580 4606
4581 4607 Import a list of patches and commit them individually (unless
4582 4608 --no-commit is specified).
4583 4609
4584 4610 To read a patch from standard input, use "-" as the patch name. If
4585 4611 a URL is specified, the patch will be downloaded from there.
4586 4612
4587 4613 Import first applies changes to the working directory (unless
4588 4614 --bypass is specified), import will abort if there are outstanding
4589 4615 changes.
4590 4616
4591 4617 Use --bypass to apply and commit patches directly to the
4592 4618 repository, without affecting the working directory. Without
4593 4619 --exact, patches will be applied on top of the working directory
4594 4620 parent revision.
4595 4621
4596 4622 You can import a patch straight from a mail message. Even patches
4597 4623 as attachments work (to use the body part, it must have type
4598 4624 text/plain or text/x-patch). From and Subject headers of email
4599 4625 message are used as default committer and commit message. All
4600 4626 text/plain body parts before first diff are added to the commit
4601 4627 message.
4602 4628
4603 4629 If the imported patch was generated by :hg:`export`, user and
4604 4630 description from patch override values from message headers and
4605 4631 body. Values given on command line with -m/--message and -u/--user
4606 4632 override these.
4607 4633
4608 4634 If --exact is specified, import will set the working directory to
4609 4635 the parent of each patch before applying it, and will abort if the
4610 4636 resulting changeset has a different ID than the one recorded in
4611 4637 the patch. This may happen due to character set problems or other
4612 4638 deficiencies in the text patch format.
4613 4639
4614 4640 Use --partial to ensure a changeset will be created from the patch
4615 4641 even if some hunks fail to apply. Hunks that fail to apply will be
4616 4642 written to a <target-file>.rej file. Conflicts can then be resolved
4617 4643 by hand before :hg:`commit --amend` is run to update the created
4618 4644 changeset. This flag exists to let people import patches that
4619 4645 partially apply without losing the associated metadata (author,
4620 4646 date, description, ...).
4621 4647
4622 4648 .. note::
4623 4649
4624 4650 When no hunks apply cleanly, :hg:`import --partial` will create
4625 4651 an empty changeset, importing only the patch metadata.
4626 4652
4627 4653 With -s/--similarity, hg will attempt to discover renames and
4628 4654 copies in the patch in the same way as :hg:`addremove`.
4629 4655
4630 4656 It is possible to use external patch programs to perform the patch
4631 4657 by setting the ``ui.patch`` configuration option. For the default
4632 4658 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4633 4659 See :hg:`help config` for more information about configuration
4634 4660 files and how to use these options.
4635 4661
4636 4662 See :hg:`help dates` for a list of formats valid for -d/--date.
4637 4663
4638 4664 .. container:: verbose
4639 4665
4640 4666 Examples:
4641 4667
4642 4668 - import a traditional patch from a website and detect renames::
4643 4669
4644 4670 hg import -s 80 http://example.com/bugfix.patch
4645 4671
4646 4672 - import a changeset from an hgweb server::
4647 4673
4648 4674 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4649 4675
4650 4676 - import all the patches in an Unix-style mbox::
4651 4677
4652 4678 hg import incoming-patches.mbox
4653 4679
4654 4680 - attempt to exactly restore an exported changeset (not always
4655 4681 possible)::
4656 4682
4657 4683 hg import --exact proposed-fix.patch
4658 4684
4659 4685 - use an external tool to apply a patch which is too fuzzy for
4660 4686 the default internal tool.
4661 4687
4662 4688 hg import --config ui.patch="patch --merge" fuzzy.patch
4663 4689
4664 4690 - change the default fuzzing from 2 to a less strict 7
4665 4691
4666 4692 hg import --config ui.fuzz=7 fuzz.patch
4667 4693
4668 4694 Returns 0 on success, 1 on partial success (see --partial).
4669 4695 """
4670 4696
4671 4697 if not patch1:
4672 4698 raise error.Abort(_('need at least one patch to import'))
4673 4699
4674 4700 patches = (patch1,) + patches
4675 4701
4676 4702 date = opts.get('date')
4677 4703 if date:
4678 4704 opts['date'] = util.parsedate(date)
4679 4705
4680 4706 exact = opts.get('exact')
4681 4707 update = not opts.get('bypass')
4682 4708 if not update and opts.get('no_commit'):
4683 4709 raise error.Abort(_('cannot use --no-commit with --bypass'))
4684 4710 try:
4685 4711 sim = float(opts.get('similarity') or 0)
4686 4712 except ValueError:
4687 4713 raise error.Abort(_('similarity must be a number'))
4688 4714 if sim < 0 or sim > 100:
4689 4715 raise error.Abort(_('similarity must be between 0 and 100'))
4690 4716 if sim and not update:
4691 4717 raise error.Abort(_('cannot use --similarity with --bypass'))
4692 4718 if exact:
4693 4719 if opts.get('edit'):
4694 4720 raise error.Abort(_('cannot use --exact with --edit'))
4695 4721 if opts.get('prefix'):
4696 4722 raise error.Abort(_('cannot use --exact with --prefix'))
4697 4723
4698 4724 base = opts["base"]
4699 4725 wlock = dsguard = lock = tr = None
4700 4726 msgs = []
4701 4727 ret = 0
4702 4728
4703 4729
4704 4730 try:
4705 4731 try:
4706 4732 wlock = repo.wlock()
4707 4733
4708 4734 if update:
4709 4735 cmdutil.checkunfinished(repo)
4710 4736 if (exact or not opts.get('force')):
4711 4737 cmdutil.bailifchanged(repo)
4712 4738
4713 4739 if not opts.get('no_commit'):
4714 4740 lock = repo.lock()
4715 4741 tr = repo.transaction('import')
4716 4742 else:
4717 4743 dsguard = cmdutil.dirstateguard(repo, 'import')
4718 4744 parents = repo[None].parents()
4719 4745 for patchurl in patches:
4720 4746 if patchurl == '-':
4721 4747 ui.status(_('applying patch from stdin\n'))
4722 4748 patchfile = ui.fin
4723 4749 patchurl = 'stdin' # for error message
4724 4750 else:
4725 4751 patchurl = os.path.join(base, patchurl)
4726 4752 ui.status(_('applying %s\n') % patchurl)
4727 4753 patchfile = hg.openpath(ui, patchurl)
4728 4754
4729 4755 haspatch = False
4730 4756 for hunk in patch.split(patchfile):
4731 4757 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4732 4758 parents, opts,
4733 4759 msgs, hg.clean)
4734 4760 if msg:
4735 4761 haspatch = True
4736 4762 ui.note(msg + '\n')
4737 4763 if update or exact:
4738 4764 parents = repo[None].parents()
4739 4765 else:
4740 4766 parents = [repo[node]]
4741 4767 if rej:
4742 4768 ui.write_err(_("patch applied partially\n"))
4743 4769 ui.write_err(_("(fix the .rej files and run "
4744 4770 "`hg commit --amend`)\n"))
4745 4771 ret = 1
4746 4772 break
4747 4773
4748 4774 if not haspatch:
4749 4775 raise error.Abort(_('%s: no diffs found') % patchurl)
4750 4776
4751 4777 if tr:
4752 4778 tr.close()
4753 4779 if msgs:
4754 4780 repo.savecommitmessage('\n* * *\n'.join(msgs))
4755 4781 if dsguard:
4756 4782 dsguard.close()
4757 4783 return ret
4758 4784 finally:
4759 4785 # TODO: get rid of this meaningless try/finally enclosing.
4760 4786 # this is kept only to reduce changes in a patch.
4761 4787 pass
4762 4788 finally:
4763 4789 if tr:
4764 4790 tr.release()
4765 4791 release(lock, dsguard, wlock)
4766 4792
4767 4793 @command('incoming|in',
4768 4794 [('f', 'force', None,
4769 4795 _('run even if remote repository is unrelated')),
4770 4796 ('n', 'newest-first', None, _('show newest record first')),
4771 4797 ('', 'bundle', '',
4772 4798 _('file to store the bundles into'), _('FILE')),
4773 4799 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4774 4800 ('B', 'bookmarks', False, _("compare bookmarks")),
4775 4801 ('b', 'branch', [],
4776 4802 _('a specific branch you would like to pull'), _('BRANCH')),
4777 4803 ] + logopts + remoteopts + subrepoopts,
4778 4804 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4779 4805 def incoming(ui, repo, source="default", **opts):
4780 4806 """show new changesets found in source
4781 4807
4782 4808 Show new changesets found in the specified path/URL or the default
4783 4809 pull location. These are the changesets that would have been pulled
4784 4810 if a pull at the time you issued this command.
4785 4811
4786 4812 See pull for valid source format details.
4787 4813
4788 4814 .. container:: verbose
4789 4815
4790 4816 With -B/--bookmarks, the result of bookmark comparison between
4791 4817 local and remote repositories is displayed. With -v/--verbose,
4792 4818 status is also displayed for each bookmark like below::
4793 4819
4794 4820 BM1 01234567890a added
4795 4821 BM2 1234567890ab advanced
4796 4822 BM3 234567890abc diverged
4797 4823 BM4 34567890abcd changed
4798 4824
4799 4825 The action taken locally when pulling depends on the
4800 4826 status of each bookmark:
4801 4827
4802 4828 :``added``: pull will create it
4803 4829 :``advanced``: pull will update it
4804 4830 :``diverged``: pull will create a divergent bookmark
4805 4831 :``changed``: result depends on remote changesets
4806 4832
4807 4833 From the point of view of pulling behavior, bookmark
4808 4834 existing only in the remote repository are treated as ``added``,
4809 4835 even if it is in fact locally deleted.
4810 4836
4811 4837 .. container:: verbose
4812 4838
4813 4839 For remote repository, using --bundle avoids downloading the
4814 4840 changesets twice if the incoming is followed by a pull.
4815 4841
4816 4842 Examples:
4817 4843
4818 4844 - show incoming changes with patches and full description::
4819 4845
4820 4846 hg incoming -vp
4821 4847
4822 4848 - show incoming changes excluding merges, store a bundle::
4823 4849
4824 4850 hg in -vpM --bundle incoming.hg
4825 4851 hg pull incoming.hg
4826 4852
4827 4853 - briefly list changes inside a bundle::
4828 4854
4829 4855 hg in changes.hg -T "{desc|firstline}\\n"
4830 4856
4831 4857 Returns 0 if there are incoming changes, 1 otherwise.
4832 4858 """
4833 4859 if opts.get('graph'):
4834 4860 cmdutil.checkunsupportedgraphflags([], opts)
4835 4861 def display(other, chlist, displayer):
4836 4862 revdag = cmdutil.graphrevs(other, chlist, opts)
4837 4863 cmdutil.displaygraph(ui, repo, revdag, displayer,
4838 4864 graphmod.asciiedges)
4839 4865
4840 4866 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4841 4867 return 0
4842 4868
4843 4869 if opts.get('bundle') and opts.get('subrepos'):
4844 4870 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4845 4871
4846 4872 if opts.get('bookmarks'):
4847 4873 source, branches = hg.parseurl(ui.expandpath(source),
4848 4874 opts.get('branch'))
4849 4875 other = hg.peer(repo, opts, source)
4850 4876 if 'bookmarks' not in other.listkeys('namespaces'):
4851 4877 ui.warn(_("remote doesn't support bookmarks\n"))
4852 4878 return 0
4853 4879 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4854 4880 return bookmarks.incoming(ui, repo, other)
4855 4881
4856 4882 repo._subtoppath = ui.expandpath(source)
4857 4883 try:
4858 4884 return hg.incoming(ui, repo, source, opts)
4859 4885 finally:
4860 4886 del repo._subtoppath
4861 4887
4862 4888
4863 4889 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4864 4890 norepo=True)
4865 4891 def init(ui, dest=".", **opts):
4866 4892 """create a new repository in the given directory
4867 4893
4868 4894 Initialize a new repository in the given directory. If the given
4869 4895 directory does not exist, it will be created.
4870 4896
4871 4897 If no directory is given, the current directory is used.
4872 4898
4873 4899 It is possible to specify an ``ssh://`` URL as the destination.
4874 4900 See :hg:`help urls` for more information.
4875 4901
4876 4902 Returns 0 on success.
4877 4903 """
4878 4904 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4879 4905
4880 4906 @command('locate',
4881 4907 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4882 4908 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4883 4909 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4884 4910 ] + walkopts,
4885 4911 _('[OPTION]... [PATTERN]...'))
4886 4912 def locate(ui, repo, *pats, **opts):
4887 4913 """locate files matching specific patterns (DEPRECATED)
4888 4914
4889 4915 Print files under Mercurial control in the working directory whose
4890 4916 names match the given patterns.
4891 4917
4892 4918 By default, this command searches all directories in the working
4893 4919 directory. To search just the current directory and its
4894 4920 subdirectories, use "--include .".
4895 4921
4896 4922 If no patterns are given to match, this command prints the names
4897 4923 of all files under Mercurial control in the working directory.
4898 4924
4899 4925 If you want to feed the output of this command into the "xargs"
4900 4926 command, use the -0 option to both this command and "xargs". This
4901 4927 will avoid the problem of "xargs" treating single filenames that
4902 4928 contain whitespace as multiple filenames.
4903 4929
4904 4930 See :hg:`help files` for a more versatile command.
4905 4931
4906 4932 Returns 0 if a match is found, 1 otherwise.
4907 4933 """
4908 4934 if opts.get('print0'):
4909 4935 end = '\0'
4910 4936 else:
4911 4937 end = '\n'
4912 4938 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4913 4939
4914 4940 ret = 1
4915 4941 ctx = repo[rev]
4916 4942 m = scmutil.match(ctx, pats, opts, default='relglob',
4917 4943 badfn=lambda x, y: False)
4918 4944
4919 4945 for abs in ctx.matches(m):
4920 4946 if opts.get('fullpath'):
4921 4947 ui.write(repo.wjoin(abs), end)
4922 4948 else:
4923 4949 ui.write(((pats and m.rel(abs)) or abs), end)
4924 4950 ret = 0
4925 4951
4926 4952 return ret
4927 4953
4928 4954 @command('^log|history',
4929 4955 [('f', 'follow', None,
4930 4956 _('follow changeset history, or file history across copies and renames')),
4931 4957 ('', 'follow-first', None,
4932 4958 _('only follow the first parent of merge changesets (DEPRECATED)')),
4933 4959 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4934 4960 ('C', 'copies', None, _('show copied files')),
4935 4961 ('k', 'keyword', [],
4936 4962 _('do case-insensitive search for a given text'), _('TEXT')),
4937 4963 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4938 4964 ('', 'removed', None, _('include revisions where files were removed')),
4939 4965 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4940 4966 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4941 4967 ('', 'only-branch', [],
4942 4968 _('show only changesets within the given named branch (DEPRECATED)'),
4943 4969 _('BRANCH')),
4944 4970 ('b', 'branch', [],
4945 4971 _('show changesets within the given named branch'), _('BRANCH')),
4946 4972 ('P', 'prune', [],
4947 4973 _('do not display revision or any of its ancestors'), _('REV')),
4948 4974 ] + logopts + walkopts,
4949 4975 _('[OPTION]... [FILE]'),
4950 4976 inferrepo=True)
4951 4977 def log(ui, repo, *pats, **opts):
4952 4978 """show revision history of entire repository or files
4953 4979
4954 4980 Print the revision history of the specified files or the entire
4955 4981 project.
4956 4982
4957 4983 If no revision range is specified, the default is ``tip:0`` unless
4958 4984 --follow is set, in which case the working directory parent is
4959 4985 used as the starting revision.
4960 4986
4961 4987 File history is shown without following rename or copy history of
4962 4988 files. Use -f/--follow with a filename to follow history across
4963 4989 renames and copies. --follow without a filename will only show
4964 4990 ancestors or descendants of the starting revision.
4965 4991
4966 4992 By default this command prints revision number and changeset id,
4967 4993 tags, non-trivial parents, user, date and time, and a summary for
4968 4994 each commit. When the -v/--verbose switch is used, the list of
4969 4995 changed files and full commit message are shown.
4970 4996
4971 4997 With --graph the revisions are shown as an ASCII art DAG with the most
4972 4998 recent changeset at the top.
4973 4999 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4974 5000 and '+' represents a fork where the changeset from the lines below is a
4975 5001 parent of the 'o' merge on the same line.
4976 5002
4977 5003 .. note::
4978 5004
4979 5005 :hg:`log --patch` may generate unexpected diff output for merge
4980 5006 changesets, as it will only compare the merge changeset against
4981 5007 its first parent. Also, only files different from BOTH parents
4982 5008 will appear in files:.
4983 5009
4984 5010 .. note::
4985 5011
4986 5012 For performance reasons, :hg:`log FILE` may omit duplicate changes
4987 5013 made on branches and will not show removals or mode changes. To
4988 5014 see all such changes, use the --removed switch.
4989 5015
4990 5016 .. container:: verbose
4991 5017
4992 5018 Some examples:
4993 5019
4994 5020 - changesets with full descriptions and file lists::
4995 5021
4996 5022 hg log -v
4997 5023
4998 5024 - changesets ancestral to the working directory::
4999 5025
5000 5026 hg log -f
5001 5027
5002 5028 - last 10 commits on the current branch::
5003 5029
5004 5030 hg log -l 10 -b .
5005 5031
5006 5032 - changesets showing all modifications of a file, including removals::
5007 5033
5008 5034 hg log --removed file.c
5009 5035
5010 5036 - all changesets that touch a directory, with diffs, excluding merges::
5011 5037
5012 5038 hg log -Mp lib/
5013 5039
5014 5040 - all revision numbers that match a keyword::
5015 5041
5016 5042 hg log -k bug --template "{rev}\\n"
5017 5043
5018 5044 - the full hash identifier of the working directory parent::
5019 5045
5020 5046 hg log -r . --template "{node}\\n"
5021 5047
5022 5048 - list available log templates::
5023 5049
5024 5050 hg log -T list
5025 5051
5026 5052 - check if a given changeset is included in a tagged release::
5027 5053
5028 5054 hg log -r "a21ccf and ancestor(1.9)"
5029 5055
5030 5056 - find all changesets by some user in a date range::
5031 5057
5032 5058 hg log -k alice -d "may 2008 to jul 2008"
5033 5059
5034 5060 - summary of all changesets after the last tag::
5035 5061
5036 5062 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5037 5063
5038 5064 See :hg:`help dates` for a list of formats valid for -d/--date.
5039 5065
5040 5066 See :hg:`help revisions` and :hg:`help revsets` for more about
5041 5067 specifying and ordering revisions.
5042 5068
5043 5069 See :hg:`help templates` for more about pre-packaged styles and
5044 5070 specifying custom templates.
5045 5071
5046 5072 Returns 0 on success.
5047 5073
5048 5074 """
5049 5075 if opts.get('follow') and opts.get('rev'):
5050 5076 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5051 5077 del opts['follow']
5052 5078
5053 5079 if opts.get('graph'):
5054 5080 return cmdutil.graphlog(ui, repo, *pats, **opts)
5055 5081
5056 5082 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5057 5083 limit = cmdutil.loglimit(opts)
5058 5084 count = 0
5059 5085
5060 5086 getrenamed = None
5061 5087 if opts.get('copies'):
5062 5088 endrev = None
5063 5089 if opts.get('rev'):
5064 5090 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5065 5091 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5066 5092
5067 5093 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5068 5094 for rev in revs:
5069 5095 if count == limit:
5070 5096 break
5071 5097 ctx = repo[rev]
5072 5098 copies = None
5073 5099 if getrenamed is not None and rev:
5074 5100 copies = []
5075 5101 for fn in ctx.files():
5076 5102 rename = getrenamed(fn, rev)
5077 5103 if rename:
5078 5104 copies.append((fn, rename[0]))
5079 5105 if filematcher:
5080 5106 revmatchfn = filematcher(ctx.rev())
5081 5107 else:
5082 5108 revmatchfn = None
5083 5109 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5084 5110 if displayer.flush(ctx):
5085 5111 count += 1
5086 5112
5087 5113 displayer.close()
5088 5114
5089 5115 @command('manifest',
5090 5116 [('r', 'rev', '', _('revision to display'), _('REV')),
5091 5117 ('', 'all', False, _("list files from all revisions"))]
5092 5118 + formatteropts,
5093 5119 _('[-r REV]'))
5094 5120 def manifest(ui, repo, node=None, rev=None, **opts):
5095 5121 """output the current or given revision of the project manifest
5096 5122
5097 5123 Print a list of version controlled files for the given revision.
5098 5124 If no revision is given, the first parent of the working directory
5099 5125 is used, or the null revision if no revision is checked out.
5100 5126
5101 5127 With -v, print file permissions, symlink and executable bits.
5102 5128 With --debug, print file revision hashes.
5103 5129
5104 5130 If option --all is specified, the list of all files from all revisions
5105 5131 is printed. This includes deleted and renamed files.
5106 5132
5107 5133 Returns 0 on success.
5108 5134 """
5109 5135
5110 5136 fm = ui.formatter('manifest', opts)
5111 5137
5112 5138 if opts.get('all'):
5113 5139 if rev or node:
5114 5140 raise error.Abort(_("can't specify a revision with --all"))
5115 5141
5116 5142 res = []
5117 5143 prefix = "data/"
5118 5144 suffix = ".i"
5119 5145 plen = len(prefix)
5120 5146 slen = len(suffix)
5121 5147 lock = repo.lock()
5122 5148 try:
5123 5149 for fn, b, size in repo.store.datafiles():
5124 5150 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5125 5151 res.append(fn[plen:-slen])
5126 5152 finally:
5127 5153 lock.release()
5128 5154 for f in res:
5129 5155 fm.startitem()
5130 5156 fm.write("path", '%s\n', f)
5131 5157 fm.end()
5132 5158 return
5133 5159
5134 5160 if rev and node:
5135 5161 raise error.Abort(_("please specify just one revision"))
5136 5162
5137 5163 if not node:
5138 5164 node = rev
5139 5165
5140 5166 char = {'l': '@', 'x': '*', '': ''}
5141 5167 mode = {'l': '644', 'x': '755', '': '644'}
5142 5168 ctx = scmutil.revsingle(repo, node)
5143 5169 mf = ctx.manifest()
5144 5170 for f in ctx:
5145 5171 fm.startitem()
5146 5172 fl = ctx[f].flags()
5147 5173 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5148 5174 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5149 5175 fm.write('path', '%s\n', f)
5150 5176 fm.end()
5151 5177
5152 5178 @command('^merge',
5153 5179 [('f', 'force', None,
5154 5180 _('force a merge including outstanding changes (DEPRECATED)')),
5155 5181 ('r', 'rev', '', _('revision to merge'), _('REV')),
5156 5182 ('P', 'preview', None,
5157 5183 _('review revisions to merge (no merge is performed)'))
5158 5184 ] + mergetoolopts,
5159 5185 _('[-P] [-f] [[-r] REV]'))
5160 5186 def merge(ui, repo, node=None, **opts):
5161 5187 """merge another revision into working directory
5162 5188
5163 5189 The current working directory is updated with all changes made in
5164 5190 the requested revision since the last common predecessor revision.
5165 5191
5166 5192 Files that changed between either parent are marked as changed for
5167 5193 the next commit and a commit must be performed before any further
5168 5194 updates to the repository are allowed. The next commit will have
5169 5195 two parents.
5170 5196
5171 5197 ``--tool`` can be used to specify the merge tool used for file
5172 5198 merges. It overrides the HGMERGE environment variable and your
5173 5199 configuration files. See :hg:`help merge-tools` for options.
5174 5200
5175 5201 If no revision is specified, the working directory's parent is a
5176 5202 head revision, and the current branch contains exactly one other
5177 5203 head, the other head is merged with by default. Otherwise, an
5178 5204 explicit revision with which to merge with must be provided.
5179 5205
5180 5206 See :hg:`help resolve` for information on handling file conflicts.
5181 5207
5182 5208 To undo an uncommitted merge, use :hg:`update --clean .` which
5183 5209 will check out a clean copy of the original merge parent, losing
5184 5210 all changes.
5185 5211
5186 5212 Returns 0 on success, 1 if there are unresolved files.
5187 5213 """
5188 5214
5189 5215 if opts.get('rev') and node:
5190 5216 raise error.Abort(_("please specify just one revision"))
5191 5217 if not node:
5192 5218 node = opts.get('rev')
5193 5219
5194 5220 if node:
5195 5221 node = scmutil.revsingle(repo, node).node()
5196 5222
5197 5223 if not node:
5198 5224 node = repo[destutil.destmerge(repo)].node()
5199 5225
5200 5226 if opts.get('preview'):
5201 5227 # find nodes that are ancestors of p2 but not of p1
5202 5228 p1 = repo.lookup('.')
5203 5229 p2 = repo.lookup(node)
5204 5230 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5205 5231
5206 5232 displayer = cmdutil.show_changeset(ui, repo, opts)
5207 5233 for node in nodes:
5208 5234 displayer.show(repo[node])
5209 5235 displayer.close()
5210 5236 return 0
5211 5237
5212 5238 try:
5213 5239 # ui.forcemerge is an internal variable, do not document
5214 5240 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5215 5241 return hg.merge(repo, node, force=opts.get('force'))
5216 5242 finally:
5217 5243 ui.setconfig('ui', 'forcemerge', '', 'merge')
5218 5244
5219 5245 @command('outgoing|out',
5220 5246 [('f', 'force', None, _('run even when the destination is unrelated')),
5221 5247 ('r', 'rev', [],
5222 5248 _('a changeset intended to be included in the destination'), _('REV')),
5223 5249 ('n', 'newest-first', None, _('show newest record first')),
5224 5250 ('B', 'bookmarks', False, _('compare bookmarks')),
5225 5251 ('b', 'branch', [], _('a specific branch you would like to push'),
5226 5252 _('BRANCH')),
5227 5253 ] + logopts + remoteopts + subrepoopts,
5228 5254 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5229 5255 def outgoing(ui, repo, dest=None, **opts):
5230 5256 """show changesets not found in the destination
5231 5257
5232 5258 Show changesets not found in the specified destination repository
5233 5259 or the default push location. These are the changesets that would
5234 5260 be pushed if a push was requested.
5235 5261
5236 5262 See pull for details of valid destination formats.
5237 5263
5238 5264 .. container:: verbose
5239 5265
5240 5266 With -B/--bookmarks, the result of bookmark comparison between
5241 5267 local and remote repositories is displayed. With -v/--verbose,
5242 5268 status is also displayed for each bookmark like below::
5243 5269
5244 5270 BM1 01234567890a added
5245 5271 BM2 deleted
5246 5272 BM3 234567890abc advanced
5247 5273 BM4 34567890abcd diverged
5248 5274 BM5 4567890abcde changed
5249 5275
5250 5276 The action taken when pushing depends on the
5251 5277 status of each bookmark:
5252 5278
5253 5279 :``added``: push with ``-B`` will create it
5254 5280 :``deleted``: push with ``-B`` will delete it
5255 5281 :``advanced``: push will update it
5256 5282 :``diverged``: push with ``-B`` will update it
5257 5283 :``changed``: push with ``-B`` will update it
5258 5284
5259 5285 From the point of view of pushing behavior, bookmarks
5260 5286 existing only in the remote repository are treated as
5261 5287 ``deleted``, even if it is in fact added remotely.
5262 5288
5263 5289 Returns 0 if there are outgoing changes, 1 otherwise.
5264 5290 """
5265 5291 if opts.get('graph'):
5266 5292 cmdutil.checkunsupportedgraphflags([], opts)
5267 5293 o, other = hg._outgoing(ui, repo, dest, opts)
5268 5294 if not o:
5269 5295 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5270 5296 return
5271 5297
5272 5298 revdag = cmdutil.graphrevs(repo, o, opts)
5273 5299 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5274 5300 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5275 5301 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5276 5302 return 0
5277 5303
5278 5304 if opts.get('bookmarks'):
5279 5305 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5280 5306 dest, branches = hg.parseurl(dest, opts.get('branch'))
5281 5307 other = hg.peer(repo, opts, dest)
5282 5308 if 'bookmarks' not in other.listkeys('namespaces'):
5283 5309 ui.warn(_("remote doesn't support bookmarks\n"))
5284 5310 return 0
5285 5311 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5286 5312 return bookmarks.outgoing(ui, repo, other)
5287 5313
5288 5314 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5289 5315 try:
5290 5316 return hg.outgoing(ui, repo, dest, opts)
5291 5317 finally:
5292 5318 del repo._subtoppath
5293 5319
5294 5320 @command('parents',
5295 5321 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5296 5322 ] + templateopts,
5297 5323 _('[-r REV] [FILE]'),
5298 5324 inferrepo=True)
5299 5325 def parents(ui, repo, file_=None, **opts):
5300 5326 """show the parents of the working directory or revision (DEPRECATED)
5301 5327
5302 5328 Print the working directory's parent revisions. If a revision is
5303 5329 given via -r/--rev, the parent of that revision will be printed.
5304 5330 If a file argument is given, the revision in which the file was
5305 5331 last changed (before the working directory revision or the
5306 5332 argument to --rev if given) is printed.
5307 5333
5308 5334 This command is equivalent to::
5309 5335
5310 5336 hg log -r "p1()+p2()" or
5311 5337 hg log -r "p1(REV)+p2(REV)" or
5312 5338 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5313 5339 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5314 5340
5315 5341 See :hg:`summary` and :hg:`help revsets` for related information.
5316 5342
5317 5343 Returns 0 on success.
5318 5344 """
5319 5345
5320 5346 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5321 5347
5322 5348 if file_:
5323 5349 m = scmutil.match(ctx, (file_,), opts)
5324 5350 if m.anypats() or len(m.files()) != 1:
5325 5351 raise error.Abort(_('can only specify an explicit filename'))
5326 5352 file_ = m.files()[0]
5327 5353 filenodes = []
5328 5354 for cp in ctx.parents():
5329 5355 if not cp:
5330 5356 continue
5331 5357 try:
5332 5358 filenodes.append(cp.filenode(file_))
5333 5359 except error.LookupError:
5334 5360 pass
5335 5361 if not filenodes:
5336 5362 raise error.Abort(_("'%s' not found in manifest!") % file_)
5337 5363 p = []
5338 5364 for fn in filenodes:
5339 5365 fctx = repo.filectx(file_, fileid=fn)
5340 5366 p.append(fctx.node())
5341 5367 else:
5342 5368 p = [cp.node() for cp in ctx.parents()]
5343 5369
5344 5370 displayer = cmdutil.show_changeset(ui, repo, opts)
5345 5371 for n in p:
5346 5372 if n != nullid:
5347 5373 displayer.show(repo[n])
5348 5374 displayer.close()
5349 5375
5350 5376 @command('paths', [], _('[NAME]'), optionalrepo=True)
5351 5377 def paths(ui, repo, search=None):
5352 5378 """show aliases for remote repositories
5353 5379
5354 5380 Show definition of symbolic path name NAME. If no name is given,
5355 5381 show definition of all available names.
5356 5382
5357 5383 Option -q/--quiet suppresses all output when searching for NAME
5358 5384 and shows only the path names when listing all definitions.
5359 5385
5360 5386 Path names are defined in the [paths] section of your
5361 5387 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5362 5388 repository, ``.hg/hgrc`` is used, too.
5363 5389
5364 5390 The path names ``default`` and ``default-push`` have a special
5365 5391 meaning. When performing a push or pull operation, they are used
5366 5392 as fallbacks if no location is specified on the command-line.
5367 5393 When ``default-push`` is set, it will be used for push and
5368 5394 ``default`` will be used for pull; otherwise ``default`` is used
5369 5395 as the fallback for both. When cloning a repository, the clone
5370 5396 source is written as ``default`` in ``.hg/hgrc``.
5371 5397
5372 5398 .. note::
5373 5399
5374 5400 ``default`` and ``default-push`` apply to all inbound (e.g.
5375 5401 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5376 5402 and :hg:`bundle`) operations.
5377 5403
5378 5404 See :hg:`help urls` for more information.
5379 5405
5380 5406 Returns 0 on success.
5381 5407 """
5382 5408 if search:
5383 5409 for name, path in sorted(ui.paths.iteritems()):
5384 5410 if name == search:
5385 5411 ui.status("%s\n" % util.hidepassword(path.rawloc))
5386 5412 return
5387 5413 if not ui.quiet:
5388 5414 ui.warn(_("not found!\n"))
5389 5415 return 1
5390 5416 else:
5391 5417 for name, path in sorted(ui.paths.iteritems()):
5392 5418 if ui.quiet:
5393 5419 ui.write("%s\n" % name)
5394 5420 else:
5395 5421 ui.write("%s = %s\n" % (name,
5396 5422 util.hidepassword(path.rawloc)))
5397 5423 for subopt, value in sorted(path.suboptions.items()):
5398 5424 ui.write('%s:%s = %s\n' % (name, subopt, value))
5399 5425
5400 5426 @command('phase',
5401 5427 [('p', 'public', False, _('set changeset phase to public')),
5402 5428 ('d', 'draft', False, _('set changeset phase to draft')),
5403 5429 ('s', 'secret', False, _('set changeset phase to secret')),
5404 5430 ('f', 'force', False, _('allow to move boundary backward')),
5405 5431 ('r', 'rev', [], _('target revision'), _('REV')),
5406 5432 ],
5407 5433 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5408 5434 def phase(ui, repo, *revs, **opts):
5409 5435 """set or show the current phase name
5410 5436
5411 5437 With no argument, show the phase name of the current revision(s).
5412 5438
5413 5439 With one of -p/--public, -d/--draft or -s/--secret, change the
5414 5440 phase value of the specified revisions.
5415 5441
5416 5442 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5417 5443 lower phase to an higher phase. Phases are ordered as follows::
5418 5444
5419 5445 public < draft < secret
5420 5446
5421 5447 Returns 0 on success, 1 if some phases could not be changed.
5422 5448
5423 5449 (For more information about the phases concept, see :hg:`help phases`.)
5424 5450 """
5425 5451 # search for a unique phase argument
5426 5452 targetphase = None
5427 5453 for idx, name in enumerate(phases.phasenames):
5428 5454 if opts[name]:
5429 5455 if targetphase is not None:
5430 5456 raise error.Abort(_('only one phase can be specified'))
5431 5457 targetphase = idx
5432 5458
5433 5459 # look for specified revision
5434 5460 revs = list(revs)
5435 5461 revs.extend(opts['rev'])
5436 5462 if not revs:
5437 5463 # display both parents as the second parent phase can influence
5438 5464 # the phase of a merge commit
5439 5465 revs = [c.rev() for c in repo[None].parents()]
5440 5466
5441 5467 revs = scmutil.revrange(repo, revs)
5442 5468
5443 5469 lock = None
5444 5470 ret = 0
5445 5471 if targetphase is None:
5446 5472 # display
5447 5473 for r in revs:
5448 5474 ctx = repo[r]
5449 5475 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5450 5476 else:
5451 5477 tr = None
5452 5478 lock = repo.lock()
5453 5479 try:
5454 5480 tr = repo.transaction("phase")
5455 5481 # set phase
5456 5482 if not revs:
5457 5483 raise error.Abort(_('empty revision set'))
5458 5484 nodes = [repo[r].node() for r in revs]
5459 5485 # moving revision from public to draft may hide them
5460 5486 # We have to check result on an unfiltered repository
5461 5487 unfi = repo.unfiltered()
5462 5488 getphase = unfi._phasecache.phase
5463 5489 olddata = [getphase(unfi, r) for r in unfi]
5464 5490 phases.advanceboundary(repo, tr, targetphase, nodes)
5465 5491 if opts['force']:
5466 5492 phases.retractboundary(repo, tr, targetphase, nodes)
5467 5493 tr.close()
5468 5494 finally:
5469 5495 if tr is not None:
5470 5496 tr.release()
5471 5497 lock.release()
5472 5498 getphase = unfi._phasecache.phase
5473 5499 newdata = [getphase(unfi, r) for r in unfi]
5474 5500 changes = sum(newdata[r] != olddata[r] for r in unfi)
5475 5501 cl = unfi.changelog
5476 5502 rejected = [n for n in nodes
5477 5503 if newdata[cl.rev(n)] < targetphase]
5478 5504 if rejected:
5479 5505 ui.warn(_('cannot move %i changesets to a higher '
5480 5506 'phase, use --force\n') % len(rejected))
5481 5507 ret = 1
5482 5508 if changes:
5483 5509 msg = _('phase changed for %i changesets\n') % changes
5484 5510 if ret:
5485 5511 ui.status(msg)
5486 5512 else:
5487 5513 ui.note(msg)
5488 5514 else:
5489 5515 ui.warn(_('no phases changed\n'))
5490 5516 return ret
5491 5517
5492 5518 def postincoming(ui, repo, modheads, optupdate, checkout):
5493 5519 if modheads == 0:
5494 5520 return
5495 5521 if optupdate:
5496 5522 try:
5497 5523 brev = checkout
5498 5524 movemarkfrom = None
5499 5525 if not checkout:
5500 5526 updata = destutil.destupdate(repo)
5501 5527 checkout, movemarkfrom, brev = updata
5502 5528 ret = hg.update(repo, checkout)
5503 5529 except error.UpdateAbort as inst:
5504 5530 msg = _("not updating: %s") % str(inst)
5505 5531 hint = inst.hint
5506 5532 raise error.UpdateAbort(msg, hint=hint)
5507 5533 if not ret and not checkout:
5508 5534 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5509 5535 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5510 5536 return ret
5511 5537 if modheads > 1:
5512 5538 currentbranchheads = len(repo.branchheads())
5513 5539 if currentbranchheads == modheads:
5514 5540 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5515 5541 elif currentbranchheads > 1:
5516 5542 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5517 5543 "merge)\n"))
5518 5544 else:
5519 5545 ui.status(_("(run 'hg heads' to see heads)\n"))
5520 5546 else:
5521 5547 ui.status(_("(run 'hg update' to get a working copy)\n"))
5522 5548
5523 5549 @command('^pull',
5524 5550 [('u', 'update', None,
5525 5551 _('update to new branch head if changesets were pulled')),
5526 5552 ('f', 'force', None, _('run even when remote repository is unrelated')),
5527 5553 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5528 5554 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5529 5555 ('b', 'branch', [], _('a specific branch you would like to pull'),
5530 5556 _('BRANCH')),
5531 5557 ] + remoteopts,
5532 5558 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5533 5559 def pull(ui, repo, source="default", **opts):
5534 5560 """pull changes from the specified source
5535 5561
5536 5562 Pull changes from a remote repository to a local one.
5537 5563
5538 5564 This finds all changes from the repository at the specified path
5539 5565 or URL and adds them to a local repository (the current one unless
5540 5566 -R is specified). By default, this does not update the copy of the
5541 5567 project in the working directory.
5542 5568
5543 5569 Use :hg:`incoming` if you want to see what would have been added
5544 5570 by a pull at the time you issued this command. If you then decide
5545 5571 to add those changes to the repository, you should use :hg:`pull
5546 5572 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5547 5573
5548 5574 If SOURCE is omitted, the 'default' path will be used.
5549 5575 See :hg:`help urls` for more information.
5550 5576
5551 5577 Returns 0 on success, 1 if an update had unresolved files.
5552 5578 """
5553 5579 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5554 5580 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5555 5581 other = hg.peer(repo, opts, source)
5556 5582 try:
5557 5583 revs, checkout = hg.addbranchrevs(repo, other, branches,
5558 5584 opts.get('rev'))
5559 5585
5560 5586
5561 5587 pullopargs = {}
5562 5588 if opts.get('bookmark'):
5563 5589 if not revs:
5564 5590 revs = []
5565 5591 # The list of bookmark used here is not the one used to actually
5566 5592 # update the bookmark name. This can result in the revision pulled
5567 5593 # not ending up with the name of the bookmark because of a race
5568 5594 # condition on the server. (See issue 4689 for details)
5569 5595 remotebookmarks = other.listkeys('bookmarks')
5570 5596 pullopargs['remotebookmarks'] = remotebookmarks
5571 5597 for b in opts['bookmark']:
5572 5598 if b not in remotebookmarks:
5573 5599 raise error.Abort(_('remote bookmark %s not found!') % b)
5574 5600 revs.append(remotebookmarks[b])
5575 5601
5576 5602 if revs:
5577 5603 try:
5578 5604 # When 'rev' is a bookmark name, we cannot guarantee that it
5579 5605 # will be updated with that name because of a race condition
5580 5606 # server side. (See issue 4689 for details)
5581 5607 oldrevs = revs
5582 5608 revs = [] # actually, nodes
5583 5609 for r in oldrevs:
5584 5610 node = other.lookup(r)
5585 5611 revs.append(node)
5586 5612 if r == checkout:
5587 5613 checkout = node
5588 5614 except error.CapabilityError:
5589 5615 err = _("other repository doesn't support revision lookup, "
5590 5616 "so a rev cannot be specified.")
5591 5617 raise error.Abort(err)
5592 5618
5593 5619 pullopargs.update(opts.get('opargs', {}))
5594 5620 modheads = exchange.pull(repo, other, heads=revs,
5595 5621 force=opts.get('force'),
5596 5622 bookmarks=opts.get('bookmark', ()),
5597 5623 opargs=pullopargs).cgresult
5598 5624 if checkout:
5599 5625 checkout = str(repo.changelog.rev(checkout))
5600 5626 repo._subtoppath = source
5601 5627 try:
5602 5628 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5603 5629
5604 5630 finally:
5605 5631 del repo._subtoppath
5606 5632
5607 5633 finally:
5608 5634 other.close()
5609 5635 return ret
5610 5636
5611 5637 @command('^push',
5612 5638 [('f', 'force', None, _('force push')),
5613 5639 ('r', 'rev', [],
5614 5640 _('a changeset intended to be included in the destination'),
5615 5641 _('REV')),
5616 5642 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5617 5643 ('b', 'branch', [],
5618 5644 _('a specific branch you would like to push'), _('BRANCH')),
5619 5645 ('', 'new-branch', False, _('allow pushing a new branch')),
5620 5646 ] + remoteopts,
5621 5647 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5622 5648 def push(ui, repo, dest=None, **opts):
5623 5649 """push changes to the specified destination
5624 5650
5625 5651 Push changesets from the local repository to the specified
5626 5652 destination.
5627 5653
5628 5654 This operation is symmetrical to pull: it is identical to a pull
5629 5655 in the destination repository from the current one.
5630 5656
5631 5657 By default, push will not allow creation of new heads at the
5632 5658 destination, since multiple heads would make it unclear which head
5633 5659 to use. In this situation, it is recommended to pull and merge
5634 5660 before pushing.
5635 5661
5636 5662 Use --new-branch if you want to allow push to create a new named
5637 5663 branch that is not present at the destination. This allows you to
5638 5664 only create a new branch without forcing other changes.
5639 5665
5640 5666 .. note::
5641 5667
5642 5668 Extra care should be taken with the -f/--force option,
5643 5669 which will push all new heads on all branches, an action which will
5644 5670 almost always cause confusion for collaborators.
5645 5671
5646 5672 If -r/--rev is used, the specified revision and all its ancestors
5647 5673 will be pushed to the remote repository.
5648 5674
5649 5675 If -B/--bookmark is used, the specified bookmarked revision, its
5650 5676 ancestors, and the bookmark will be pushed to the remote
5651 5677 repository.
5652 5678
5653 5679 Please see :hg:`help urls` for important details about ``ssh://``
5654 5680 URLs. If DESTINATION is omitted, a default path will be used.
5655 5681
5656 5682 Returns 0 if push was successful, 1 if nothing to push.
5657 5683 """
5658 5684
5659 5685 if opts.get('bookmark'):
5660 5686 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5661 5687 for b in opts['bookmark']:
5662 5688 # translate -B options to -r so changesets get pushed
5663 5689 if b in repo._bookmarks:
5664 5690 opts.setdefault('rev', []).append(b)
5665 5691 else:
5666 5692 # if we try to push a deleted bookmark, translate it to null
5667 5693 # this lets simultaneous -r, -b options continue working
5668 5694 opts.setdefault('rev', []).append("null")
5669 5695
5670 5696 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5671 5697 if not path:
5672 5698 raise error.Abort(_('default repository not configured!'),
5673 5699 hint=_('see the "path" section in "hg help config"'))
5674 5700 dest = path.pushloc or path.loc
5675 5701 branches = (path.branch, opts.get('branch') or [])
5676 5702 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5677 5703 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5678 5704 other = hg.peer(repo, opts, dest)
5679 5705
5680 5706 if revs:
5681 5707 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5682 5708 if not revs:
5683 5709 raise error.Abort(_("specified revisions evaluate to an empty set"),
5684 5710 hint=_("use different revision arguments"))
5685 5711
5686 5712 repo._subtoppath = dest
5687 5713 try:
5688 5714 # push subrepos depth-first for coherent ordering
5689 5715 c = repo['']
5690 5716 subs = c.substate # only repos that are committed
5691 5717 for s in sorted(subs):
5692 5718 result = c.sub(s).push(opts)
5693 5719 if result == 0:
5694 5720 return not result
5695 5721 finally:
5696 5722 del repo._subtoppath
5697 5723 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5698 5724 newbranch=opts.get('new_branch'),
5699 5725 bookmarks=opts.get('bookmark', ()),
5700 5726 opargs=opts.get('opargs'))
5701 5727
5702 5728 result = not pushop.cgresult
5703 5729
5704 5730 if pushop.bkresult is not None:
5705 5731 if pushop.bkresult == 2:
5706 5732 result = 2
5707 5733 elif not result and pushop.bkresult:
5708 5734 result = 2
5709 5735
5710 5736 return result
5711 5737
5712 5738 @command('recover', [])
5713 5739 def recover(ui, repo):
5714 5740 """roll back an interrupted transaction
5715 5741
5716 5742 Recover from an interrupted commit or pull.
5717 5743
5718 5744 This command tries to fix the repository status after an
5719 5745 interrupted operation. It should only be necessary when Mercurial
5720 5746 suggests it.
5721 5747
5722 5748 Returns 0 if successful, 1 if nothing to recover or verify fails.
5723 5749 """
5724 5750 if repo.recover():
5725 5751 return hg.verify(repo)
5726 5752 return 1
5727 5753
5728 5754 @command('^remove|rm',
5729 5755 [('A', 'after', None, _('record delete for missing files')),
5730 5756 ('f', 'force', None,
5731 5757 _('remove (and delete) file even if added or modified')),
5732 5758 ] + subrepoopts + walkopts,
5733 5759 _('[OPTION]... FILE...'),
5734 5760 inferrepo=True)
5735 5761 def remove(ui, repo, *pats, **opts):
5736 5762 """remove the specified files on the next commit
5737 5763
5738 5764 Schedule the indicated files for removal from the current branch.
5739 5765
5740 5766 This command schedules the files to be removed at the next commit.
5741 5767 To undo a remove before that, see :hg:`revert`. To undo added
5742 5768 files, see :hg:`forget`.
5743 5769
5744 5770 .. container:: verbose
5745 5771
5746 5772 -A/--after can be used to remove only files that have already
5747 5773 been deleted, -f/--force can be used to force deletion, and -Af
5748 5774 can be used to remove files from the next revision without
5749 5775 deleting them from the working directory.
5750 5776
5751 5777 The following table details the behavior of remove for different
5752 5778 file states (columns) and option combinations (rows). The file
5753 5779 states are Added [A], Clean [C], Modified [M] and Missing [!]
5754 5780 (as reported by :hg:`status`). The actions are Warn, Remove
5755 5781 (from branch) and Delete (from disk):
5756 5782
5757 5783 ========= == == == ==
5758 5784 opt/state A C M !
5759 5785 ========= == == == ==
5760 5786 none W RD W R
5761 5787 -f R RD RD R
5762 5788 -A W W W R
5763 5789 -Af R R R R
5764 5790 ========= == == == ==
5765 5791
5766 5792 .. note::
5767 5793
5768 5794 :hg:`remove` never deletes files in Added [A] state from the
5769 5795 working directory, not even if ``--force`` is specified.
5770 5796
5771 5797 Returns 0 on success, 1 if any warnings encountered.
5772 5798 """
5773 5799
5774 5800 after, force = opts.get('after'), opts.get('force')
5775 5801 if not pats and not after:
5776 5802 raise error.Abort(_('no files specified'))
5777 5803
5778 5804 m = scmutil.match(repo[None], pats, opts)
5779 5805 subrepos = opts.get('subrepos')
5780 5806 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5781 5807
5782 5808 @command('rename|move|mv',
5783 5809 [('A', 'after', None, _('record a rename that has already occurred')),
5784 5810 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5785 5811 ] + walkopts + dryrunopts,
5786 5812 _('[OPTION]... SOURCE... DEST'))
5787 5813 def rename(ui, repo, *pats, **opts):
5788 5814 """rename files; equivalent of copy + remove
5789 5815
5790 5816 Mark dest as copies of sources; mark sources for deletion. If dest
5791 5817 is a directory, copies are put in that directory. If dest is a
5792 5818 file, there can only be one source.
5793 5819
5794 5820 By default, this command copies the contents of files as they
5795 5821 exist in the working directory. If invoked with -A/--after, the
5796 5822 operation is recorded, but no copying is performed.
5797 5823
5798 5824 This command takes effect at the next commit. To undo a rename
5799 5825 before that, see :hg:`revert`.
5800 5826
5801 5827 Returns 0 on success, 1 if errors are encountered.
5802 5828 """
5803 5829 wlock = repo.wlock(False)
5804 5830 try:
5805 5831 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5806 5832 finally:
5807 5833 wlock.release()
5808 5834
5809 5835 @command('resolve',
5810 5836 [('a', 'all', None, _('select all unresolved files')),
5811 5837 ('l', 'list', None, _('list state of files needing merge')),
5812 5838 ('m', 'mark', None, _('mark files as resolved')),
5813 5839 ('u', 'unmark', None, _('mark files as unresolved')),
5814 5840 ('n', 'no-status', None, _('hide status prefix'))]
5815 5841 + mergetoolopts + walkopts + formatteropts,
5816 5842 _('[OPTION]... [FILE]...'),
5817 5843 inferrepo=True)
5818 5844 def resolve(ui, repo, *pats, **opts):
5819 5845 """redo merges or set/view the merge status of files
5820 5846
5821 5847 Merges with unresolved conflicts are often the result of
5822 5848 non-interactive merging using the ``internal:merge`` configuration
5823 5849 setting, or a command-line merge tool like ``diff3``. The resolve
5824 5850 command is used to manage the files involved in a merge, after
5825 5851 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5826 5852 working directory must have two parents). See :hg:`help
5827 5853 merge-tools` for information on configuring merge tools.
5828 5854
5829 5855 The resolve command can be used in the following ways:
5830 5856
5831 5857 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5832 5858 files, discarding any previous merge attempts. Re-merging is not
5833 5859 performed for files already marked as resolved. Use ``--all/-a``
5834 5860 to select all unresolved files. ``--tool`` can be used to specify
5835 5861 the merge tool used for the given files. It overrides the HGMERGE
5836 5862 environment variable and your configuration files. Previous file
5837 5863 contents are saved with a ``.orig`` suffix.
5838 5864
5839 5865 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5840 5866 (e.g. after having manually fixed-up the files). The default is
5841 5867 to mark all unresolved files.
5842 5868
5843 5869 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5844 5870 default is to mark all resolved files.
5845 5871
5846 5872 - :hg:`resolve -l`: list files which had or still have conflicts.
5847 5873 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5848 5874
5849 5875 .. note::
5850 5876
5851 5877 Mercurial will not let you commit files with unresolved merge
5852 5878 conflicts. You must use :hg:`resolve -m ...` before you can
5853 5879 commit after a conflicting merge.
5854 5880
5855 5881 Returns 0 on success, 1 if any files fail a resolve attempt.
5856 5882 """
5857 5883
5858 5884 all, mark, unmark, show, nostatus = \
5859 5885 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5860 5886
5861 5887 if (show and (mark or unmark)) or (mark and unmark):
5862 5888 raise error.Abort(_("too many options specified"))
5863 5889 if pats and all:
5864 5890 raise error.Abort(_("can't specify --all and patterns"))
5865 5891 if not (all or pats or show or mark or unmark):
5866 5892 raise error.Abort(_('no files or directories specified'),
5867 5893 hint=('use --all to re-merge all unresolved files'))
5868 5894
5869 5895 if show:
5870 5896 fm = ui.formatter('resolve', opts)
5871 5897 ms = mergemod.mergestate.read(repo)
5872 5898 m = scmutil.match(repo[None], pats, opts)
5873 5899 for f in ms:
5874 5900 if not m(f):
5875 5901 continue
5876 5902 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5877 5903 'd': 'driverresolved'}[ms[f]]
5878 5904 fm.startitem()
5879 5905 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5880 5906 fm.write('path', '%s\n', f, label=l)
5881 5907 fm.end()
5882 5908 return 0
5883 5909
5884 5910 wlock = repo.wlock()
5885 5911 try:
5886 5912 ms = mergemod.mergestate.read(repo)
5887 5913
5888 5914 if not (ms.active() or repo.dirstate.p2() != nullid):
5889 5915 raise error.Abort(
5890 5916 _('resolve command not applicable when not merging'))
5891 5917
5892 5918 wctx = repo[None]
5893 5919
5894 5920 if ms.mergedriver and ms.mdstate() == 'u':
5895 5921 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5896 5922 ms.commit()
5897 5923 # allow mark and unmark to go through
5898 5924 if not mark and not unmark and not proceed:
5899 5925 return 1
5900 5926
5901 5927 m = scmutil.match(wctx, pats, opts)
5902 5928 ret = 0
5903 5929 didwork = False
5904 5930 runconclude = False
5905 5931
5906 5932 tocomplete = []
5907 5933 for f in ms:
5908 5934 if not m(f):
5909 5935 continue
5910 5936
5911 5937 didwork = True
5912 5938
5913 5939 # don't let driver-resolved files be marked, and run the conclude
5914 5940 # step if asked to resolve
5915 5941 if ms[f] == "d":
5916 5942 exact = m.exact(f)
5917 5943 if mark:
5918 5944 if exact:
5919 5945 ui.warn(_('not marking %s as it is driver-resolved\n')
5920 5946 % f)
5921 5947 elif unmark:
5922 5948 if exact:
5923 5949 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5924 5950 % f)
5925 5951 else:
5926 5952 runconclude = True
5927 5953 continue
5928 5954
5929 5955 if mark:
5930 5956 ms.mark(f, "r")
5931 5957 elif unmark:
5932 5958 ms.mark(f, "u")
5933 5959 else:
5934 5960 # backup pre-resolve (merge uses .orig for its own purposes)
5935 5961 a = repo.wjoin(f)
5936 5962 try:
5937 5963 util.copyfile(a, a + ".resolve")
5938 5964 except (IOError, OSError) as inst:
5939 5965 if inst.errno != errno.ENOENT:
5940 5966 raise
5941 5967
5942 5968 try:
5943 5969 # preresolve file
5944 5970 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5945 5971 'resolve')
5946 5972 complete, r = ms.preresolve(f, wctx)
5947 5973 if not complete:
5948 5974 tocomplete.append(f)
5949 5975 elif r:
5950 5976 ret = 1
5951 5977 finally:
5952 5978 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5953 5979 ms.commit()
5954 5980
5955 5981 # replace filemerge's .orig file with our resolve file, but only
5956 5982 # for merges that are complete
5957 5983 if complete:
5958 5984 try:
5959 5985 util.rename(a + ".resolve",
5960 5986 scmutil.origpath(ui, repo, a))
5961 5987 except OSError as inst:
5962 5988 if inst.errno != errno.ENOENT:
5963 5989 raise
5964 5990
5965 5991 for f in tocomplete:
5966 5992 try:
5967 5993 # resolve file
5968 5994 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5969 5995 'resolve')
5970 5996 r = ms.resolve(f, wctx)
5971 5997 if r:
5972 5998 ret = 1
5973 5999 finally:
5974 6000 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5975 6001 ms.commit()
5976 6002
5977 6003 # replace filemerge's .orig file with our resolve file
5978 6004 a = repo.wjoin(f)
5979 6005 try:
5980 6006 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5981 6007 except OSError as inst:
5982 6008 if inst.errno != errno.ENOENT:
5983 6009 raise
5984 6010
5985 6011 ms.commit()
5986 6012 ms.recordactions()
5987 6013
5988 6014 if not didwork and pats:
5989 6015 ui.warn(_("arguments do not match paths that need resolving\n"))
5990 6016 elif ms.mergedriver and ms.mdstate() != 's':
5991 6017 # run conclude step when either a driver-resolved file is requested
5992 6018 # or there are no driver-resolved files
5993 6019 # we can't use 'ret' to determine whether any files are unresolved
5994 6020 # because we might not have tried to resolve some
5995 6021 if ((runconclude or not list(ms.driverresolved()))
5996 6022 and not list(ms.unresolved())):
5997 6023 proceed = mergemod.driverconclude(repo, ms, wctx)
5998 6024 ms.commit()
5999 6025 if not proceed:
6000 6026 return 1
6001 6027
6002 6028 finally:
6003 6029 wlock.release()
6004 6030
6005 6031 # Nudge users into finishing an unfinished operation
6006 6032 unresolvedf = list(ms.unresolved())
6007 6033 driverresolvedf = list(ms.driverresolved())
6008 6034 if not unresolvedf and not driverresolvedf:
6009 6035 ui.status(_('(no more unresolved files)\n'))
6010 6036 cmdutil.checkafterresolved(repo)
6011 6037 elif not unresolvedf:
6012 6038 ui.status(_('(no more unresolved files -- '
6013 6039 'run "hg resolve --all" to conclude)\n'))
6014 6040
6015 6041 return ret
6016 6042
6017 6043 @command('revert',
6018 6044 [('a', 'all', None, _('revert all changes when no arguments given')),
6019 6045 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6020 6046 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6021 6047 ('C', 'no-backup', None, _('do not save backup copies of files')),
6022 6048 ('i', 'interactive', None,
6023 6049 _('interactively select the changes (EXPERIMENTAL)')),
6024 6050 ] + walkopts + dryrunopts,
6025 6051 _('[OPTION]... [-r REV] [NAME]...'))
6026 6052 def revert(ui, repo, *pats, **opts):
6027 6053 """restore files to their checkout state
6028 6054
6029 6055 .. note::
6030 6056
6031 6057 To check out earlier revisions, you should use :hg:`update REV`.
6032 6058 To cancel an uncommitted merge (and lose your changes),
6033 6059 use :hg:`update --clean .`.
6034 6060
6035 6061 With no revision specified, revert the specified files or directories
6036 6062 to the contents they had in the parent of the working directory.
6037 6063 This restores the contents of files to an unmodified
6038 6064 state and unschedules adds, removes, copies, and renames. If the
6039 6065 working directory has two parents, you must explicitly specify a
6040 6066 revision.
6041 6067
6042 6068 Using the -r/--rev or -d/--date options, revert the given files or
6043 6069 directories to their states as of a specific revision. Because
6044 6070 revert does not change the working directory parents, this will
6045 6071 cause these files to appear modified. This can be helpful to "back
6046 6072 out" some or all of an earlier change. See :hg:`backout` for a
6047 6073 related method.
6048 6074
6049 6075 Modified files are saved with a .orig suffix before reverting.
6050 6076 To disable these backups, use --no-backup.
6051 6077
6052 6078 See :hg:`help dates` for a list of formats valid for -d/--date.
6053 6079
6054 6080 See :hg:`help backout` for a way to reverse the effect of an
6055 6081 earlier changeset.
6056 6082
6057 6083 Returns 0 on success.
6058 6084 """
6059 6085
6060 6086 if opts.get("date"):
6061 6087 if opts.get("rev"):
6062 6088 raise error.Abort(_("you can't specify a revision and a date"))
6063 6089 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6064 6090
6065 6091 parent, p2 = repo.dirstate.parents()
6066 6092 if not opts.get('rev') and p2 != nullid:
6067 6093 # revert after merge is a trap for new users (issue2915)
6068 6094 raise error.Abort(_('uncommitted merge with no revision specified'),
6069 6095 hint=_('use "hg update" or see "hg help revert"'))
6070 6096
6071 6097 ctx = scmutil.revsingle(repo, opts.get('rev'))
6072 6098
6073 6099 if (not (pats or opts.get('include') or opts.get('exclude') or
6074 6100 opts.get('all') or opts.get('interactive'))):
6075 6101 msg = _("no files or directories specified")
6076 6102 if p2 != nullid:
6077 6103 hint = _("uncommitted merge, use --all to discard all changes,"
6078 6104 " or 'hg update -C .' to abort the merge")
6079 6105 raise error.Abort(msg, hint=hint)
6080 6106 dirty = any(repo.status())
6081 6107 node = ctx.node()
6082 6108 if node != parent:
6083 6109 if dirty:
6084 6110 hint = _("uncommitted changes, use --all to discard all"
6085 6111 " changes, or 'hg update %s' to update") % ctx.rev()
6086 6112 else:
6087 6113 hint = _("use --all to revert all files,"
6088 6114 " or 'hg update %s' to update") % ctx.rev()
6089 6115 elif dirty:
6090 6116 hint = _("uncommitted changes, use --all to discard all changes")
6091 6117 else:
6092 6118 hint = _("use --all to revert all files")
6093 6119 raise error.Abort(msg, hint=hint)
6094 6120
6095 6121 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6096 6122
6097 6123 @command('rollback', dryrunopts +
6098 6124 [('f', 'force', False, _('ignore safety measures'))])
6099 6125 def rollback(ui, repo, **opts):
6100 6126 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6101 6127
6102 6128 Please use :hg:`commit --amend` instead of rollback to correct
6103 6129 mistakes in the last commit.
6104 6130
6105 6131 This command should be used with care. There is only one level of
6106 6132 rollback, and there is no way to undo a rollback. It will also
6107 6133 restore the dirstate at the time of the last transaction, losing
6108 6134 any dirstate changes since that time. This command does not alter
6109 6135 the working directory.
6110 6136
6111 6137 Transactions are used to encapsulate the effects of all commands
6112 6138 that create new changesets or propagate existing changesets into a
6113 6139 repository.
6114 6140
6115 6141 .. container:: verbose
6116 6142
6117 6143 For example, the following commands are transactional, and their
6118 6144 effects can be rolled back:
6119 6145
6120 6146 - commit
6121 6147 - import
6122 6148 - pull
6123 6149 - push (with this repository as the destination)
6124 6150 - unbundle
6125 6151
6126 6152 To avoid permanent data loss, rollback will refuse to rollback a
6127 6153 commit transaction if it isn't checked out. Use --force to
6128 6154 override this protection.
6129 6155
6130 6156 This command is not intended for use on public repositories. Once
6131 6157 changes are visible for pull by other users, rolling a transaction
6132 6158 back locally is ineffective (someone else may already have pulled
6133 6159 the changes). Furthermore, a race is possible with readers of the
6134 6160 repository; for example an in-progress pull from the repository
6135 6161 may fail if a rollback is performed.
6136 6162
6137 6163 Returns 0 on success, 1 if no rollback data is available.
6138 6164 """
6139 6165 return repo.rollback(dryrun=opts.get('dry_run'),
6140 6166 force=opts.get('force'))
6141 6167
6142 6168 @command('root', [])
6143 6169 def root(ui, repo):
6144 6170 """print the root (top) of the current working directory
6145 6171
6146 6172 Print the root directory of the current repository.
6147 6173
6148 6174 Returns 0 on success.
6149 6175 """
6150 6176 ui.write(repo.root + "\n")
6151 6177
6152 6178 @command('^serve',
6153 6179 [('A', 'accesslog', '', _('name of access log file to write to'),
6154 6180 _('FILE')),
6155 6181 ('d', 'daemon', None, _('run server in background')),
6156 6182 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6157 6183 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6158 6184 # use string type, then we can check if something was passed
6159 6185 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6160 6186 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6161 6187 _('ADDR')),
6162 6188 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6163 6189 _('PREFIX')),
6164 6190 ('n', 'name', '',
6165 6191 _('name to show in web pages (default: working directory)'), _('NAME')),
6166 6192 ('', 'web-conf', '',
6167 6193 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6168 6194 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6169 6195 _('FILE')),
6170 6196 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6171 6197 ('', 'stdio', None, _('for remote clients')),
6172 6198 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6173 6199 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6174 6200 ('', 'style', '', _('template style to use'), _('STYLE')),
6175 6201 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6176 6202 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6177 6203 _('[OPTION]...'),
6178 6204 optionalrepo=True)
6179 6205 def serve(ui, repo, **opts):
6180 6206 """start stand-alone webserver
6181 6207
6182 6208 Start a local HTTP repository browser and pull server. You can use
6183 6209 this for ad-hoc sharing and browsing of repositories. It is
6184 6210 recommended to use a real web server to serve a repository for
6185 6211 longer periods of time.
6186 6212
6187 6213 Please note that the server does not implement access control.
6188 6214 This means that, by default, anybody can read from the server and
6189 6215 nobody can write to it by default. Set the ``web.allow_push``
6190 6216 option to ``*`` to allow everybody to push to the server. You
6191 6217 should use a real web server if you need to authenticate users.
6192 6218
6193 6219 By default, the server logs accesses to stdout and errors to
6194 6220 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6195 6221 files.
6196 6222
6197 6223 To have the server choose a free port number to listen on, specify
6198 6224 a port number of 0; in this case, the server will print the port
6199 6225 number it uses.
6200 6226
6201 6227 Returns 0 on success.
6202 6228 """
6203 6229
6204 6230 if opts["stdio"] and opts["cmdserver"]:
6205 6231 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6206 6232
6207 6233 if opts["stdio"]:
6208 6234 if repo is None:
6209 6235 raise error.RepoError(_("there is no Mercurial repository here"
6210 6236 " (.hg not found)"))
6211 6237 s = sshserver.sshserver(ui, repo)
6212 6238 s.serve_forever()
6213 6239
6214 6240 if opts["cmdserver"]:
6215 6241 service = commandserver.createservice(ui, repo, opts)
6216 6242 else:
6217 6243 service = hgweb.createservice(ui, repo, opts)
6218 6244 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6219 6245
6220 6246 @command('^status|st',
6221 6247 [('A', 'all', None, _('show status of all files')),
6222 6248 ('m', 'modified', None, _('show only modified files')),
6223 6249 ('a', 'added', None, _('show only added files')),
6224 6250 ('r', 'removed', None, _('show only removed files')),
6225 6251 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6226 6252 ('c', 'clean', None, _('show only files without changes')),
6227 6253 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6228 6254 ('i', 'ignored', None, _('show only ignored files')),
6229 6255 ('n', 'no-status', None, _('hide status prefix')),
6230 6256 ('C', 'copies', None, _('show source of copied files')),
6231 6257 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6232 6258 ('', 'rev', [], _('show difference from revision'), _('REV')),
6233 6259 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6234 6260 ] + walkopts + subrepoopts + formatteropts,
6235 6261 _('[OPTION]... [FILE]...'),
6236 6262 inferrepo=True)
6237 6263 def status(ui, repo, *pats, **opts):
6238 6264 """show changed files in the working directory
6239 6265
6240 6266 Show status of files in the repository. If names are given, only
6241 6267 files that match are shown. Files that are clean or ignored or
6242 6268 the source of a copy/move operation, are not listed unless
6243 6269 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6244 6270 Unless options described with "show only ..." are given, the
6245 6271 options -mardu are used.
6246 6272
6247 6273 Option -q/--quiet hides untracked (unknown and ignored) files
6248 6274 unless explicitly requested with -u/--unknown or -i/--ignored.
6249 6275
6250 6276 .. note::
6251 6277
6252 6278 :hg:`status` may appear to disagree with diff if permissions have
6253 6279 changed or a merge has occurred. The standard diff format does
6254 6280 not report permission changes and diff only reports changes
6255 6281 relative to one merge parent.
6256 6282
6257 6283 If one revision is given, it is used as the base revision.
6258 6284 If two revisions are given, the differences between them are
6259 6285 shown. The --change option can also be used as a shortcut to list
6260 6286 the changed files of a revision from its first parent.
6261 6287
6262 6288 The codes used to show the status of files are::
6263 6289
6264 6290 M = modified
6265 6291 A = added
6266 6292 R = removed
6267 6293 C = clean
6268 6294 ! = missing (deleted by non-hg command, but still tracked)
6269 6295 ? = not tracked
6270 6296 I = ignored
6271 6297 = origin of the previous file (with --copies)
6272 6298
6273 6299 .. container:: verbose
6274 6300
6275 6301 Examples:
6276 6302
6277 6303 - show changes in the working directory relative to a
6278 6304 changeset::
6279 6305
6280 6306 hg status --rev 9353
6281 6307
6282 6308 - show changes in the working directory relative to the
6283 6309 current directory (see :hg:`help patterns` for more information)::
6284 6310
6285 6311 hg status re:
6286 6312
6287 6313 - show all changes including copies in an existing changeset::
6288 6314
6289 6315 hg status --copies --change 9353
6290 6316
6291 6317 - get a NUL separated list of added files, suitable for xargs::
6292 6318
6293 6319 hg status -an0
6294 6320
6295 6321 Returns 0 on success.
6296 6322 """
6297 6323
6298 6324 revs = opts.get('rev')
6299 6325 change = opts.get('change')
6300 6326
6301 6327 if revs and change:
6302 6328 msg = _('cannot specify --rev and --change at the same time')
6303 6329 raise error.Abort(msg)
6304 6330 elif change:
6305 6331 node2 = scmutil.revsingle(repo, change, None).node()
6306 6332 node1 = repo[node2].p1().node()
6307 6333 else:
6308 6334 node1, node2 = scmutil.revpair(repo, revs)
6309 6335
6310 6336 if pats:
6311 6337 cwd = repo.getcwd()
6312 6338 else:
6313 6339 cwd = ''
6314 6340
6315 6341 if opts.get('print0'):
6316 6342 end = '\0'
6317 6343 else:
6318 6344 end = '\n'
6319 6345 copy = {}
6320 6346 states = 'modified added removed deleted unknown ignored clean'.split()
6321 6347 show = [k for k in states if opts.get(k)]
6322 6348 if opts.get('all'):
6323 6349 show += ui.quiet and (states[:4] + ['clean']) or states
6324 6350 if not show:
6325 6351 if ui.quiet:
6326 6352 show = states[:4]
6327 6353 else:
6328 6354 show = states[:5]
6329 6355
6330 6356 m = scmutil.match(repo[node2], pats, opts)
6331 6357 stat = repo.status(node1, node2, m,
6332 6358 'ignored' in show, 'clean' in show, 'unknown' in show,
6333 6359 opts.get('subrepos'))
6334 6360 changestates = zip(states, 'MAR!?IC', stat)
6335 6361
6336 6362 if (opts.get('all') or opts.get('copies')
6337 6363 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6338 6364 copy = copies.pathcopies(repo[node1], repo[node2], m)
6339 6365
6340 6366 fm = ui.formatter('status', opts)
6341 6367 fmt = '%s' + end
6342 6368 showchar = not opts.get('no_status')
6343 6369
6344 6370 for state, char, files in changestates:
6345 6371 if state in show:
6346 6372 label = 'status.' + state
6347 6373 for f in files:
6348 6374 fm.startitem()
6349 6375 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6350 6376 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6351 6377 if f in copy:
6352 6378 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6353 6379 label='status.copied')
6354 6380 fm.end()
6355 6381
6356 6382 @command('^summary|sum',
6357 6383 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6358 6384 def summary(ui, repo, **opts):
6359 6385 """summarize working directory state
6360 6386
6361 6387 This generates a brief summary of the working directory state,
6362 6388 including parents, branch, commit status, phase and available updates.
6363 6389
6364 6390 With the --remote option, this will check the default paths for
6365 6391 incoming and outgoing changes. This can be time-consuming.
6366 6392
6367 6393 Returns 0 on success.
6368 6394 """
6369 6395
6370 6396 ctx = repo[None]
6371 6397 parents = ctx.parents()
6372 6398 pnode = parents[0].node()
6373 6399 marks = []
6374 6400
6375 6401 for p in parents:
6376 6402 # label with log.changeset (instead of log.parent) since this
6377 6403 # shows a working directory parent *changeset*:
6378 6404 # i18n: column positioning for "hg summary"
6379 6405 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6380 6406 label='log.changeset changeset.%s' % p.phasestr())
6381 6407 ui.write(' '.join(p.tags()), label='log.tag')
6382 6408 if p.bookmarks():
6383 6409 marks.extend(p.bookmarks())
6384 6410 if p.rev() == -1:
6385 6411 if not len(repo):
6386 6412 ui.write(_(' (empty repository)'))
6387 6413 else:
6388 6414 ui.write(_(' (no revision checked out)'))
6389 6415 ui.write('\n')
6390 6416 if p.description():
6391 6417 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6392 6418 label='log.summary')
6393 6419
6394 6420 branch = ctx.branch()
6395 6421 bheads = repo.branchheads(branch)
6396 6422 # i18n: column positioning for "hg summary"
6397 6423 m = _('branch: %s\n') % branch
6398 6424 if branch != 'default':
6399 6425 ui.write(m, label='log.branch')
6400 6426 else:
6401 6427 ui.status(m, label='log.branch')
6402 6428
6403 6429 if marks:
6404 6430 active = repo._activebookmark
6405 6431 # i18n: column positioning for "hg summary"
6406 6432 ui.write(_('bookmarks:'), label='log.bookmark')
6407 6433 if active is not None:
6408 6434 if active in marks:
6409 6435 ui.write(' *' + active, label=activebookmarklabel)
6410 6436 marks.remove(active)
6411 6437 else:
6412 6438 ui.write(' [%s]' % active, label=activebookmarklabel)
6413 6439 for m in marks:
6414 6440 ui.write(' ' + m, label='log.bookmark')
6415 6441 ui.write('\n', label='log.bookmark')
6416 6442
6417 6443 status = repo.status(unknown=True)
6418 6444
6419 6445 c = repo.dirstate.copies()
6420 6446 copied, renamed = [], []
6421 6447 for d, s in c.iteritems():
6422 6448 if s in status.removed:
6423 6449 status.removed.remove(s)
6424 6450 renamed.append(d)
6425 6451 else:
6426 6452 copied.append(d)
6427 6453 if d in status.added:
6428 6454 status.added.remove(d)
6429 6455
6430 6456 try:
6431 6457 ms = mergemod.mergestate.read(repo)
6432 6458 except error.UnsupportedMergeRecords as e:
6433 6459 s = ' '.join(e.recordtypes)
6434 6460 ui.warn(
6435 6461 _('warning: merge state has unsupported record types: %s\n') % s)
6436 6462 unresolved = 0
6437 6463 else:
6438 6464 unresolved = [f for f in ms if ms[f] == 'u']
6439 6465
6440 6466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6441 6467
6442 6468 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6443 6469 (ui.label(_('%d added'), 'status.added'), status.added),
6444 6470 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6445 6471 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6446 6472 (ui.label(_('%d copied'), 'status.copied'), copied),
6447 6473 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6448 6474 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6449 6475 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6450 6476 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6451 6477 t = []
6452 6478 for l, s in labels:
6453 6479 if s:
6454 6480 t.append(l % len(s))
6455 6481
6456 6482 t = ', '.join(t)
6457 6483 cleanworkdir = False
6458 6484
6459 6485 if repo.vfs.exists('graftstate'):
6460 6486 t += _(' (graft in progress)')
6461 6487 if repo.vfs.exists('updatestate'):
6462 6488 t += _(' (interrupted update)')
6463 6489 elif len(parents) > 1:
6464 6490 t += _(' (merge)')
6465 6491 elif branch != parents[0].branch():
6466 6492 t += _(' (new branch)')
6467 6493 elif (parents[0].closesbranch() and
6468 6494 pnode in repo.branchheads(branch, closed=True)):
6469 6495 t += _(' (head closed)')
6470 6496 elif not (status.modified or status.added or status.removed or renamed or
6471 6497 copied or subs):
6472 6498 t += _(' (clean)')
6473 6499 cleanworkdir = True
6474 6500 elif pnode not in bheads:
6475 6501 t += _(' (new branch head)')
6476 6502
6477 6503 if parents:
6478 6504 pendingphase = max(p.phase() for p in parents)
6479 6505 else:
6480 6506 pendingphase = phases.public
6481 6507
6482 6508 if pendingphase > phases.newcommitphase(ui):
6483 6509 t += ' (%s)' % phases.phasenames[pendingphase]
6484 6510
6485 6511 if cleanworkdir:
6486 6512 # i18n: column positioning for "hg summary"
6487 6513 ui.status(_('commit: %s\n') % t.strip())
6488 6514 else:
6489 6515 # i18n: column positioning for "hg summary"
6490 6516 ui.write(_('commit: %s\n') % t.strip())
6491 6517
6492 6518 # all ancestors of branch heads - all ancestors of parent = new csets
6493 6519 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6494 6520 bheads))
6495 6521
6496 6522 if new == 0:
6497 6523 # i18n: column positioning for "hg summary"
6498 6524 ui.status(_('update: (current)\n'))
6499 6525 elif pnode not in bheads:
6500 6526 # i18n: column positioning for "hg summary"
6501 6527 ui.write(_('update: %d new changesets (update)\n') % new)
6502 6528 else:
6503 6529 # i18n: column positioning for "hg summary"
6504 6530 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6505 6531 (new, len(bheads)))
6506 6532
6507 6533 t = []
6508 6534 draft = len(repo.revs('draft()'))
6509 6535 if draft:
6510 6536 t.append(_('%d draft') % draft)
6511 6537 secret = len(repo.revs('secret()'))
6512 6538 if secret:
6513 6539 t.append(_('%d secret') % secret)
6514 6540
6515 6541 if draft or secret:
6516 6542 ui.status(_('phases: %s\n') % ', '.join(t))
6517 6543
6518 6544 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6519 6545 for trouble in ("unstable", "divergent", "bumped"):
6520 6546 numtrouble = len(repo.revs(trouble + "()"))
6521 6547 # We write all the possibilities to ease translation
6522 6548 troublemsg = {
6523 6549 "unstable": _("unstable: %d changeset"),
6524 6550 "divergent": _("divergent: %d changeset"),
6525 6551 "bumped": _("bumped: %d changeset"),
6526 6552 }
6527 6553 if numtrouble > 0:
6528 6554 ui.status(troublemsg[trouble] % numtrouble + "\n")
6529 6555
6530 6556 cmdutil.summaryhooks(ui, repo)
6531 6557
6532 6558 if opts.get('remote'):
6533 6559 needsincoming, needsoutgoing = True, True
6534 6560 else:
6535 6561 needsincoming, needsoutgoing = False, False
6536 6562 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6537 6563 if i:
6538 6564 needsincoming = True
6539 6565 if o:
6540 6566 needsoutgoing = True
6541 6567 if not needsincoming and not needsoutgoing:
6542 6568 return
6543 6569
6544 6570 def getincoming():
6545 6571 source, branches = hg.parseurl(ui.expandpath('default'))
6546 6572 sbranch = branches[0]
6547 6573 try:
6548 6574 other = hg.peer(repo, {}, source)
6549 6575 except error.RepoError:
6550 6576 if opts.get('remote'):
6551 6577 raise
6552 6578 return source, sbranch, None, None, None
6553 6579 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6554 6580 if revs:
6555 6581 revs = [other.lookup(rev) for rev in revs]
6556 6582 ui.debug('comparing with %s\n' % util.hidepassword(source))
6557 6583 repo.ui.pushbuffer()
6558 6584 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6559 6585 repo.ui.popbuffer()
6560 6586 return source, sbranch, other, commoninc, commoninc[1]
6561 6587
6562 6588 if needsincoming:
6563 6589 source, sbranch, sother, commoninc, incoming = getincoming()
6564 6590 else:
6565 6591 source = sbranch = sother = commoninc = incoming = None
6566 6592
6567 6593 def getoutgoing():
6568 6594 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6569 6595 dbranch = branches[0]
6570 6596 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6571 6597 if source != dest:
6572 6598 try:
6573 6599 dother = hg.peer(repo, {}, dest)
6574 6600 except error.RepoError:
6575 6601 if opts.get('remote'):
6576 6602 raise
6577 6603 return dest, dbranch, None, None
6578 6604 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6579 6605 elif sother is None:
6580 6606 # there is no explicit destination peer, but source one is invalid
6581 6607 return dest, dbranch, None, None
6582 6608 else:
6583 6609 dother = sother
6584 6610 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6585 6611 common = None
6586 6612 else:
6587 6613 common = commoninc
6588 6614 if revs:
6589 6615 revs = [repo.lookup(rev) for rev in revs]
6590 6616 repo.ui.pushbuffer()
6591 6617 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6592 6618 commoninc=common)
6593 6619 repo.ui.popbuffer()
6594 6620 return dest, dbranch, dother, outgoing
6595 6621
6596 6622 if needsoutgoing:
6597 6623 dest, dbranch, dother, outgoing = getoutgoing()
6598 6624 else:
6599 6625 dest = dbranch = dother = outgoing = None
6600 6626
6601 6627 if opts.get('remote'):
6602 6628 t = []
6603 6629 if incoming:
6604 6630 t.append(_('1 or more incoming'))
6605 6631 o = outgoing.missing
6606 6632 if o:
6607 6633 t.append(_('%d outgoing') % len(o))
6608 6634 other = dother or sother
6609 6635 if 'bookmarks' in other.listkeys('namespaces'):
6610 6636 counts = bookmarks.summary(repo, other)
6611 6637 if counts[0] > 0:
6612 6638 t.append(_('%d incoming bookmarks') % counts[0])
6613 6639 if counts[1] > 0:
6614 6640 t.append(_('%d outgoing bookmarks') % counts[1])
6615 6641
6616 6642 if t:
6617 6643 # i18n: column positioning for "hg summary"
6618 6644 ui.write(_('remote: %s\n') % (', '.join(t)))
6619 6645 else:
6620 6646 # i18n: column positioning for "hg summary"
6621 6647 ui.status(_('remote: (synced)\n'))
6622 6648
6623 6649 cmdutil.summaryremotehooks(ui, repo, opts,
6624 6650 ((source, sbranch, sother, commoninc),
6625 6651 (dest, dbranch, dother, outgoing)))
6626 6652
6627 6653 @command('tag',
6628 6654 [('f', 'force', None, _('force tag')),
6629 6655 ('l', 'local', None, _('make the tag local')),
6630 6656 ('r', 'rev', '', _('revision to tag'), _('REV')),
6631 6657 ('', 'remove', None, _('remove a tag')),
6632 6658 # -l/--local is already there, commitopts cannot be used
6633 6659 ('e', 'edit', None, _('invoke editor on commit messages')),
6634 6660 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6635 6661 ] + commitopts2,
6636 6662 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6637 6663 def tag(ui, repo, name1, *names, **opts):
6638 6664 """add one or more tags for the current or given revision
6639 6665
6640 6666 Name a particular revision using <name>.
6641 6667
6642 6668 Tags are used to name particular revisions of the repository and are
6643 6669 very useful to compare different revisions, to go back to significant
6644 6670 earlier versions or to mark branch points as releases, etc. Changing
6645 6671 an existing tag is normally disallowed; use -f/--force to override.
6646 6672
6647 6673 If no revision is given, the parent of the working directory is
6648 6674 used.
6649 6675
6650 6676 To facilitate version control, distribution, and merging of tags,
6651 6677 they are stored as a file named ".hgtags" which is managed similarly
6652 6678 to other project files and can be hand-edited if necessary. This
6653 6679 also means that tagging creates a new commit. The file
6654 6680 ".hg/localtags" is used for local tags (not shared among
6655 6681 repositories).
6656 6682
6657 6683 Tag commits are usually made at the head of a branch. If the parent
6658 6684 of the working directory is not a branch head, :hg:`tag` aborts; use
6659 6685 -f/--force to force the tag commit to be based on a non-head
6660 6686 changeset.
6661 6687
6662 6688 See :hg:`help dates` for a list of formats valid for -d/--date.
6663 6689
6664 6690 Since tag names have priority over branch names during revision
6665 6691 lookup, using an existing branch name as a tag name is discouraged.
6666 6692
6667 6693 Returns 0 on success.
6668 6694 """
6669 6695 wlock = lock = None
6670 6696 try:
6671 6697 wlock = repo.wlock()
6672 6698 lock = repo.lock()
6673 6699 rev_ = "."
6674 6700 names = [t.strip() for t in (name1,) + names]
6675 6701 if len(names) != len(set(names)):
6676 6702 raise error.Abort(_('tag names must be unique'))
6677 6703 for n in names:
6678 6704 scmutil.checknewlabel(repo, n, 'tag')
6679 6705 if not n:
6680 6706 raise error.Abort(_('tag names cannot consist entirely of '
6681 6707 'whitespace'))
6682 6708 if opts.get('rev') and opts.get('remove'):
6683 6709 raise error.Abort(_("--rev and --remove are incompatible"))
6684 6710 if opts.get('rev'):
6685 6711 rev_ = opts['rev']
6686 6712 message = opts.get('message')
6687 6713 if opts.get('remove'):
6688 6714 if opts.get('local'):
6689 6715 expectedtype = 'local'
6690 6716 else:
6691 6717 expectedtype = 'global'
6692 6718
6693 6719 for n in names:
6694 6720 if not repo.tagtype(n):
6695 6721 raise error.Abort(_("tag '%s' does not exist") % n)
6696 6722 if repo.tagtype(n) != expectedtype:
6697 6723 if expectedtype == 'global':
6698 6724 raise error.Abort(_("tag '%s' is not a global tag") % n)
6699 6725 else:
6700 6726 raise error.Abort(_("tag '%s' is not a local tag") % n)
6701 6727 rev_ = 'null'
6702 6728 if not message:
6703 6729 # we don't translate commit messages
6704 6730 message = 'Removed tag %s' % ', '.join(names)
6705 6731 elif not opts.get('force'):
6706 6732 for n in names:
6707 6733 if n in repo.tags():
6708 6734 raise error.Abort(_("tag '%s' already exists "
6709 6735 "(use -f to force)") % n)
6710 6736 if not opts.get('local'):
6711 6737 p1, p2 = repo.dirstate.parents()
6712 6738 if p2 != nullid:
6713 6739 raise error.Abort(_('uncommitted merge'))
6714 6740 bheads = repo.branchheads()
6715 6741 if not opts.get('force') and bheads and p1 not in bheads:
6716 6742 raise error.Abort(_('not at a branch head (use -f to force)'))
6717 6743 r = scmutil.revsingle(repo, rev_).node()
6718 6744
6719 6745 if not message:
6720 6746 # we don't translate commit messages
6721 6747 message = ('Added tag %s for changeset %s' %
6722 6748 (', '.join(names), short(r)))
6723 6749
6724 6750 date = opts.get('date')
6725 6751 if date:
6726 6752 date = util.parsedate(date)
6727 6753
6728 6754 if opts.get('remove'):
6729 6755 editform = 'tag.remove'
6730 6756 else:
6731 6757 editform = 'tag.add'
6732 6758 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6733 6759
6734 6760 # don't allow tagging the null rev
6735 6761 if (not opts.get('remove') and
6736 6762 scmutil.revsingle(repo, rev_).rev() == nullrev):
6737 6763 raise error.Abort(_("cannot tag null revision"))
6738 6764
6739 6765 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6740 6766 editor=editor)
6741 6767 finally:
6742 6768 release(lock, wlock)
6743 6769
6744 6770 @command('tags', formatteropts, '')
6745 6771 def tags(ui, repo, **opts):
6746 6772 """list repository tags
6747 6773
6748 6774 This lists both regular and local tags. When the -v/--verbose
6749 6775 switch is used, a third column "local" is printed for local tags.
6750 6776 When the -q/--quiet switch is used, only the tag name is printed.
6751 6777
6752 6778 Returns 0 on success.
6753 6779 """
6754 6780
6755 6781 fm = ui.formatter('tags', opts)
6756 6782 hexfunc = fm.hexfunc
6757 6783 tagtype = ""
6758 6784
6759 6785 for t, n in reversed(repo.tagslist()):
6760 6786 hn = hexfunc(n)
6761 6787 label = 'tags.normal'
6762 6788 tagtype = ''
6763 6789 if repo.tagtype(t) == 'local':
6764 6790 label = 'tags.local'
6765 6791 tagtype = 'local'
6766 6792
6767 6793 fm.startitem()
6768 6794 fm.write('tag', '%s', t, label=label)
6769 6795 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6770 6796 fm.condwrite(not ui.quiet, 'rev node', fmt,
6771 6797 repo.changelog.rev(n), hn, label=label)
6772 6798 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6773 6799 tagtype, label=label)
6774 6800 fm.plain('\n')
6775 6801 fm.end()
6776 6802
6777 6803 @command('tip',
6778 6804 [('p', 'patch', None, _('show patch')),
6779 6805 ('g', 'git', None, _('use git extended diff format')),
6780 6806 ] + templateopts,
6781 6807 _('[-p] [-g]'))
6782 6808 def tip(ui, repo, **opts):
6783 6809 """show the tip revision (DEPRECATED)
6784 6810
6785 6811 The tip revision (usually just called the tip) is the changeset
6786 6812 most recently added to the repository (and therefore the most
6787 6813 recently changed head).
6788 6814
6789 6815 If you have just made a commit, that commit will be the tip. If
6790 6816 you have just pulled changes from another repository, the tip of
6791 6817 that repository becomes the current tip. The "tip" tag is special
6792 6818 and cannot be renamed or assigned to a different changeset.
6793 6819
6794 6820 This command is deprecated, please use :hg:`heads` instead.
6795 6821
6796 6822 Returns 0 on success.
6797 6823 """
6798 6824 displayer = cmdutil.show_changeset(ui, repo, opts)
6799 6825 displayer.show(repo['tip'])
6800 6826 displayer.close()
6801 6827
6802 6828 @command('unbundle',
6803 6829 [('u', 'update', None,
6804 6830 _('update to new branch head if changesets were unbundled'))],
6805 6831 _('[-u] FILE...'))
6806 6832 def unbundle(ui, repo, fname1, *fnames, **opts):
6807 6833 """apply one or more changegroup files
6808 6834
6809 6835 Apply one or more compressed changegroup files generated by the
6810 6836 bundle command.
6811 6837
6812 6838 Returns 0 on success, 1 if an update has unresolved files.
6813 6839 """
6814 6840 fnames = (fname1,) + fnames
6815 6841
6816 6842 lock = repo.lock()
6817 6843 try:
6818 6844 for fname in fnames:
6819 6845 f = hg.openpath(ui, fname)
6820 6846 gen = exchange.readbundle(ui, f, fname)
6821 6847 if isinstance(gen, bundle2.unbundle20):
6822 6848 tr = repo.transaction('unbundle')
6823 6849 try:
6824 6850 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6825 6851 url='bundle:' + fname)
6826 6852 tr.close()
6827 6853 except error.BundleUnknownFeatureError as exc:
6828 6854 raise error.Abort(_('%s: unknown bundle feature, %s')
6829 6855 % (fname, exc),
6830 6856 hint=_("see https://mercurial-scm.org/"
6831 6857 "wiki/BundleFeature for more "
6832 6858 "information"))
6833 6859 finally:
6834 6860 if tr:
6835 6861 tr.release()
6836 6862 changes = [r.get('return', 0)
6837 6863 for r in op.records['changegroup']]
6838 6864 modheads = changegroup.combineresults(changes)
6839 6865 elif isinstance(gen, streamclone.streamcloneapplier):
6840 6866 raise error.Abort(
6841 6867 _('packed bundles cannot be applied with '
6842 6868 '"hg unbundle"'),
6843 6869 hint=_('use "hg debugapplystreamclonebundle"'))
6844 6870 else:
6845 6871 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6846 6872 finally:
6847 6873 lock.release()
6848 6874
6849 6875 return postincoming(ui, repo, modheads, opts.get('update'), None)
6850 6876
6851 6877 @command('^update|up|checkout|co',
6852 6878 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6853 6879 ('c', 'check', None,
6854 6880 _('update across branches if no uncommitted changes')),
6855 6881 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6856 6882 ('r', 'rev', '', _('revision'), _('REV'))
6857 6883 ] + mergetoolopts,
6858 6884 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6859 6885 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6860 6886 tool=None):
6861 6887 """update working directory (or switch revisions)
6862 6888
6863 6889 Update the repository's working directory to the specified
6864 6890 changeset. If no changeset is specified, update to the tip of the
6865 6891 current named branch and move the active bookmark (see :hg:`help
6866 6892 bookmarks`).
6867 6893
6868 6894 Update sets the working directory's parent revision to the specified
6869 6895 changeset (see :hg:`help parents`).
6870 6896
6871 6897 If the changeset is not a descendant or ancestor of the working
6872 6898 directory's parent, the update is aborted. With the -c/--check
6873 6899 option, the working directory is checked for uncommitted changes; if
6874 6900 none are found, the working directory is updated to the specified
6875 6901 changeset.
6876 6902
6877 6903 .. container:: verbose
6878 6904
6879 6905 The following rules apply when the working directory contains
6880 6906 uncommitted changes:
6881 6907
6882 6908 1. If neither -c/--check nor -C/--clean is specified, and if
6883 6909 the requested changeset is an ancestor or descendant of
6884 6910 the working directory's parent, the uncommitted changes
6885 6911 are merged into the requested changeset and the merged
6886 6912 result is left uncommitted. If the requested changeset is
6887 6913 not an ancestor or descendant (that is, it is on another
6888 6914 branch), the update is aborted and the uncommitted changes
6889 6915 are preserved.
6890 6916
6891 6917 2. With the -c/--check option, the update is aborted and the
6892 6918 uncommitted changes are preserved.
6893 6919
6894 6920 3. With the -C/--clean option, uncommitted changes are discarded and
6895 6921 the working directory is updated to the requested changeset.
6896 6922
6897 6923 To cancel an uncommitted merge (and lose your changes), use
6898 6924 :hg:`update --clean .`.
6899 6925
6900 6926 Use null as the changeset to remove the working directory (like
6901 6927 :hg:`clone -U`).
6902 6928
6903 6929 If you want to revert just one file to an older revision, use
6904 6930 :hg:`revert [-r REV] NAME`.
6905 6931
6906 6932 See :hg:`help dates` for a list of formats valid for -d/--date.
6907 6933
6908 6934 Returns 0 on success, 1 if there are unresolved files.
6909 6935 """
6910 6936 movemarkfrom = None
6911 6937 if rev and node:
6912 6938 raise error.Abort(_("please specify just one revision"))
6913 6939
6914 6940 if rev is None or rev == '':
6915 6941 rev = node
6916 6942
6917 6943 wlock = repo.wlock()
6918 6944 try:
6919 6945 cmdutil.clearunfinished(repo)
6920 6946
6921 6947 if date:
6922 6948 if rev is not None:
6923 6949 raise error.Abort(_("you can't specify a revision and a date"))
6924 6950 rev = cmdutil.finddate(ui, repo, date)
6925 6951
6926 6952 # if we defined a bookmark, we have to remember the original name
6927 6953 brev = rev
6928 6954 rev = scmutil.revsingle(repo, rev, rev).rev()
6929 6955
6930 6956 if check and clean:
6931 6957 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6932 6958 )
6933 6959
6934 6960 if check:
6935 6961 cmdutil.bailifchanged(repo, merge=False)
6936 6962 if rev is None:
6937 6963 updata = destutil.destupdate(repo, clean=clean, check=check)
6938 6964 rev, movemarkfrom, brev = updata
6939 6965
6940 6966 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6941 6967
6942 6968 if clean:
6943 6969 ret = hg.clean(repo, rev)
6944 6970 else:
6945 6971 ret = hg.update(repo, rev)
6946 6972
6947 6973 if not ret and movemarkfrom:
6948 6974 if movemarkfrom == repo['.'].node():
6949 6975 pass # no-op update
6950 6976 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6951 6977 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6952 6978 else:
6953 6979 # this can happen with a non-linear update
6954 6980 ui.status(_("(leaving bookmark %s)\n") %
6955 6981 repo._activebookmark)
6956 6982 bookmarks.deactivate(repo)
6957 6983 elif brev in repo._bookmarks:
6958 6984 bookmarks.activate(repo, brev)
6959 6985 ui.status(_("(activating bookmark %s)\n") % brev)
6960 6986 elif brev:
6961 6987 if repo._activebookmark:
6962 6988 ui.status(_("(leaving bookmark %s)\n") %
6963 6989 repo._activebookmark)
6964 6990 bookmarks.deactivate(repo)
6965 6991 finally:
6966 6992 wlock.release()
6967 6993
6968 6994 return ret
6969 6995
6970 6996 @command('verify', [])
6971 6997 def verify(ui, repo):
6972 6998 """verify the integrity of the repository
6973 6999
6974 7000 Verify the integrity of the current repository.
6975 7001
6976 7002 This will perform an extensive check of the repository's
6977 7003 integrity, validating the hashes and checksums of each entry in
6978 7004 the changelog, manifest, and tracked files, as well as the
6979 7005 integrity of their crosslinks and indices.
6980 7006
6981 7007 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6982 7008 for more information about recovery from corruption of the
6983 7009 repository.
6984 7010
6985 7011 Returns 0 on success, 1 if errors are encountered.
6986 7012 """
6987 7013 return hg.verify(repo)
6988 7014
6989 7015 @command('version', [], norepo=True)
6990 7016 def version_(ui):
6991 7017 """output version and copyright information"""
6992 7018 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6993 7019 % util.version())
6994 7020 ui.status(_(
6995 7021 "(see https://mercurial-scm.org for more information)\n"
6996 7022 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6997 7023 "This is free software; see the source for copying conditions. "
6998 7024 "There is NO\nwarranty; "
6999 7025 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7000 7026 ))
7001 7027
7002 7028 ui.note(_("\nEnabled extensions:\n\n"))
7003 7029 if ui.verbose:
7004 7030 # format names and versions into columns
7005 7031 names = []
7006 7032 vers = []
7007 7033 for name, module in extensions.extensions():
7008 7034 names.append(name)
7009 7035 vers.append(extensions.moduleversion(module))
7010 7036 if names:
7011 7037 maxnamelen = max(len(n) for n in names)
7012 7038 for i, name in enumerate(names):
7013 7039 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,2985 +1,2986 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 internals Technical implementation topics
115 115 merge-tools Merge Tools
116 116 multirevs Specifying Multiple Revisions
117 117 patterns File Name Patterns
118 118 phases Working with Phases
119 119 revisions Specifying Single Revisions
120 120 revsets Specifying Revision Sets
121 121 scripting Using Mercurial from scripts and automation
122 122 subrepos Subrepositories
123 123 templating Template Usage
124 124 urls URL Paths
125 125
126 126 (use "hg help -v" to show built-in aliases and global options)
127 127
128 128 $ hg -q help
129 129 add add the specified files on the next commit
130 130 addremove add all new files, delete all missing files
131 131 annotate show changeset information by line for each file
132 132 archive create an unversioned archive of a repository revision
133 133 backout reverse effect of earlier changeset
134 134 bisect subdivision search of changesets
135 135 bookmarks create a new bookmark or list existing bookmarks
136 136 branch set or show the current branch name
137 137 branches list repository named branches
138 138 bundle create a changegroup file
139 139 cat output the current or given revision of files
140 140 clone make a copy of an existing repository
141 141 commit commit the specified files or all outstanding changes
142 142 config show combined config settings from all hgrc files
143 143 copy mark files as copied for the next commit
144 144 diff diff repository (or selected files)
145 145 export dump the header and diffs for one or more changesets
146 146 files list tracked files
147 147 forget forget the specified files on the next commit
148 148 graft copy changes from other branches onto the current branch
149 149 grep search for a pattern in specified files and revisions
150 150 heads show branch heads
151 151 help show help for a given topic or a help overview
152 152 identify identify the working directory or specified revision
153 153 import import an ordered set of patches
154 154 incoming show new changesets found in source
155 155 init create a new repository in the given directory
156 156 log show revision history of entire repository or files
157 157 manifest output the current or given revision of the project manifest
158 158 merge merge another revision into working directory
159 159 outgoing show changesets not found in the destination
160 160 paths show aliases for remote repositories
161 161 phase set or show the current phase name
162 162 pull pull changes from the specified source
163 163 push push changes to the specified destination
164 164 recover roll back an interrupted transaction
165 165 remove remove the specified files on the next commit
166 166 rename rename files; equivalent of copy + remove
167 167 resolve redo merges or set/view the merge status of files
168 168 revert restore files to their checkout state
169 169 root print the root (top) of the current working directory
170 170 serve start stand-alone webserver
171 171 status show changed files in the working directory
172 172 summary summarize working directory state
173 173 tag add one or more tags for the current or given revision
174 174 tags list repository tags
175 175 unbundle apply one or more changegroup files
176 176 update update working directory (or switch revisions)
177 177 verify verify the integrity of the repository
178 178 version output version and copyright information
179 179
180 180 additional help topics:
181 181
182 182 config Configuration Files
183 183 dates Date Formats
184 184 diffs Diff Formats
185 185 environment Environment Variables
186 186 extensions Using Additional Features
187 187 filesets Specifying File Sets
188 188 glossary Glossary
189 189 hgignore Syntax for Mercurial Ignore Files
190 190 hgweb Configuring hgweb
191 191 internals Technical implementation topics
192 192 merge-tools Merge Tools
193 193 multirevs Specifying Multiple Revisions
194 194 patterns File Name Patterns
195 195 phases Working with Phases
196 196 revisions Specifying Single Revisions
197 197 revsets Specifying Revision Sets
198 198 scripting Using Mercurial from scripts and automation
199 199 subrepos Subrepositories
200 200 templating Template Usage
201 201 urls URL Paths
202 202
203 203 Test extension help:
204 204 $ hg help extensions --config extensions.rebase= --config extensions.children=
205 205 Using Additional Features
206 206 """""""""""""""""""""""""
207 207
208 208 Mercurial has the ability to add new features through the use of
209 209 extensions. Extensions may add new commands, add options to existing
210 210 commands, change the default behavior of commands, or implement hooks.
211 211
212 212 To enable the "foo" extension, either shipped with Mercurial or in the
213 213 Python search path, create an entry for it in your configuration file,
214 214 like this:
215 215
216 216 [extensions]
217 217 foo =
218 218
219 219 You may also specify the full path to an extension:
220 220
221 221 [extensions]
222 222 myfeature = ~/.hgext/myfeature.py
223 223
224 224 See "hg help config" for more information on configuration files.
225 225
226 226 Extensions are not loaded by default for a variety of reasons: they can
227 227 increase startup overhead; they may be meant for advanced usage only; they
228 228 may provide potentially dangerous abilities (such as letting you destroy
229 229 or modify history); they might not be ready for prime time; or they may
230 230 alter some usual behaviors of stock Mercurial. It is thus up to the user
231 231 to activate extensions as needed.
232 232
233 233 To explicitly disable an extension enabled in a configuration file of
234 234 broader scope, prepend its path with !:
235 235
236 236 [extensions]
237 237 # disabling extension bar residing in /path/to/extension/bar.py
238 238 bar = !/path/to/extension/bar.py
239 239 # ditto, but no path was supplied for extension baz
240 240 baz = !
241 241
242 242 enabled extensions:
243 243
244 244 children command to display child changesets (DEPRECATED)
245 245 rebase command to move sets of revisions to a different ancestor
246 246
247 247 disabled extensions:
248 248
249 249 acl hooks for controlling repository access
250 250 blackbox log repository events to a blackbox for debugging
251 251 bugzilla hooks for integrating with the Bugzilla bug tracker
252 252 censor erase file content at a given revision
253 253 churn command to display statistics about repository history
254 254 clonebundles advertise pre-generated bundles to seed clones
255 255 (experimental)
256 256 color colorize output from some commands
257 257 convert import revisions from foreign VCS repositories into
258 258 Mercurial
259 259 eol automatically manage newlines in repository files
260 260 extdiff command to allow external programs to compare revisions
261 261 factotum http authentication with factotum
262 262 gpg commands to sign and verify changesets
263 263 hgcia hooks for integrating with the CIA.vc notification service
264 264 hgk browse the repository in a graphical way
265 265 highlight syntax highlighting for hgweb (requires Pygments)
266 266 histedit interactive history editing
267 267 keyword expand keywords in tracked files
268 268 largefiles track large binary files
269 269 mq manage a stack of patches
270 270 notify hooks for sending email push notifications
271 271 pager browse command output with an external pager
272 272 patchbomb command to send changesets as (a series of) patch emails
273 273 purge command to delete untracked files from the working
274 274 directory
275 275 record commands to interactively select changes for
276 276 commit/qrefresh
277 277 relink recreates hardlinks between repository clones
278 278 schemes extend schemes with shortcuts to repository swarms
279 279 share share a common history between several working directories
280 280 shelve save and restore changes to the working directory
281 281 strip strip changesets and their descendants from history
282 282 transplant command to transplant changesets from another branch
283 283 win32mbcs allow the use of MBCS paths with problematic encodings
284 284 zeroconf discover and advertise repositories on the local network
285 285
286 286 Verify that extension keywords appear in help templates
287 287
288 288 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
289 289
290 290 Test short command list with verbose option
291 291
292 292 $ hg -v help shortlist
293 293 Mercurial Distributed SCM
294 294
295 295 basic commands:
296 296
297 297 add add the specified files on the next commit
298 298 annotate, blame
299 299 show changeset information by line for each file
300 300 clone make a copy of an existing repository
301 301 commit, ci commit the specified files or all outstanding changes
302 302 diff diff repository (or selected files)
303 303 export dump the header and diffs for one or more changesets
304 304 forget forget the specified files on the next commit
305 305 init create a new repository in the given directory
306 306 log, history show revision history of entire repository or files
307 307 merge merge another revision into working directory
308 308 pull pull changes from the specified source
309 309 push push changes to the specified destination
310 310 remove, rm remove the specified files on the next commit
311 311 serve start stand-alone webserver
312 312 status, st show changed files in the working directory
313 313 summary, sum summarize working directory state
314 314 update, up, checkout, co
315 315 update working directory (or switch revisions)
316 316
317 317 global options ([+] can be repeated):
318 318
319 319 -R --repository REPO repository root directory or name of overlay bundle
320 320 file
321 321 --cwd DIR change working directory
322 322 -y --noninteractive do not prompt, automatically pick the first choice for
323 323 all prompts
324 324 -q --quiet suppress output
325 325 -v --verbose enable additional output
326 326 --config CONFIG [+] set/override config option (use 'section.name=value')
327 327 --debug enable debugging output
328 328 --debugger start debugger
329 329 --encoding ENCODE set the charset encoding (default: ascii)
330 330 --encodingmode MODE set the charset encoding mode (default: strict)
331 331 --traceback always print a traceback on exception
332 332 --time time how long the command takes
333 333 --profile print command execution profile
334 334 --version output version information and exit
335 335 -h --help display help and exit
336 336 --hidden consider hidden changesets
337 337
338 338 (use "hg help" for the full list of commands)
339 339
340 340 $ hg add -h
341 341 hg add [OPTION]... [FILE]...
342 342
343 343 add the specified files on the next commit
344 344
345 345 Schedule files to be version controlled and added to the repository.
346 346
347 347 The files will be added to the repository at the next commit. To undo an
348 348 add before that, see "hg forget".
349 349
350 350 If no names are given, add all files to the repository (except files
351 351 matching ".hgignore").
352 352
353 353 Returns 0 if all files are successfully added.
354 354
355 355 options ([+] can be repeated):
356 356
357 357 -I --include PATTERN [+] include names matching the given patterns
358 358 -X --exclude PATTERN [+] exclude names matching the given patterns
359 359 -S --subrepos recurse into subrepositories
360 360 -n --dry-run do not perform actions, just print output
361 361
362 362 (some details hidden, use --verbose to show complete help)
363 363
364 364 Verbose help for add
365 365
366 366 $ hg add -hv
367 367 hg add [OPTION]... [FILE]...
368 368
369 369 add the specified files on the next commit
370 370
371 371 Schedule files to be version controlled and added to the repository.
372 372
373 373 The files will be added to the repository at the next commit. To undo an
374 374 add before that, see "hg forget".
375 375
376 376 If no names are given, add all files to the repository (except files
377 377 matching ".hgignore").
378 378
379 379 Examples:
380 380
381 381 - New (unknown) files are added automatically by "hg add":
382 382
383 383 $ ls
384 384 foo.c
385 385 $ hg status
386 386 ? foo.c
387 387 $ hg add
388 388 adding foo.c
389 389 $ hg status
390 390 A foo.c
391 391
392 392 - Specific files to be added can be specified:
393 393
394 394 $ ls
395 395 bar.c foo.c
396 396 $ hg status
397 397 ? bar.c
398 398 ? foo.c
399 399 $ hg add bar.c
400 400 $ hg status
401 401 A bar.c
402 402 ? foo.c
403 403
404 404 Returns 0 if all files are successfully added.
405 405
406 406 options ([+] can be repeated):
407 407
408 408 -I --include PATTERN [+] include names matching the given patterns
409 409 -X --exclude PATTERN [+] exclude names matching the given patterns
410 410 -S --subrepos recurse into subrepositories
411 411 -n --dry-run do not perform actions, just print output
412 412
413 413 global options ([+] can be repeated):
414 414
415 415 -R --repository REPO repository root directory or name of overlay bundle
416 416 file
417 417 --cwd DIR change working directory
418 418 -y --noninteractive do not prompt, automatically pick the first choice for
419 419 all prompts
420 420 -q --quiet suppress output
421 421 -v --verbose enable additional output
422 422 --config CONFIG [+] set/override config option (use 'section.name=value')
423 423 --debug enable debugging output
424 424 --debugger start debugger
425 425 --encoding ENCODE set the charset encoding (default: ascii)
426 426 --encodingmode MODE set the charset encoding mode (default: strict)
427 427 --traceback always print a traceback on exception
428 428 --time time how long the command takes
429 429 --profile print command execution profile
430 430 --version output version information and exit
431 431 -h --help display help and exit
432 432 --hidden consider hidden changesets
433 433
434 434 Test help option with version option
435 435
436 436 $ hg add -h --version
437 437 Mercurial Distributed SCM (version *) (glob)
438 438 (see https://mercurial-scm.org for more information)
439 439
440 440 Copyright (C) 2005-2015 Matt Mackall and others
441 441 This is free software; see the source for copying conditions. There is NO
442 442 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
443 443
444 444 $ hg add --skjdfks
445 445 hg add: option --skjdfks not recognized
446 446 hg add [OPTION]... [FILE]...
447 447
448 448 add the specified files on the next commit
449 449
450 450 options ([+] can be repeated):
451 451
452 452 -I --include PATTERN [+] include names matching the given patterns
453 453 -X --exclude PATTERN [+] exclude names matching the given patterns
454 454 -S --subrepos recurse into subrepositories
455 455 -n --dry-run do not perform actions, just print output
456 456
457 457 (use "hg add -h" to show more help)
458 458 [255]
459 459
460 460 Test ambiguous command help
461 461
462 462 $ hg help ad
463 463 list of commands:
464 464
465 465 add add the specified files on the next commit
466 466 addremove add all new files, delete all missing files
467 467
468 468 (use "hg help -v ad" to show built-in aliases and global options)
469 469
470 470 Test command without options
471 471
472 472 $ hg help verify
473 473 hg verify
474 474
475 475 verify the integrity of the repository
476 476
477 477 Verify the integrity of the current repository.
478 478
479 479 This will perform an extensive check of the repository's integrity,
480 480 validating the hashes and checksums of each entry in the changelog,
481 481 manifest, and tracked files, as well as the integrity of their crosslinks
482 482 and indices.
483 483
484 484 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
485 485 information about recovery from corruption of the repository.
486 486
487 487 Returns 0 on success, 1 if errors are encountered.
488 488
489 489 (some details hidden, use --verbose to show complete help)
490 490
491 491 $ hg help diff
492 492 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
493 493
494 494 diff repository (or selected files)
495 495
496 496 Show differences between revisions for the specified files.
497 497
498 498 Differences between files are shown using the unified diff format.
499 499
500 500 Note:
501 501 "hg diff" may generate unexpected results for merges, as it will
502 502 default to comparing against the working directory's first parent
503 503 changeset if no revisions are specified.
504 504
505 505 When two revision arguments are given, then changes are shown between
506 506 those revisions. If only one revision is specified then that revision is
507 507 compared to the working directory, and, when no revisions are specified,
508 508 the working directory files are compared to its first parent.
509 509
510 510 Alternatively you can specify -c/--change with a revision to see the
511 511 changes in that changeset relative to its first parent.
512 512
513 513 Without the -a/--text option, diff will avoid generating diffs of files it
514 514 detects as binary. With -a, diff will generate a diff anyway, probably
515 515 with undesirable results.
516 516
517 517 Use the -g/--git option to generate diffs in the git extended diff format.
518 518 For more information, read "hg help diffs".
519 519
520 520 Returns 0 on success.
521 521
522 522 options ([+] can be repeated):
523 523
524 524 -r --rev REV [+] revision
525 525 -c --change REV change made by revision
526 526 -a --text treat all files as text
527 527 -g --git use git extended diff format
528 528 --nodates omit dates from diff headers
529 529 --noprefix omit a/ and b/ prefixes from filenames
530 530 -p --show-function show which function each change is in
531 531 --reverse produce a diff that undoes the changes
532 532 -w --ignore-all-space ignore white space when comparing lines
533 533 -b --ignore-space-change ignore changes in the amount of white space
534 534 -B --ignore-blank-lines ignore changes whose lines are all blank
535 535 -U --unified NUM number of lines of context to show
536 536 --stat output diffstat-style summary of changes
537 537 --root DIR produce diffs relative to subdirectory
538 538 -I --include PATTERN [+] include names matching the given patterns
539 539 -X --exclude PATTERN [+] exclude names matching the given patterns
540 540 -S --subrepos recurse into subrepositories
541 541
542 542 (some details hidden, use --verbose to show complete help)
543 543
544 544 $ hg help status
545 545 hg status [OPTION]... [FILE]...
546 546
547 547 aliases: st
548 548
549 549 show changed files in the working directory
550 550
551 551 Show status of files in the repository. If names are given, only files
552 552 that match are shown. Files that are clean or ignored or the source of a
553 553 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
554 554 -C/--copies or -A/--all are given. Unless options described with "show
555 555 only ..." are given, the options -mardu are used.
556 556
557 557 Option -q/--quiet hides untracked (unknown and ignored) files unless
558 558 explicitly requested with -u/--unknown or -i/--ignored.
559 559
560 560 Note:
561 561 "hg status" may appear to disagree with diff if permissions have
562 562 changed or a merge has occurred. The standard diff format does not
563 563 report permission changes and diff only reports changes relative to one
564 564 merge parent.
565 565
566 566 If one revision is given, it is used as the base revision. If two
567 567 revisions are given, the differences between them are shown. The --change
568 568 option can also be used as a shortcut to list the changed files of a
569 569 revision from its first parent.
570 570
571 571 The codes used to show the status of files are:
572 572
573 573 M = modified
574 574 A = added
575 575 R = removed
576 576 C = clean
577 577 ! = missing (deleted by non-hg command, but still tracked)
578 578 ? = not tracked
579 579 I = ignored
580 580 = origin of the previous file (with --copies)
581 581
582 582 Returns 0 on success.
583 583
584 584 options ([+] can be repeated):
585 585
586 586 -A --all show status of all files
587 587 -m --modified show only modified files
588 588 -a --added show only added files
589 589 -r --removed show only removed files
590 590 -d --deleted show only deleted (but tracked) files
591 591 -c --clean show only files without changes
592 592 -u --unknown show only unknown (not tracked) files
593 593 -i --ignored show only ignored files
594 594 -n --no-status hide status prefix
595 595 -C --copies show source of copied files
596 596 -0 --print0 end filenames with NUL, for use with xargs
597 597 --rev REV [+] show difference from revision
598 598 --change REV list the changed files of a revision
599 599 -I --include PATTERN [+] include names matching the given patterns
600 600 -X --exclude PATTERN [+] exclude names matching the given patterns
601 601 -S --subrepos recurse into subrepositories
602 602
603 603 (some details hidden, use --verbose to show complete help)
604 604
605 605 $ hg -q help status
606 606 hg status [OPTION]... [FILE]...
607 607
608 608 show changed files in the working directory
609 609
610 610 $ hg help foo
611 611 abort: no such help topic: foo
612 612 (try "hg help --keyword foo")
613 613 [255]
614 614
615 615 $ hg skjdfks
616 616 hg: unknown command 'skjdfks'
617 617 Mercurial Distributed SCM
618 618
619 619 basic commands:
620 620
621 621 add add the specified files on the next commit
622 622 annotate show changeset information by line for each file
623 623 clone make a copy of an existing repository
624 624 commit commit the specified files or all outstanding changes
625 625 diff diff repository (or selected files)
626 626 export dump the header and diffs for one or more changesets
627 627 forget forget the specified files on the next commit
628 628 init create a new repository in the given directory
629 629 log show revision history of entire repository or files
630 630 merge merge another revision into working directory
631 631 pull pull changes from the specified source
632 632 push push changes to the specified destination
633 633 remove remove the specified files on the next commit
634 634 serve start stand-alone webserver
635 635 status show changed files in the working directory
636 636 summary summarize working directory state
637 637 update update working directory (or switch revisions)
638 638
639 639 (use "hg help" for the full list of commands or "hg -v" for details)
640 640 [255]
641 641
642 642
643 643 Make sure that we don't run afoul of the help system thinking that
644 644 this is a section and erroring out weirdly.
645 645
646 646 $ hg .log
647 647 hg: unknown command '.log'
648 648 (did you mean log?)
649 649 [255]
650 650
651 651 $ hg log.
652 652 hg: unknown command 'log.'
653 653 (did you mean log?)
654 654 [255]
655 655 $ hg pu.lh
656 656 hg: unknown command 'pu.lh'
657 657 (did you mean one of pull, push?)
658 658 [255]
659 659
660 660 $ cat > helpext.py <<EOF
661 661 > import os
662 662 > from mercurial import cmdutil, commands
663 663 >
664 664 > cmdtable = {}
665 665 > command = cmdutil.command(cmdtable)
666 666 >
667 667 > @command('nohelp',
668 668 > [('', 'longdesc', 3, 'x'*90),
669 669 > ('n', '', None, 'normal desc'),
670 670 > ('', 'newline', '', 'line1\nline2')],
671 671 > 'hg nohelp',
672 672 > norepo=True)
673 673 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
674 674 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
675 675 > def nohelp(ui, *args, **kwargs):
676 676 > pass
677 677 >
678 678 > EOF
679 679 $ echo '[extensions]' >> $HGRCPATH
680 680 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
681 681
682 682 Test command with no help text
683 683
684 684 $ hg help nohelp
685 685 hg nohelp
686 686
687 687 (no help text available)
688 688
689 689 options:
690 690
691 691 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
692 692 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
693 693 -n -- normal desc
694 694 --newline VALUE line1 line2
695 695
696 696 (some details hidden, use --verbose to show complete help)
697 697
698 698 $ hg help -k nohelp
699 699 Commands:
700 700
701 701 nohelp hg nohelp
702 702
703 703 Extension Commands:
704 704
705 705 nohelp (no help text available)
706 706
707 707 Test that default list of commands omits extension commands
708 708
709 709 $ hg help
710 710 Mercurial Distributed SCM
711 711
712 712 list of commands:
713 713
714 714 add add the specified files on the next commit
715 715 addremove add all new files, delete all missing files
716 716 annotate show changeset information by line for each file
717 717 archive create an unversioned archive of a repository revision
718 718 backout reverse effect of earlier changeset
719 719 bisect subdivision search of changesets
720 720 bookmarks create a new bookmark or list existing bookmarks
721 721 branch set or show the current branch name
722 722 branches list repository named branches
723 723 bundle create a changegroup file
724 724 cat output the current or given revision of files
725 725 clone make a copy of an existing repository
726 726 commit commit the specified files or all outstanding changes
727 727 config show combined config settings from all hgrc files
728 728 copy mark files as copied for the next commit
729 729 diff diff repository (or selected files)
730 730 export dump the header and diffs for one or more changesets
731 731 files list tracked files
732 732 forget forget the specified files on the next commit
733 733 graft copy changes from other branches onto the current branch
734 734 grep search for a pattern in specified files and revisions
735 735 heads show branch heads
736 736 help show help for a given topic or a help overview
737 737 identify identify the working directory or specified revision
738 738 import import an ordered set of patches
739 739 incoming show new changesets found in source
740 740 init create a new repository in the given directory
741 741 log show revision history of entire repository or files
742 742 manifest output the current or given revision of the project manifest
743 743 merge merge another revision into working directory
744 744 outgoing show changesets not found in the destination
745 745 paths show aliases for remote repositories
746 746 phase set or show the current phase name
747 747 pull pull changes from the specified source
748 748 push push changes to the specified destination
749 749 recover roll back an interrupted transaction
750 750 remove remove the specified files on the next commit
751 751 rename rename files; equivalent of copy + remove
752 752 resolve redo merges or set/view the merge status of files
753 753 revert restore files to their checkout state
754 754 root print the root (top) of the current working directory
755 755 serve start stand-alone webserver
756 756 status show changed files in the working directory
757 757 summary summarize working directory state
758 758 tag add one or more tags for the current or given revision
759 759 tags list repository tags
760 760 unbundle apply one or more changegroup files
761 761 update update working directory (or switch revisions)
762 762 verify verify the integrity of the repository
763 763 version output version and copyright information
764 764
765 765 enabled extensions:
766 766
767 767 helpext (no help text available)
768 768
769 769 additional help topics:
770 770
771 771 config Configuration Files
772 772 dates Date Formats
773 773 diffs Diff Formats
774 774 environment Environment Variables
775 775 extensions Using Additional Features
776 776 filesets Specifying File Sets
777 777 glossary Glossary
778 778 hgignore Syntax for Mercurial Ignore Files
779 779 hgweb Configuring hgweb
780 780 internals Technical implementation topics
781 781 merge-tools Merge Tools
782 782 multirevs Specifying Multiple Revisions
783 783 patterns File Name Patterns
784 784 phases Working with Phases
785 785 revisions Specifying Single Revisions
786 786 revsets Specifying Revision Sets
787 787 scripting Using Mercurial from scripts and automation
788 788 subrepos Subrepositories
789 789 templating Template Usage
790 790 urls URL Paths
791 791
792 792 (use "hg help -v" to show built-in aliases and global options)
793 793
794 794
795 795 Test list of internal help commands
796 796
797 797 $ hg help debug
798 798 debug commands (internal and unsupported):
799 799
800 800 debugancestor
801 801 find the ancestor revision of two revisions in a given index
802 802 debugapplystreamclonebundle
803 803 apply a stream clone bundle file
804 804 debugbuilddag
805 805 builds a repo with a given DAG from scratch in the current
806 806 empty repo
807 807 debugbundle lists the contents of a bundle
808 808 debugcheckstate
809 809 validate the correctness of the current dirstate
810 810 debugcommands
811 811 list all available commands and options
812 812 debugcomplete
813 813 returns the completion list associated with the given command
814 814 debugcreatestreamclonebundle
815 815 create a stream clone bundle file
816 816 debugdag format the changelog or an index DAG as a concise textual
817 817 description
818 818 debugdata dump the contents of a data file revision
819 819 debugdate parse and display a date
820 820 debugdeltachain
821 821 dump information about delta chains in a revlog
822 822 debugdirstate
823 823 show the contents of the current dirstate
824 824 debugdiscovery
825 825 runs the changeset discovery protocol in isolation
826 826 debugextensions
827 827 show information about active extensions
828 828 debugfileset parse and apply a fileset specification
829 829 debugfsinfo show information detected about current filesystem
830 830 debuggetbundle
831 831 retrieves a bundle from a repo
832 debugignore display the combined ignore pattern
832 debugignore display the combined ignore pattern and information about
833 ignored files
833 834 debugindex dump the contents of an index file
834 835 debugindexdot
835 836 dump an index DAG as a graphviz dot file
836 837 debuginstall test Mercurial installation
837 838 debugknown test whether node ids are known to a repo
838 839 debuglocks show or modify state of locks
839 840 debugmergestate
840 841 print merge state
841 842 debugnamecomplete
842 843 complete "names" - tags, open branch names, bookmark names
843 844 debugobsolete
844 845 create arbitrary obsolete marker
845 846 debugoptDEP (no help text available)
846 847 debugoptEXP (no help text available)
847 848 debugpathcomplete
848 849 complete part or all of a tracked path
849 850 debugpushkey access the pushkey key/value protocol
850 851 debugpvec (no help text available)
851 852 debugrebuilddirstate
852 853 rebuild the dirstate as it would look like for the given
853 854 revision
854 855 debugrebuildfncache
855 856 rebuild the fncache file
856 857 debugrename dump rename information
857 858 debugrevlog show data and statistics about a revlog
858 859 debugrevspec parse and apply a revision specification
859 860 debugsetparents
860 861 manually set the parents of the current working directory
861 862 debugsub (no help text available)
862 863 debugsuccessorssets
863 864 show set of successors for revision
864 865 debugwalk show how files match on given patterns
865 866 debugwireargs
866 867 (no help text available)
867 868
868 869 (use "hg help -v debug" to show built-in aliases and global options)
869 870
870 871 internals topic renders index of available sub-topics
871 872
872 873 $ hg help internals
873 874 Technical implementation topics
874 875 """""""""""""""""""""""""""""""
875 876
876 877 bundles container for exchange of repository data
877 878 changegroups representation of revlog data
878 879 revlogs revision storage mechanism
879 880
880 881 sub-topics can be accessed
881 882
882 883 $ hg help internals.changegroups
883 884 Changegroups
884 885 ============
885 886
886 887 Changegroups are representations of repository revlog data, specifically
887 888 the changelog, manifest, and filelogs.
888 889
889 890 There are 3 versions of changegroups: "1", "2", and "3". From a high-
890 891 level, versions "1" and "2" are almost exactly the same, with the only
891 892 difference being a header on entries in the changeset segment. Version "3"
892 893 adds support for exchanging treemanifests and includes revlog flags in the
893 894 delta header.
894 895
895 896 Changegroups consists of 3 logical segments:
896 897
897 898 +---------------------------------+
898 899 | | | |
899 900 | changeset | manifest | filelogs |
900 901 | | | |
901 902 +---------------------------------+
902 903
903 904 The principle building block of each segment is a *chunk*. A *chunk* is a
904 905 framed piece of data:
905 906
906 907 +---------------------------------------+
907 908 | | |
908 909 | length | data |
909 910 | (32 bits) | <length> bytes |
910 911 | | |
911 912 +---------------------------------------+
912 913
913 914 Each chunk starts with a 32-bit big-endian signed integer indicating the
914 915 length of the raw data that follows.
915 916
916 917 There is a special case chunk that has 0 length ("0x00000000"). We call
917 918 this an *empty chunk*.
918 919
919 920 Delta Groups
920 921 ------------
921 922
922 923 A *delta group* expresses the content of a revlog as a series of deltas,
923 924 or patches against previous revisions.
924 925
925 926 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
926 927 to signal the end of the delta group:
927 928
928 929 +------------------------------------------------------------------------+
929 930 | | | | | |
930 931 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
931 932 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
932 933 | | | | | |
933 934 +------------------------------------------------------------+-----------+
934 935
935 936 Each *chunk*'s data consists of the following:
936 937
937 938 +-----------------------------------------+
938 939 | | | |
939 940 | delta header | mdiff header | delta |
940 941 | (various) | (12 bytes) | (various) |
941 942 | | | |
942 943 +-----------------------------------------+
943 944
944 945 The *length* field is the byte length of the remaining 3 logical pieces of
945 946 data. The *delta* is a diff from an existing entry in the changelog.
946 947
947 948 The *delta header* is different between versions "1", "2", and "3" of the
948 949 changegroup format.
949 950
950 951 Version 1:
951 952
952 953 +------------------------------------------------------+
953 954 | | | | |
954 955 | node | p1 node | p2 node | link node |
955 956 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
956 957 | | | | |
957 958 +------------------------------------------------------+
958 959
959 960 Version 2:
960 961
961 962 +------------------------------------------------------------------+
962 963 | | | | | |
963 964 | node | p1 node | p2 node | base node | link node |
964 965 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
965 966 | | | | | |
966 967 +------------------------------------------------------------------+
967 968
968 969 Version 3:
969 970
970 971 +------------------------------------------------------------------------------+
971 972 | | | | | | |
972 973 | node | p1 node | p2 node | base node | link node | flags |
973 974 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
974 975 | | | | | | |
975 976 +------------------------------------------------------------------------------+
976 977
977 978 The *mdiff header* consists of 3 32-bit big-endian signed integers
978 979 describing offsets at which to apply the following delta content:
979 980
980 981 +-------------------------------------+
981 982 | | | |
982 983 | offset | old length | new length |
983 984 | (32 bits) | (32 bits) | (32 bits) |
984 985 | | | |
985 986 +-------------------------------------+
986 987
987 988 In version 1, the delta is always applied against the previous node from
988 989 the changegroup or the first parent if this is the first entry in the
989 990 changegroup.
990 991
991 992 In version 2, the delta base node is encoded in the entry in the
992 993 changegroup. This allows the delta to be expressed against any parent,
993 994 which can result in smaller deltas and more efficient encoding of data.
994 995
995 996 Changeset Segment
996 997 -----------------
997 998
998 999 The *changeset segment* consists of a single *delta group* holding
999 1000 changelog data. It is followed by an *empty chunk* to denote the boundary
1000 1001 to the *manifests segment*.
1001 1002
1002 1003 Manifest Segment
1003 1004 ----------------
1004 1005
1005 1006 The *manifest segment* consists of a single *delta group* holding manifest
1006 1007 data. It is followed by an *empty chunk* to denote the boundary to the
1007 1008 *filelogs segment*.
1008 1009
1009 1010 Filelogs Segment
1010 1011 ----------------
1011 1012
1012 1013 The *filelogs* segment consists of multiple sub-segments, each
1013 1014 corresponding to an individual file whose data is being described:
1014 1015
1015 1016 +--------------------------------------+
1016 1017 | | | | |
1017 1018 | filelog0 | filelog1 | filelog2 | ... |
1018 1019 | | | | |
1019 1020 +--------------------------------------+
1020 1021
1021 1022 In version "3" of the changegroup format, filelogs may include directory
1022 1023 logs when treemanifests are in use. directory logs are identified by
1023 1024 having a trailing '/' on their filename (see below).
1024 1025
1025 1026 The final filelog sub-segment is followed by an *empty chunk* to denote
1026 1027 the end of the segment and the overall changegroup.
1027 1028
1028 1029 Each filelog sub-segment consists of the following:
1029 1030
1030 1031 +------------------------------------------+
1031 1032 | | | |
1032 1033 | filename size | filename | delta group |
1033 1034 | (32 bits) | (various) | (various) |
1034 1035 | | | |
1035 1036 +------------------------------------------+
1036 1037
1037 1038 That is, a *chunk* consisting of the filename (not terminated or padded)
1038 1039 followed by N chunks constituting the *delta group* for this file.
1039 1040
1040 1041 Test list of commands with command with no help text
1041 1042
1042 1043 $ hg help helpext
1043 1044 helpext extension - no help text available
1044 1045
1045 1046 list of commands:
1046 1047
1047 1048 nohelp (no help text available)
1048 1049
1049 1050 (use "hg help -v helpext" to show built-in aliases and global options)
1050 1051
1051 1052
1052 1053 test deprecated and experimental options are hidden in command help
1053 1054 $ hg help debugoptDEP
1054 1055 hg debugoptDEP
1055 1056
1056 1057 (no help text available)
1057 1058
1058 1059 options:
1059 1060
1060 1061 (some details hidden, use --verbose to show complete help)
1061 1062
1062 1063 $ hg help debugoptEXP
1063 1064 hg debugoptEXP
1064 1065
1065 1066 (no help text available)
1066 1067
1067 1068 options:
1068 1069
1069 1070 (some details hidden, use --verbose to show complete help)
1070 1071
1071 1072 test deprecated and experimental options is shown with -v
1072 1073 $ hg help -v debugoptDEP | grep dopt
1073 1074 --dopt option is (DEPRECATED)
1074 1075 $ hg help -v debugoptEXP | grep eopt
1075 1076 --eopt option is (EXPERIMENTAL)
1076 1077
1077 1078 #if gettext
1078 1079 test deprecated option is hidden with translation with untranslated description
1079 1080 (use many globy for not failing on changed transaction)
1080 1081 $ LANGUAGE=sv hg help debugoptDEP
1081 1082 hg debugoptDEP
1082 1083
1083 1084 (*) (glob)
1084 1085
1085 1086 options:
1086 1087
1087 1088 (some details hidden, use --verbose to show complete help)
1088 1089 #endif
1089 1090
1090 1091 Test commands that collide with topics (issue4240)
1091 1092
1092 1093 $ hg config -hq
1093 1094 hg config [-u] [NAME]...
1094 1095
1095 1096 show combined config settings from all hgrc files
1096 1097 $ hg showconfig -hq
1097 1098 hg config [-u] [NAME]...
1098 1099
1099 1100 show combined config settings from all hgrc files
1100 1101
1101 1102 Test a help topic
1102 1103
1103 1104 $ hg help revs
1104 1105 Specifying Single Revisions
1105 1106 """""""""""""""""""""""""""
1106 1107
1107 1108 Mercurial supports several ways to specify individual revisions.
1108 1109
1109 1110 A plain integer is treated as a revision number. Negative integers are
1110 1111 treated as sequential offsets from the tip, with -1 denoting the tip, -2
1111 1112 denoting the revision prior to the tip, and so forth.
1112 1113
1113 1114 A 40-digit hexadecimal string is treated as a unique revision identifier.
1114 1115
1115 1116 A hexadecimal string less than 40 characters long is treated as a unique
1116 1117 revision identifier and is referred to as a short-form identifier. A
1117 1118 short-form identifier is only valid if it is the prefix of exactly one
1118 1119 full-length identifier.
1119 1120
1120 1121 Any other string is treated as a bookmark, tag, or branch name. A bookmark
1121 1122 is a movable pointer to a revision. A tag is a permanent name associated
1122 1123 with a revision. A branch name denotes the tipmost open branch head of
1123 1124 that branch - or if they are all closed, the tipmost closed head of the
1124 1125 branch. Bookmark, tag, and branch names must not contain the ":"
1125 1126 character.
1126 1127
1127 1128 The reserved name "tip" always identifies the most recent revision.
1128 1129
1129 1130 The reserved name "null" indicates the null revision. This is the revision
1130 1131 of an empty repository, and the parent of revision 0.
1131 1132
1132 1133 The reserved name "." indicates the working directory parent. If no
1133 1134 working directory is checked out, it is equivalent to null. If an
1134 1135 uncommitted merge is in progress, "." is the revision of the first parent.
1135 1136
1136 1137 Test repeated config section name
1137 1138
1138 1139 $ hg help config.host
1139 1140 "http_proxy.host"
1140 1141 Host name and (optional) port of the proxy server, for example
1141 1142 "myproxy:8000".
1142 1143
1143 1144 "smtp.host"
1144 1145 Host name of mail server, e.g. "mail.example.com".
1145 1146
1146 1147 Unrelated trailing paragraphs shouldn't be included
1147 1148
1148 1149 $ hg help config.extramsg | grep '^$'
1149 1150
1150 1151
1151 1152 Test capitalized section name
1152 1153
1153 1154 $ hg help scripting.HGPLAIN > /dev/null
1154 1155
1155 1156 Help subsection:
1156 1157
1157 1158 $ hg help config.charsets |grep "Email example:" > /dev/null
1158 1159 [1]
1159 1160
1160 1161 Show nested definitions
1161 1162 ("profiling.type"[break]"ls"[break]"stat"[break])
1162 1163
1163 1164 $ hg help config.type | egrep '^$'|wc -l
1164 1165 \s*3 (re)
1165 1166
1166 1167 Separate sections from subsections
1167 1168
1168 1169 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1169 1170 "format"
1170 1171 --------
1171 1172
1172 1173 "usegeneraldelta"
1173 1174
1174 1175 "dotencode"
1175 1176
1176 1177 "usefncache"
1177 1178
1178 1179 "usestore"
1179 1180
1180 1181 "profiling"
1181 1182 -----------
1182 1183
1183 1184 "format"
1184 1185
1185 1186 "progress"
1186 1187 ----------
1187 1188
1188 1189 "format"
1189 1190
1190 1191
1191 1192 Last item in help config.*:
1192 1193
1193 1194 $ hg help config.`hg help config|grep '^ "'| \
1194 1195 > tail -1|sed 's![ "]*!!g'`| \
1195 1196 > grep "hg help -c config" > /dev/null
1196 1197 [1]
1197 1198
1198 1199 note to use help -c for general hg help config:
1199 1200
1200 1201 $ hg help config |grep "hg help -c config" > /dev/null
1201 1202
1202 1203 Test templating help
1203 1204
1204 1205 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1205 1206 desc String. The text of the changeset description.
1206 1207 diffstat String. Statistics of changes with the following format:
1207 1208 firstline Any text. Returns the first line of text.
1208 1209 nonempty Any text. Returns '(none)' if the string is empty.
1209 1210
1210 1211 Test deprecated items
1211 1212
1212 1213 $ hg help -v templating | grep currentbookmark
1213 1214 currentbookmark
1214 1215 $ hg help templating | (grep currentbookmark || true)
1215 1216
1216 1217 Test help hooks
1217 1218
1218 1219 $ cat > helphook1.py <<EOF
1219 1220 > from mercurial import help
1220 1221 >
1221 1222 > def rewrite(ui, topic, doc):
1222 1223 > return doc + '\nhelphook1\n'
1223 1224 >
1224 1225 > def extsetup(ui):
1225 1226 > help.addtopichook('revsets', rewrite)
1226 1227 > EOF
1227 1228 $ cat > helphook2.py <<EOF
1228 1229 > from mercurial import help
1229 1230 >
1230 1231 > def rewrite(ui, topic, doc):
1231 1232 > return doc + '\nhelphook2\n'
1232 1233 >
1233 1234 > def extsetup(ui):
1234 1235 > help.addtopichook('revsets', rewrite)
1235 1236 > EOF
1236 1237 $ echo '[extensions]' >> $HGRCPATH
1237 1238 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1238 1239 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1239 1240 $ hg help revsets | grep helphook
1240 1241 helphook1
1241 1242 helphook2
1242 1243
1243 1244 help -c should only show debug --debug
1244 1245
1245 1246 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1246 1247 [1]
1247 1248
1248 1249 help -c should only show deprecated for -v
1249 1250
1250 1251 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1251 1252 [1]
1252 1253
1253 1254 Test -e / -c / -k combinations
1254 1255
1255 1256 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1256 1257 Commands:
1257 1258 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1258 1259 Extensions:
1259 1260 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1260 1261 Topics:
1261 1262 Commands:
1262 1263 Extensions:
1263 1264 Extension Commands:
1264 1265 $ hg help -c schemes
1265 1266 abort: no such help topic: schemes
1266 1267 (try "hg help --keyword schemes")
1267 1268 [255]
1268 1269 $ hg help -e schemes |head -1
1269 1270 schemes extension - extend schemes with shortcuts to repository swarms
1270 1271 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1271 1272 Commands:
1272 1273 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1273 1274 Extensions:
1274 1275 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1275 1276 Extensions:
1276 1277 Commands:
1277 1278 $ hg help -c commit > /dev/null
1278 1279 $ hg help -e -c commit > /dev/null
1279 1280 $ hg help -e commit > /dev/null
1280 1281 abort: no such help topic: commit
1281 1282 (try "hg help --keyword commit")
1282 1283 [255]
1283 1284
1284 1285 Test keyword search help
1285 1286
1286 1287 $ cat > prefixedname.py <<EOF
1287 1288 > '''matched against word "clone"
1288 1289 > '''
1289 1290 > EOF
1290 1291 $ echo '[extensions]' >> $HGRCPATH
1291 1292 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1292 1293 $ hg help -k clone
1293 1294 Topics:
1294 1295
1295 1296 config Configuration Files
1296 1297 extensions Using Additional Features
1297 1298 glossary Glossary
1298 1299 phases Working with Phases
1299 1300 subrepos Subrepositories
1300 1301 urls URL Paths
1301 1302
1302 1303 Commands:
1303 1304
1304 1305 bookmarks create a new bookmark or list existing bookmarks
1305 1306 clone make a copy of an existing repository
1306 1307 paths show aliases for remote repositories
1307 1308 update update working directory (or switch revisions)
1308 1309
1309 1310 Extensions:
1310 1311
1311 1312 clonebundles advertise pre-generated bundles to seed clones (experimental)
1312 1313 prefixedname matched against word "clone"
1313 1314 relink recreates hardlinks between repository clones
1314 1315
1315 1316 Extension Commands:
1316 1317
1317 1318 qclone clone main and patch repository at same time
1318 1319
1319 1320 Test unfound topic
1320 1321
1321 1322 $ hg help nonexistingtopicthatwillneverexisteverever
1322 1323 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1323 1324 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
1324 1325 [255]
1325 1326
1326 1327 Test unfound keyword
1327 1328
1328 1329 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1329 1330 abort: no matches
1330 1331 (try "hg help" for a list of topics)
1331 1332 [255]
1332 1333
1333 1334 Test omit indicating for help
1334 1335
1335 1336 $ cat > addverboseitems.py <<EOF
1336 1337 > '''extension to test omit indicating.
1337 1338 >
1338 1339 > This paragraph is never omitted (for extension)
1339 1340 >
1340 1341 > .. container:: verbose
1341 1342 >
1342 1343 > This paragraph is omitted,
1343 1344 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1344 1345 >
1345 1346 > This paragraph is never omitted, too (for extension)
1346 1347 > '''
1347 1348 >
1348 1349 > from mercurial import help, commands
1349 1350 > testtopic = """This paragraph is never omitted (for topic).
1350 1351 >
1351 1352 > .. container:: verbose
1352 1353 >
1353 1354 > This paragraph is omitted,
1354 1355 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1355 1356 >
1356 1357 > This paragraph is never omitted, too (for topic)
1357 1358 > """
1358 1359 > def extsetup(ui):
1359 1360 > help.helptable.append((["topic-containing-verbose"],
1360 1361 > "This is the topic to test omit indicating.",
1361 1362 > lambda ui: testtopic))
1362 1363 > EOF
1363 1364 $ echo '[extensions]' >> $HGRCPATH
1364 1365 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1365 1366 $ hg help addverboseitems
1366 1367 addverboseitems extension - extension to test omit indicating.
1367 1368
1368 1369 This paragraph is never omitted (for extension)
1369 1370
1370 1371 This paragraph is never omitted, too (for extension)
1371 1372
1372 1373 (some details hidden, use --verbose to show complete help)
1373 1374
1374 1375 no commands defined
1375 1376 $ hg help -v addverboseitems
1376 1377 addverboseitems extension - extension to test omit indicating.
1377 1378
1378 1379 This paragraph is never omitted (for extension)
1379 1380
1380 1381 This paragraph is omitted, if "hg help" is invoked without "-v" (for
1381 1382 extension)
1382 1383
1383 1384 This paragraph is never omitted, too (for extension)
1384 1385
1385 1386 no commands defined
1386 1387 $ hg help topic-containing-verbose
1387 1388 This is the topic to test omit indicating.
1388 1389 """"""""""""""""""""""""""""""""""""""""""
1389 1390
1390 1391 This paragraph is never omitted (for topic).
1391 1392
1392 1393 This paragraph is never omitted, too (for topic)
1393 1394
1394 1395 (some details hidden, use --verbose to show complete help)
1395 1396 $ hg help -v topic-containing-verbose
1396 1397 This is the topic to test omit indicating.
1397 1398 """"""""""""""""""""""""""""""""""""""""""
1398 1399
1399 1400 This paragraph is never omitted (for topic).
1400 1401
1401 1402 This paragraph is omitted, if "hg help" is invoked without "-v" (for
1402 1403 topic)
1403 1404
1404 1405 This paragraph is never omitted, too (for topic)
1405 1406
1406 1407 Test section lookup
1407 1408
1408 1409 $ hg help revset.merge
1409 1410 "merge()"
1410 1411 Changeset is a merge changeset.
1411 1412
1412 1413 $ hg help glossary.dag
1413 1414 DAG
1414 1415 The repository of changesets of a distributed version control system
1415 1416 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1416 1417 of nodes and edges, where nodes correspond to changesets and edges
1417 1418 imply a parent -> child relation. This graph can be visualized by
1418 1419 graphical tools such as "hg log --graph". In Mercurial, the DAG is
1419 1420 limited by the requirement for children to have at most two parents.
1420 1421
1421 1422
1422 1423 $ hg help hgrc.paths
1423 1424 "paths"
1424 1425 -------
1425 1426
1426 1427 Assigns symbolic names and behavior to repositories.
1427 1428
1428 1429 Options are symbolic names defining the URL or directory that is the
1429 1430 location of the repository. Example:
1430 1431
1431 1432 [paths]
1432 1433 my_server = https://example.com/my_repo
1433 1434 local_path = /home/me/repo
1434 1435
1435 1436 These symbolic names can be used from the command line. To pull from
1436 1437 "my_server": "hg pull my_server". To push to "local_path": "hg push
1437 1438 local_path".
1438 1439
1439 1440 Options containing colons (":") denote sub-options that can influence
1440 1441 behavior for that specific path. Example:
1441 1442
1442 1443 [paths]
1443 1444 my_server = https://example.com/my_path
1444 1445 my_server:pushurl = ssh://example.com/my_path
1445 1446
1446 1447 The following sub-options can be defined:
1447 1448
1448 1449 "pushurl"
1449 1450 The URL to use for push operations. If not defined, the location
1450 1451 defined by the path's main entry is used.
1451 1452
1452 1453 The following special named paths exist:
1453 1454
1454 1455 "default"
1455 1456 The URL or directory to use when no source or remote is specified.
1456 1457
1457 1458 "hg clone" will automatically define this path to the location the
1458 1459 repository was cloned from.
1459 1460
1460 1461 "default-push"
1461 1462 (deprecated) The URL or directory for the default "hg push" location.
1462 1463 "default:pushurl" should be used instead.
1463 1464
1464 1465 $ hg help glossary.mcguffin
1465 1466 abort: help section not found
1466 1467 [255]
1467 1468
1468 1469 $ hg help glossary.mc.guffin
1469 1470 abort: help section not found
1470 1471 [255]
1471 1472
1472 1473 $ hg help template.files
1473 1474 files List of strings. All files modified, added, or removed by
1474 1475 this changeset.
1475 1476
1476 1477 Test dynamic list of merge tools only shows up once
1477 1478 $ hg help merge-tools
1478 1479 Merge Tools
1479 1480 """""""""""
1480 1481
1481 1482 To merge files Mercurial uses merge tools.
1482 1483
1483 1484 A merge tool combines two different versions of a file into a merged file.
1484 1485 Merge tools are given the two files and the greatest common ancestor of
1485 1486 the two file versions, so they can determine the changes made on both
1486 1487 branches.
1487 1488
1488 1489 Merge tools are used both for "hg resolve", "hg merge", "hg update", "hg
1489 1490 backout" and in several extensions.
1490 1491
1491 1492 Usually, the merge tool tries to automatically reconcile the files by
1492 1493 combining all non-overlapping changes that occurred separately in the two
1493 1494 different evolutions of the same initial base file. Furthermore, some
1494 1495 interactive merge programs make it easier to manually resolve conflicting
1495 1496 merges, either in a graphical way, or by inserting some conflict markers.
1496 1497 Mercurial does not include any interactive merge programs but relies on
1497 1498 external tools for that.
1498 1499
1499 1500 Available merge tools
1500 1501 =====================
1501 1502
1502 1503 External merge tools and their properties are configured in the merge-
1503 1504 tools configuration section - see hgrc(5) - but they can often just be
1504 1505 named by their executable.
1505 1506
1506 1507 A merge tool is generally usable if its executable can be found on the
1507 1508 system and if it can handle the merge. The executable is found if it is an
1508 1509 absolute or relative executable path or the name of an application in the
1509 1510 executable search path. The tool is assumed to be able to handle the merge
1510 1511 if it can handle symlinks if the file is a symlink, if it can handle
1511 1512 binary files if the file is binary, and if a GUI is available if the tool
1512 1513 requires a GUI.
1513 1514
1514 1515 There are some internal merge tools which can be used. The internal merge
1515 1516 tools are:
1516 1517
1517 1518 ":dump"
1518 1519 Creates three versions of the files to merge, containing the contents of
1519 1520 local, other and base. These files can then be used to perform a merge
1520 1521 manually. If the file to be merged is named "a.txt", these files will
1521 1522 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1522 1523 they will be placed in the same directory as "a.txt".
1523 1524
1524 1525 ":fail"
1525 1526 Rather than attempting to merge files that were modified on both
1526 1527 branches, it marks them as unresolved. The resolve command must be used
1527 1528 to resolve these conflicts.
1528 1529
1529 1530 ":local"
1530 1531 Uses the local version of files as the merged version.
1531 1532
1532 1533 ":merge"
1533 1534 Uses the internal non-interactive simple merge algorithm for merging
1534 1535 files. It will fail if there are any conflicts and leave markers in the
1535 1536 partially merged file. Markers will have two sections, one for each side
1536 1537 of merge.
1537 1538
1538 1539 ":merge-local"
1539 1540 Like :merge, but resolve all conflicts non-interactively in favor of the
1540 1541 local changes.
1541 1542
1542 1543 ":merge-other"
1543 1544 Like :merge, but resolve all conflicts non-interactively in favor of the
1544 1545 other changes.
1545 1546
1546 1547 ":merge3"
1547 1548 Uses the internal non-interactive simple merge algorithm for merging
1548 1549 files. It will fail if there are any conflicts and leave markers in the
1549 1550 partially merged file. Marker will have three sections, one from each
1550 1551 side of the merge and one for the base content.
1551 1552
1552 1553 ":other"
1553 1554 Uses the other version of files as the merged version.
1554 1555
1555 1556 ":prompt"
1556 1557 Asks the user which of the local or the other version to keep as the
1557 1558 merged version.
1558 1559
1559 1560 ":tagmerge"
1560 1561 Uses the internal tag merge algorithm (experimental).
1561 1562
1562 1563 ":union"
1563 1564 Uses the internal non-interactive simple merge algorithm for merging
1564 1565 files. It will use both left and right sides for conflict regions. No
1565 1566 markers are inserted.
1566 1567
1567 1568 Internal tools are always available and do not require a GUI but will by
1568 1569 default not handle symlinks or binary files.
1569 1570
1570 1571 Choosing a merge tool
1571 1572 =====================
1572 1573
1573 1574 Mercurial uses these rules when deciding which merge tool to use:
1574 1575
1575 1576 1. If a tool has been specified with the --tool option to merge or
1576 1577 resolve, it is used. If it is the name of a tool in the merge-tools
1577 1578 configuration, its configuration is used. Otherwise the specified tool
1578 1579 must be executable by the shell.
1579 1580 2. If the "HGMERGE" environment variable is present, its value is used and
1580 1581 must be executable by the shell.
1581 1582 3. If the filename of the file to be merged matches any of the patterns in
1582 1583 the merge-patterns configuration section, the first usable merge tool
1583 1584 corresponding to a matching pattern is used. Here, binary capabilities
1584 1585 of the merge tool are not considered.
1585 1586 4. If ui.merge is set it will be considered next. If the value is not the
1586 1587 name of a configured tool, the specified value is used and must be
1587 1588 executable by the shell. Otherwise the named tool is used if it is
1588 1589 usable.
1589 1590 5. If any usable merge tools are present in the merge-tools configuration
1590 1591 section, the one with the highest priority is used.
1591 1592 6. If a program named "hgmerge" can be found on the system, it is used -
1592 1593 but it will by default not be used for symlinks and binary files.
1593 1594 7. If the file to be merged is not binary and is not a symlink, then
1594 1595 internal ":merge" is used.
1595 1596 8. The merge of the file fails and must be resolved before commit.
1596 1597
1597 1598 Note:
1598 1599 After selecting a merge program, Mercurial will by default attempt to
1599 1600 merge the files using a simple merge algorithm first. Only if it
1600 1601 doesn't succeed because of conflicting changes Mercurial will actually
1601 1602 execute the merge program. Whether to use the simple merge algorithm
1602 1603 first can be controlled by the premerge setting of the merge tool.
1603 1604 Premerge is enabled by default unless the file is binary or a symlink.
1604 1605
1605 1606 See the merge-tools and ui sections of hgrc(5) for details on the
1606 1607 configuration of merge tools.
1607 1608
1608 1609 Test usage of section marks in help documents
1609 1610
1610 1611 $ cd "$TESTDIR"/../doc
1611 1612 $ python check-seclevel.py
1612 1613 $ cd $TESTTMP
1613 1614
1614 1615 #if serve
1615 1616
1616 1617 Test the help pages in hgweb.
1617 1618
1618 1619 Dish up an empty repo; serve it cold.
1619 1620
1620 1621 $ hg init "$TESTTMP/test"
1621 1622 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1622 1623 $ cat hg.pid >> $DAEMON_PIDS
1623 1624
1624 1625 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1625 1626 200 Script output follows
1626 1627
1627 1628 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1628 1629 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1629 1630 <head>
1630 1631 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1631 1632 <meta name="robots" content="index, nofollow" />
1632 1633 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1633 1634 <script type="text/javascript" src="/static/mercurial.js"></script>
1634 1635
1635 1636 <title>Help: Index</title>
1636 1637 </head>
1637 1638 <body>
1638 1639
1639 1640 <div class="container">
1640 1641 <div class="menu">
1641 1642 <div class="logo">
1642 1643 <a href="https://mercurial-scm.org/">
1643 1644 <img src="/static/hglogo.png" alt="mercurial" /></a>
1644 1645 </div>
1645 1646 <ul>
1646 1647 <li><a href="/shortlog">log</a></li>
1647 1648 <li><a href="/graph">graph</a></li>
1648 1649 <li><a href="/tags">tags</a></li>
1649 1650 <li><a href="/bookmarks">bookmarks</a></li>
1650 1651 <li><a href="/branches">branches</a></li>
1651 1652 </ul>
1652 1653 <ul>
1653 1654 <li class="active">help</li>
1654 1655 </ul>
1655 1656 </div>
1656 1657
1657 1658 <div class="main">
1658 1659 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1659 1660 <form class="search" action="/log">
1660 1661
1661 1662 <p><input name="rev" id="search1" type="text" size="30" /></p>
1662 1663 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1663 1664 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1664 1665 </form>
1665 1666 <table class="bigtable">
1666 1667 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1667 1668
1668 1669 <tr><td>
1669 1670 <a href="/help/config">
1670 1671 config
1671 1672 </a>
1672 1673 </td><td>
1673 1674 Configuration Files
1674 1675 </td></tr>
1675 1676 <tr><td>
1676 1677 <a href="/help/dates">
1677 1678 dates
1678 1679 </a>
1679 1680 </td><td>
1680 1681 Date Formats
1681 1682 </td></tr>
1682 1683 <tr><td>
1683 1684 <a href="/help/diffs">
1684 1685 diffs
1685 1686 </a>
1686 1687 </td><td>
1687 1688 Diff Formats
1688 1689 </td></tr>
1689 1690 <tr><td>
1690 1691 <a href="/help/environment">
1691 1692 environment
1692 1693 </a>
1693 1694 </td><td>
1694 1695 Environment Variables
1695 1696 </td></tr>
1696 1697 <tr><td>
1697 1698 <a href="/help/extensions">
1698 1699 extensions
1699 1700 </a>
1700 1701 </td><td>
1701 1702 Using Additional Features
1702 1703 </td></tr>
1703 1704 <tr><td>
1704 1705 <a href="/help/filesets">
1705 1706 filesets
1706 1707 </a>
1707 1708 </td><td>
1708 1709 Specifying File Sets
1709 1710 </td></tr>
1710 1711 <tr><td>
1711 1712 <a href="/help/glossary">
1712 1713 glossary
1713 1714 </a>
1714 1715 </td><td>
1715 1716 Glossary
1716 1717 </td></tr>
1717 1718 <tr><td>
1718 1719 <a href="/help/hgignore">
1719 1720 hgignore
1720 1721 </a>
1721 1722 </td><td>
1722 1723 Syntax for Mercurial Ignore Files
1723 1724 </td></tr>
1724 1725 <tr><td>
1725 1726 <a href="/help/hgweb">
1726 1727 hgweb
1727 1728 </a>
1728 1729 </td><td>
1729 1730 Configuring hgweb
1730 1731 </td></tr>
1731 1732 <tr><td>
1732 1733 <a href="/help/internals">
1733 1734 internals
1734 1735 </a>
1735 1736 </td><td>
1736 1737 Technical implementation topics
1737 1738 </td></tr>
1738 1739 <tr><td>
1739 1740 <a href="/help/merge-tools">
1740 1741 merge-tools
1741 1742 </a>
1742 1743 </td><td>
1743 1744 Merge Tools
1744 1745 </td></tr>
1745 1746 <tr><td>
1746 1747 <a href="/help/multirevs">
1747 1748 multirevs
1748 1749 </a>
1749 1750 </td><td>
1750 1751 Specifying Multiple Revisions
1751 1752 </td></tr>
1752 1753 <tr><td>
1753 1754 <a href="/help/patterns">
1754 1755 patterns
1755 1756 </a>
1756 1757 </td><td>
1757 1758 File Name Patterns
1758 1759 </td></tr>
1759 1760 <tr><td>
1760 1761 <a href="/help/phases">
1761 1762 phases
1762 1763 </a>
1763 1764 </td><td>
1764 1765 Working with Phases
1765 1766 </td></tr>
1766 1767 <tr><td>
1767 1768 <a href="/help/revisions">
1768 1769 revisions
1769 1770 </a>
1770 1771 </td><td>
1771 1772 Specifying Single Revisions
1772 1773 </td></tr>
1773 1774 <tr><td>
1774 1775 <a href="/help/revsets">
1775 1776 revsets
1776 1777 </a>
1777 1778 </td><td>
1778 1779 Specifying Revision Sets
1779 1780 </td></tr>
1780 1781 <tr><td>
1781 1782 <a href="/help/scripting">
1782 1783 scripting
1783 1784 </a>
1784 1785 </td><td>
1785 1786 Using Mercurial from scripts and automation
1786 1787 </td></tr>
1787 1788 <tr><td>
1788 1789 <a href="/help/subrepos">
1789 1790 subrepos
1790 1791 </a>
1791 1792 </td><td>
1792 1793 Subrepositories
1793 1794 </td></tr>
1794 1795 <tr><td>
1795 1796 <a href="/help/templating">
1796 1797 templating
1797 1798 </a>
1798 1799 </td><td>
1799 1800 Template Usage
1800 1801 </td></tr>
1801 1802 <tr><td>
1802 1803 <a href="/help/urls">
1803 1804 urls
1804 1805 </a>
1805 1806 </td><td>
1806 1807 URL Paths
1807 1808 </td></tr>
1808 1809 <tr><td>
1809 1810 <a href="/help/topic-containing-verbose">
1810 1811 topic-containing-verbose
1811 1812 </a>
1812 1813 </td><td>
1813 1814 This is the topic to test omit indicating.
1814 1815 </td></tr>
1815 1816
1816 1817
1817 1818 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1818 1819
1819 1820 <tr><td>
1820 1821 <a href="/help/add">
1821 1822 add
1822 1823 </a>
1823 1824 </td><td>
1824 1825 add the specified files on the next commit
1825 1826 </td></tr>
1826 1827 <tr><td>
1827 1828 <a href="/help/annotate">
1828 1829 annotate
1829 1830 </a>
1830 1831 </td><td>
1831 1832 show changeset information by line for each file
1832 1833 </td></tr>
1833 1834 <tr><td>
1834 1835 <a href="/help/clone">
1835 1836 clone
1836 1837 </a>
1837 1838 </td><td>
1838 1839 make a copy of an existing repository
1839 1840 </td></tr>
1840 1841 <tr><td>
1841 1842 <a href="/help/commit">
1842 1843 commit
1843 1844 </a>
1844 1845 </td><td>
1845 1846 commit the specified files or all outstanding changes
1846 1847 </td></tr>
1847 1848 <tr><td>
1848 1849 <a href="/help/diff">
1849 1850 diff
1850 1851 </a>
1851 1852 </td><td>
1852 1853 diff repository (or selected files)
1853 1854 </td></tr>
1854 1855 <tr><td>
1855 1856 <a href="/help/export">
1856 1857 export
1857 1858 </a>
1858 1859 </td><td>
1859 1860 dump the header and diffs for one or more changesets
1860 1861 </td></tr>
1861 1862 <tr><td>
1862 1863 <a href="/help/forget">
1863 1864 forget
1864 1865 </a>
1865 1866 </td><td>
1866 1867 forget the specified files on the next commit
1867 1868 </td></tr>
1868 1869 <tr><td>
1869 1870 <a href="/help/init">
1870 1871 init
1871 1872 </a>
1872 1873 </td><td>
1873 1874 create a new repository in the given directory
1874 1875 </td></tr>
1875 1876 <tr><td>
1876 1877 <a href="/help/log">
1877 1878 log
1878 1879 </a>
1879 1880 </td><td>
1880 1881 show revision history of entire repository or files
1881 1882 </td></tr>
1882 1883 <tr><td>
1883 1884 <a href="/help/merge">
1884 1885 merge
1885 1886 </a>
1886 1887 </td><td>
1887 1888 merge another revision into working directory
1888 1889 </td></tr>
1889 1890 <tr><td>
1890 1891 <a href="/help/pull">
1891 1892 pull
1892 1893 </a>
1893 1894 </td><td>
1894 1895 pull changes from the specified source
1895 1896 </td></tr>
1896 1897 <tr><td>
1897 1898 <a href="/help/push">
1898 1899 push
1899 1900 </a>
1900 1901 </td><td>
1901 1902 push changes to the specified destination
1902 1903 </td></tr>
1903 1904 <tr><td>
1904 1905 <a href="/help/remove">
1905 1906 remove
1906 1907 </a>
1907 1908 </td><td>
1908 1909 remove the specified files on the next commit
1909 1910 </td></tr>
1910 1911 <tr><td>
1911 1912 <a href="/help/serve">
1912 1913 serve
1913 1914 </a>
1914 1915 </td><td>
1915 1916 start stand-alone webserver
1916 1917 </td></tr>
1917 1918 <tr><td>
1918 1919 <a href="/help/status">
1919 1920 status
1920 1921 </a>
1921 1922 </td><td>
1922 1923 show changed files in the working directory
1923 1924 </td></tr>
1924 1925 <tr><td>
1925 1926 <a href="/help/summary">
1926 1927 summary
1927 1928 </a>
1928 1929 </td><td>
1929 1930 summarize working directory state
1930 1931 </td></tr>
1931 1932 <tr><td>
1932 1933 <a href="/help/update">
1933 1934 update
1934 1935 </a>
1935 1936 </td><td>
1936 1937 update working directory (or switch revisions)
1937 1938 </td></tr>
1938 1939
1939 1940
1940 1941
1941 1942 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
1942 1943
1943 1944 <tr><td>
1944 1945 <a href="/help/addremove">
1945 1946 addremove
1946 1947 </a>
1947 1948 </td><td>
1948 1949 add all new files, delete all missing files
1949 1950 </td></tr>
1950 1951 <tr><td>
1951 1952 <a href="/help/archive">
1952 1953 archive
1953 1954 </a>
1954 1955 </td><td>
1955 1956 create an unversioned archive of a repository revision
1956 1957 </td></tr>
1957 1958 <tr><td>
1958 1959 <a href="/help/backout">
1959 1960 backout
1960 1961 </a>
1961 1962 </td><td>
1962 1963 reverse effect of earlier changeset
1963 1964 </td></tr>
1964 1965 <tr><td>
1965 1966 <a href="/help/bisect">
1966 1967 bisect
1967 1968 </a>
1968 1969 </td><td>
1969 1970 subdivision search of changesets
1970 1971 </td></tr>
1971 1972 <tr><td>
1972 1973 <a href="/help/bookmarks">
1973 1974 bookmarks
1974 1975 </a>
1975 1976 </td><td>
1976 1977 create a new bookmark or list existing bookmarks
1977 1978 </td></tr>
1978 1979 <tr><td>
1979 1980 <a href="/help/branch">
1980 1981 branch
1981 1982 </a>
1982 1983 </td><td>
1983 1984 set or show the current branch name
1984 1985 </td></tr>
1985 1986 <tr><td>
1986 1987 <a href="/help/branches">
1987 1988 branches
1988 1989 </a>
1989 1990 </td><td>
1990 1991 list repository named branches
1991 1992 </td></tr>
1992 1993 <tr><td>
1993 1994 <a href="/help/bundle">
1994 1995 bundle
1995 1996 </a>
1996 1997 </td><td>
1997 1998 create a changegroup file
1998 1999 </td></tr>
1999 2000 <tr><td>
2000 2001 <a href="/help/cat">
2001 2002 cat
2002 2003 </a>
2003 2004 </td><td>
2004 2005 output the current or given revision of files
2005 2006 </td></tr>
2006 2007 <tr><td>
2007 2008 <a href="/help/config">
2008 2009 config
2009 2010 </a>
2010 2011 </td><td>
2011 2012 show combined config settings from all hgrc files
2012 2013 </td></tr>
2013 2014 <tr><td>
2014 2015 <a href="/help/copy">
2015 2016 copy
2016 2017 </a>
2017 2018 </td><td>
2018 2019 mark files as copied for the next commit
2019 2020 </td></tr>
2020 2021 <tr><td>
2021 2022 <a href="/help/files">
2022 2023 files
2023 2024 </a>
2024 2025 </td><td>
2025 2026 list tracked files
2026 2027 </td></tr>
2027 2028 <tr><td>
2028 2029 <a href="/help/graft">
2029 2030 graft
2030 2031 </a>
2031 2032 </td><td>
2032 2033 copy changes from other branches onto the current branch
2033 2034 </td></tr>
2034 2035 <tr><td>
2035 2036 <a href="/help/grep">
2036 2037 grep
2037 2038 </a>
2038 2039 </td><td>
2039 2040 search for a pattern in specified files and revisions
2040 2041 </td></tr>
2041 2042 <tr><td>
2042 2043 <a href="/help/heads">
2043 2044 heads
2044 2045 </a>
2045 2046 </td><td>
2046 2047 show branch heads
2047 2048 </td></tr>
2048 2049 <tr><td>
2049 2050 <a href="/help/help">
2050 2051 help
2051 2052 </a>
2052 2053 </td><td>
2053 2054 show help for a given topic or a help overview
2054 2055 </td></tr>
2055 2056 <tr><td>
2056 2057 <a href="/help/identify">
2057 2058 identify
2058 2059 </a>
2059 2060 </td><td>
2060 2061 identify the working directory or specified revision
2061 2062 </td></tr>
2062 2063 <tr><td>
2063 2064 <a href="/help/import">
2064 2065 import
2065 2066 </a>
2066 2067 </td><td>
2067 2068 import an ordered set of patches
2068 2069 </td></tr>
2069 2070 <tr><td>
2070 2071 <a href="/help/incoming">
2071 2072 incoming
2072 2073 </a>
2073 2074 </td><td>
2074 2075 show new changesets found in source
2075 2076 </td></tr>
2076 2077 <tr><td>
2077 2078 <a href="/help/manifest">
2078 2079 manifest
2079 2080 </a>
2080 2081 </td><td>
2081 2082 output the current or given revision of the project manifest
2082 2083 </td></tr>
2083 2084 <tr><td>
2084 2085 <a href="/help/nohelp">
2085 2086 nohelp
2086 2087 </a>
2087 2088 </td><td>
2088 2089 (no help text available)
2089 2090 </td></tr>
2090 2091 <tr><td>
2091 2092 <a href="/help/outgoing">
2092 2093 outgoing
2093 2094 </a>
2094 2095 </td><td>
2095 2096 show changesets not found in the destination
2096 2097 </td></tr>
2097 2098 <tr><td>
2098 2099 <a href="/help/paths">
2099 2100 paths
2100 2101 </a>
2101 2102 </td><td>
2102 2103 show aliases for remote repositories
2103 2104 </td></tr>
2104 2105 <tr><td>
2105 2106 <a href="/help/phase">
2106 2107 phase
2107 2108 </a>
2108 2109 </td><td>
2109 2110 set or show the current phase name
2110 2111 </td></tr>
2111 2112 <tr><td>
2112 2113 <a href="/help/recover">
2113 2114 recover
2114 2115 </a>
2115 2116 </td><td>
2116 2117 roll back an interrupted transaction
2117 2118 </td></tr>
2118 2119 <tr><td>
2119 2120 <a href="/help/rename">
2120 2121 rename
2121 2122 </a>
2122 2123 </td><td>
2123 2124 rename files; equivalent of copy + remove
2124 2125 </td></tr>
2125 2126 <tr><td>
2126 2127 <a href="/help/resolve">
2127 2128 resolve
2128 2129 </a>
2129 2130 </td><td>
2130 2131 redo merges or set/view the merge status of files
2131 2132 </td></tr>
2132 2133 <tr><td>
2133 2134 <a href="/help/revert">
2134 2135 revert
2135 2136 </a>
2136 2137 </td><td>
2137 2138 restore files to their checkout state
2138 2139 </td></tr>
2139 2140 <tr><td>
2140 2141 <a href="/help/root">
2141 2142 root
2142 2143 </a>
2143 2144 </td><td>
2144 2145 print the root (top) of the current working directory
2145 2146 </td></tr>
2146 2147 <tr><td>
2147 2148 <a href="/help/tag">
2148 2149 tag
2149 2150 </a>
2150 2151 </td><td>
2151 2152 add one or more tags for the current or given revision
2152 2153 </td></tr>
2153 2154 <tr><td>
2154 2155 <a href="/help/tags">
2155 2156 tags
2156 2157 </a>
2157 2158 </td><td>
2158 2159 list repository tags
2159 2160 </td></tr>
2160 2161 <tr><td>
2161 2162 <a href="/help/unbundle">
2162 2163 unbundle
2163 2164 </a>
2164 2165 </td><td>
2165 2166 apply one or more changegroup files
2166 2167 </td></tr>
2167 2168 <tr><td>
2168 2169 <a href="/help/verify">
2169 2170 verify
2170 2171 </a>
2171 2172 </td><td>
2172 2173 verify the integrity of the repository
2173 2174 </td></tr>
2174 2175 <tr><td>
2175 2176 <a href="/help/version">
2176 2177 version
2177 2178 </a>
2178 2179 </td><td>
2179 2180 output version and copyright information
2180 2181 </td></tr>
2181 2182
2182 2183
2183 2184 </table>
2184 2185 </div>
2185 2186 </div>
2186 2187
2187 2188 <script type="text/javascript">process_dates()</script>
2188 2189
2189 2190
2190 2191 </body>
2191 2192 </html>
2192 2193
2193 2194
2194 2195 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2195 2196 200 Script output follows
2196 2197
2197 2198 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2198 2199 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2199 2200 <head>
2200 2201 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2201 2202 <meta name="robots" content="index, nofollow" />
2202 2203 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2203 2204 <script type="text/javascript" src="/static/mercurial.js"></script>
2204 2205
2205 2206 <title>Help: add</title>
2206 2207 </head>
2207 2208 <body>
2208 2209
2209 2210 <div class="container">
2210 2211 <div class="menu">
2211 2212 <div class="logo">
2212 2213 <a href="https://mercurial-scm.org/">
2213 2214 <img src="/static/hglogo.png" alt="mercurial" /></a>
2214 2215 </div>
2215 2216 <ul>
2216 2217 <li><a href="/shortlog">log</a></li>
2217 2218 <li><a href="/graph">graph</a></li>
2218 2219 <li><a href="/tags">tags</a></li>
2219 2220 <li><a href="/bookmarks">bookmarks</a></li>
2220 2221 <li><a href="/branches">branches</a></li>
2221 2222 </ul>
2222 2223 <ul>
2223 2224 <li class="active"><a href="/help">help</a></li>
2224 2225 </ul>
2225 2226 </div>
2226 2227
2227 2228 <div class="main">
2228 2229 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2229 2230 <h3>Help: add</h3>
2230 2231
2231 2232 <form class="search" action="/log">
2232 2233
2233 2234 <p><input name="rev" id="search1" type="text" size="30" /></p>
2234 2235 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2235 2236 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2236 2237 </form>
2237 2238 <div id="doc">
2238 2239 <p>
2239 2240 hg add [OPTION]... [FILE]...
2240 2241 </p>
2241 2242 <p>
2242 2243 add the specified files on the next commit
2243 2244 </p>
2244 2245 <p>
2245 2246 Schedule files to be version controlled and added to the
2246 2247 repository.
2247 2248 </p>
2248 2249 <p>
2249 2250 The files will be added to the repository at the next commit. To
2250 2251 undo an add before that, see &quot;hg forget&quot;.
2251 2252 </p>
2252 2253 <p>
2253 2254 If no names are given, add all files to the repository (except
2254 2255 files matching &quot;.hgignore&quot;).
2255 2256 </p>
2256 2257 <p>
2257 2258 Examples:
2258 2259 </p>
2259 2260 <ul>
2260 2261 <li> New (unknown) files are added automatically by &quot;hg add&quot;:
2261 2262 <pre>
2262 2263 \$ ls (re)
2263 2264 foo.c
2264 2265 \$ hg status (re)
2265 2266 ? foo.c
2266 2267 \$ hg add (re)
2267 2268 adding foo.c
2268 2269 \$ hg status (re)
2269 2270 A foo.c
2270 2271 </pre>
2271 2272 <li> Specific files to be added can be specified:
2272 2273 <pre>
2273 2274 \$ ls (re)
2274 2275 bar.c foo.c
2275 2276 \$ hg status (re)
2276 2277 ? bar.c
2277 2278 ? foo.c
2278 2279 \$ hg add bar.c (re)
2279 2280 \$ hg status (re)
2280 2281 A bar.c
2281 2282 ? foo.c
2282 2283 </pre>
2283 2284 </ul>
2284 2285 <p>
2285 2286 Returns 0 if all files are successfully added.
2286 2287 </p>
2287 2288 <p>
2288 2289 options ([+] can be repeated):
2289 2290 </p>
2290 2291 <table>
2291 2292 <tr><td>-I</td>
2292 2293 <td>--include PATTERN [+]</td>
2293 2294 <td>include names matching the given patterns</td></tr>
2294 2295 <tr><td>-X</td>
2295 2296 <td>--exclude PATTERN [+]</td>
2296 2297 <td>exclude names matching the given patterns</td></tr>
2297 2298 <tr><td>-S</td>
2298 2299 <td>--subrepos</td>
2299 2300 <td>recurse into subrepositories</td></tr>
2300 2301 <tr><td>-n</td>
2301 2302 <td>--dry-run</td>
2302 2303 <td>do not perform actions, just print output</td></tr>
2303 2304 </table>
2304 2305 <p>
2305 2306 global options ([+] can be repeated):
2306 2307 </p>
2307 2308 <table>
2308 2309 <tr><td>-R</td>
2309 2310 <td>--repository REPO</td>
2310 2311 <td>repository root directory or name of overlay bundle file</td></tr>
2311 2312 <tr><td></td>
2312 2313 <td>--cwd DIR</td>
2313 2314 <td>change working directory</td></tr>
2314 2315 <tr><td>-y</td>
2315 2316 <td>--noninteractive</td>
2316 2317 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2317 2318 <tr><td>-q</td>
2318 2319 <td>--quiet</td>
2319 2320 <td>suppress output</td></tr>
2320 2321 <tr><td>-v</td>
2321 2322 <td>--verbose</td>
2322 2323 <td>enable additional output</td></tr>
2323 2324 <tr><td></td>
2324 2325 <td>--config CONFIG [+]</td>
2325 2326 <td>set/override config option (use 'section.name=value')</td></tr>
2326 2327 <tr><td></td>
2327 2328 <td>--debug</td>
2328 2329 <td>enable debugging output</td></tr>
2329 2330 <tr><td></td>
2330 2331 <td>--debugger</td>
2331 2332 <td>start debugger</td></tr>
2332 2333 <tr><td></td>
2333 2334 <td>--encoding ENCODE</td>
2334 2335 <td>set the charset encoding (default: ascii)</td></tr>
2335 2336 <tr><td></td>
2336 2337 <td>--encodingmode MODE</td>
2337 2338 <td>set the charset encoding mode (default: strict)</td></tr>
2338 2339 <tr><td></td>
2339 2340 <td>--traceback</td>
2340 2341 <td>always print a traceback on exception</td></tr>
2341 2342 <tr><td></td>
2342 2343 <td>--time</td>
2343 2344 <td>time how long the command takes</td></tr>
2344 2345 <tr><td></td>
2345 2346 <td>--profile</td>
2346 2347 <td>print command execution profile</td></tr>
2347 2348 <tr><td></td>
2348 2349 <td>--version</td>
2349 2350 <td>output version information and exit</td></tr>
2350 2351 <tr><td>-h</td>
2351 2352 <td>--help</td>
2352 2353 <td>display help and exit</td></tr>
2353 2354 <tr><td></td>
2354 2355 <td>--hidden</td>
2355 2356 <td>consider hidden changesets</td></tr>
2356 2357 </table>
2357 2358
2358 2359 </div>
2359 2360 </div>
2360 2361 </div>
2361 2362
2362 2363 <script type="text/javascript">process_dates()</script>
2363 2364
2364 2365
2365 2366 </body>
2366 2367 </html>
2367 2368
2368 2369
2369 2370 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2370 2371 200 Script output follows
2371 2372
2372 2373 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2373 2374 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2374 2375 <head>
2375 2376 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2376 2377 <meta name="robots" content="index, nofollow" />
2377 2378 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2378 2379 <script type="text/javascript" src="/static/mercurial.js"></script>
2379 2380
2380 2381 <title>Help: remove</title>
2381 2382 </head>
2382 2383 <body>
2383 2384
2384 2385 <div class="container">
2385 2386 <div class="menu">
2386 2387 <div class="logo">
2387 2388 <a href="https://mercurial-scm.org/">
2388 2389 <img src="/static/hglogo.png" alt="mercurial" /></a>
2389 2390 </div>
2390 2391 <ul>
2391 2392 <li><a href="/shortlog">log</a></li>
2392 2393 <li><a href="/graph">graph</a></li>
2393 2394 <li><a href="/tags">tags</a></li>
2394 2395 <li><a href="/bookmarks">bookmarks</a></li>
2395 2396 <li><a href="/branches">branches</a></li>
2396 2397 </ul>
2397 2398 <ul>
2398 2399 <li class="active"><a href="/help">help</a></li>
2399 2400 </ul>
2400 2401 </div>
2401 2402
2402 2403 <div class="main">
2403 2404 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2404 2405 <h3>Help: remove</h3>
2405 2406
2406 2407 <form class="search" action="/log">
2407 2408
2408 2409 <p><input name="rev" id="search1" type="text" size="30" /></p>
2409 2410 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2410 2411 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2411 2412 </form>
2412 2413 <div id="doc">
2413 2414 <p>
2414 2415 hg remove [OPTION]... FILE...
2415 2416 </p>
2416 2417 <p>
2417 2418 aliases: rm
2418 2419 </p>
2419 2420 <p>
2420 2421 remove the specified files on the next commit
2421 2422 </p>
2422 2423 <p>
2423 2424 Schedule the indicated files for removal from the current branch.
2424 2425 </p>
2425 2426 <p>
2426 2427 This command schedules the files to be removed at the next commit.
2427 2428 To undo a remove before that, see &quot;hg revert&quot;. To undo added
2428 2429 files, see &quot;hg forget&quot;.
2429 2430 </p>
2430 2431 <p>
2431 2432 -A/--after can be used to remove only files that have already
2432 2433 been deleted, -f/--force can be used to force deletion, and -Af
2433 2434 can be used to remove files from the next revision without
2434 2435 deleting them from the working directory.
2435 2436 </p>
2436 2437 <p>
2437 2438 The following table details the behavior of remove for different
2438 2439 file states (columns) and option combinations (rows). The file
2439 2440 states are Added [A], Clean [C], Modified [M] and Missing [!]
2440 2441 (as reported by &quot;hg status&quot;). The actions are Warn, Remove
2441 2442 (from branch) and Delete (from disk):
2442 2443 </p>
2443 2444 <table>
2444 2445 <tr><td>opt/state</td>
2445 2446 <td>A</td>
2446 2447 <td>C</td>
2447 2448 <td>M</td>
2448 2449 <td>!</td></tr>
2449 2450 <tr><td>none</td>
2450 2451 <td>W</td>
2451 2452 <td>RD</td>
2452 2453 <td>W</td>
2453 2454 <td>R</td></tr>
2454 2455 <tr><td>-f</td>
2455 2456 <td>R</td>
2456 2457 <td>RD</td>
2457 2458 <td>RD</td>
2458 2459 <td>R</td></tr>
2459 2460 <tr><td>-A</td>
2460 2461 <td>W</td>
2461 2462 <td>W</td>
2462 2463 <td>W</td>
2463 2464 <td>R</td></tr>
2464 2465 <tr><td>-Af</td>
2465 2466 <td>R</td>
2466 2467 <td>R</td>
2467 2468 <td>R</td>
2468 2469 <td>R</td></tr>
2469 2470 </table>
2470 2471 <p>
2471 2472 <b>Note:</b>
2472 2473 </p>
2473 2474 <p>
2474 2475 &quot;hg remove&quot; never deletes files in Added [A] state from the
2475 2476 working directory, not even if &quot;--force&quot; is specified.
2476 2477 </p>
2477 2478 <p>
2478 2479 Returns 0 on success, 1 if any warnings encountered.
2479 2480 </p>
2480 2481 <p>
2481 2482 options ([+] can be repeated):
2482 2483 </p>
2483 2484 <table>
2484 2485 <tr><td>-A</td>
2485 2486 <td>--after</td>
2486 2487 <td>record delete for missing files</td></tr>
2487 2488 <tr><td>-f</td>
2488 2489 <td>--force</td>
2489 2490 <td>remove (and delete) file even if added or modified</td></tr>
2490 2491 <tr><td>-S</td>
2491 2492 <td>--subrepos</td>
2492 2493 <td>recurse into subrepositories</td></tr>
2493 2494 <tr><td>-I</td>
2494 2495 <td>--include PATTERN [+]</td>
2495 2496 <td>include names matching the given patterns</td></tr>
2496 2497 <tr><td>-X</td>
2497 2498 <td>--exclude PATTERN [+]</td>
2498 2499 <td>exclude names matching the given patterns</td></tr>
2499 2500 </table>
2500 2501 <p>
2501 2502 global options ([+] can be repeated):
2502 2503 </p>
2503 2504 <table>
2504 2505 <tr><td>-R</td>
2505 2506 <td>--repository REPO</td>
2506 2507 <td>repository root directory or name of overlay bundle file</td></tr>
2507 2508 <tr><td></td>
2508 2509 <td>--cwd DIR</td>
2509 2510 <td>change working directory</td></tr>
2510 2511 <tr><td>-y</td>
2511 2512 <td>--noninteractive</td>
2512 2513 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2513 2514 <tr><td>-q</td>
2514 2515 <td>--quiet</td>
2515 2516 <td>suppress output</td></tr>
2516 2517 <tr><td>-v</td>
2517 2518 <td>--verbose</td>
2518 2519 <td>enable additional output</td></tr>
2519 2520 <tr><td></td>
2520 2521 <td>--config CONFIG [+]</td>
2521 2522 <td>set/override config option (use 'section.name=value')</td></tr>
2522 2523 <tr><td></td>
2523 2524 <td>--debug</td>
2524 2525 <td>enable debugging output</td></tr>
2525 2526 <tr><td></td>
2526 2527 <td>--debugger</td>
2527 2528 <td>start debugger</td></tr>
2528 2529 <tr><td></td>
2529 2530 <td>--encoding ENCODE</td>
2530 2531 <td>set the charset encoding (default: ascii)</td></tr>
2531 2532 <tr><td></td>
2532 2533 <td>--encodingmode MODE</td>
2533 2534 <td>set the charset encoding mode (default: strict)</td></tr>
2534 2535 <tr><td></td>
2535 2536 <td>--traceback</td>
2536 2537 <td>always print a traceback on exception</td></tr>
2537 2538 <tr><td></td>
2538 2539 <td>--time</td>
2539 2540 <td>time how long the command takes</td></tr>
2540 2541 <tr><td></td>
2541 2542 <td>--profile</td>
2542 2543 <td>print command execution profile</td></tr>
2543 2544 <tr><td></td>
2544 2545 <td>--version</td>
2545 2546 <td>output version information and exit</td></tr>
2546 2547 <tr><td>-h</td>
2547 2548 <td>--help</td>
2548 2549 <td>display help and exit</td></tr>
2549 2550 <tr><td></td>
2550 2551 <td>--hidden</td>
2551 2552 <td>consider hidden changesets</td></tr>
2552 2553 </table>
2553 2554
2554 2555 </div>
2555 2556 </div>
2556 2557 </div>
2557 2558
2558 2559 <script type="text/javascript">process_dates()</script>
2559 2560
2560 2561
2561 2562 </body>
2562 2563 </html>
2563 2564
2564 2565
2565 2566 $ get-with-headers.py 127.0.0.1:$HGPORT "help/revisions"
2566 2567 200 Script output follows
2567 2568
2568 2569 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2569 2570 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2570 2571 <head>
2571 2572 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2572 2573 <meta name="robots" content="index, nofollow" />
2573 2574 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2574 2575 <script type="text/javascript" src="/static/mercurial.js"></script>
2575 2576
2576 2577 <title>Help: revisions</title>
2577 2578 </head>
2578 2579 <body>
2579 2580
2580 2581 <div class="container">
2581 2582 <div class="menu">
2582 2583 <div class="logo">
2583 2584 <a href="https://mercurial-scm.org/">
2584 2585 <img src="/static/hglogo.png" alt="mercurial" /></a>
2585 2586 </div>
2586 2587 <ul>
2587 2588 <li><a href="/shortlog">log</a></li>
2588 2589 <li><a href="/graph">graph</a></li>
2589 2590 <li><a href="/tags">tags</a></li>
2590 2591 <li><a href="/bookmarks">bookmarks</a></li>
2591 2592 <li><a href="/branches">branches</a></li>
2592 2593 </ul>
2593 2594 <ul>
2594 2595 <li class="active"><a href="/help">help</a></li>
2595 2596 </ul>
2596 2597 </div>
2597 2598
2598 2599 <div class="main">
2599 2600 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2600 2601 <h3>Help: revisions</h3>
2601 2602
2602 2603 <form class="search" action="/log">
2603 2604
2604 2605 <p><input name="rev" id="search1" type="text" size="30" /></p>
2605 2606 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2606 2607 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2607 2608 </form>
2608 2609 <div id="doc">
2609 2610 <h1>Specifying Single Revisions</h1>
2610 2611 <p>
2611 2612 Mercurial supports several ways to specify individual revisions.
2612 2613 </p>
2613 2614 <p>
2614 2615 A plain integer is treated as a revision number. Negative integers are
2615 2616 treated as sequential offsets from the tip, with -1 denoting the tip,
2616 2617 -2 denoting the revision prior to the tip, and so forth.
2617 2618 </p>
2618 2619 <p>
2619 2620 A 40-digit hexadecimal string is treated as a unique revision
2620 2621 identifier.
2621 2622 </p>
2622 2623 <p>
2623 2624 A hexadecimal string less than 40 characters long is treated as a
2624 2625 unique revision identifier and is referred to as a short-form
2625 2626 identifier. A short-form identifier is only valid if it is the prefix
2626 2627 of exactly one full-length identifier.
2627 2628 </p>
2628 2629 <p>
2629 2630 Any other string is treated as a bookmark, tag, or branch name. A
2630 2631 bookmark is a movable pointer to a revision. A tag is a permanent name
2631 2632 associated with a revision. A branch name denotes the tipmost open branch head
2632 2633 of that branch - or if they are all closed, the tipmost closed head of the
2633 2634 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2634 2635 </p>
2635 2636 <p>
2636 2637 The reserved name &quot;tip&quot; always identifies the most recent revision.
2637 2638 </p>
2638 2639 <p>
2639 2640 The reserved name &quot;null&quot; indicates the null revision. This is the
2640 2641 revision of an empty repository, and the parent of revision 0.
2641 2642 </p>
2642 2643 <p>
2643 2644 The reserved name &quot;.&quot; indicates the working directory parent. If no
2644 2645 working directory is checked out, it is equivalent to null. If an
2645 2646 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2646 2647 parent.
2647 2648 </p>
2648 2649
2649 2650 </div>
2650 2651 </div>
2651 2652 </div>
2652 2653
2653 2654 <script type="text/javascript">process_dates()</script>
2654 2655
2655 2656
2656 2657 </body>
2657 2658 </html>
2658 2659
2659 2660
2660 2661 Sub-topic indexes rendered properly
2661 2662
2662 2663 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2663 2664 200 Script output follows
2664 2665
2665 2666 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2666 2667 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2667 2668 <head>
2668 2669 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2669 2670 <meta name="robots" content="index, nofollow" />
2670 2671 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2671 2672 <script type="text/javascript" src="/static/mercurial.js"></script>
2672 2673
2673 2674 <title>Help: internals</title>
2674 2675 </head>
2675 2676 <body>
2676 2677
2677 2678 <div class="container">
2678 2679 <div class="menu">
2679 2680 <div class="logo">
2680 2681 <a href="https://mercurial-scm.org/">
2681 2682 <img src="/static/hglogo.png" alt="mercurial" /></a>
2682 2683 </div>
2683 2684 <ul>
2684 2685 <li><a href="/shortlog">log</a></li>
2685 2686 <li><a href="/graph">graph</a></li>
2686 2687 <li><a href="/tags">tags</a></li>
2687 2688 <li><a href="/bookmarks">bookmarks</a></li>
2688 2689 <li><a href="/branches">branches</a></li>
2689 2690 </ul>
2690 2691 <ul>
2691 2692 <li><a href="/help">help</a></li>
2692 2693 </ul>
2693 2694 </div>
2694 2695
2695 2696 <div class="main">
2696 2697 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2697 2698 <form class="search" action="/log">
2698 2699
2699 2700 <p><input name="rev" id="search1" type="text" size="30" /></p>
2700 2701 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2701 2702 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2702 2703 </form>
2703 2704 <table class="bigtable">
2704 2705 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
2705 2706
2706 2707 <tr><td>
2707 2708 <a href="/help/internals.bundles">
2708 2709 bundles
2709 2710 </a>
2710 2711 </td><td>
2711 2712 container for exchange of repository data
2712 2713 </td></tr>
2713 2714 <tr><td>
2714 2715 <a href="/help/internals.changegroups">
2715 2716 changegroups
2716 2717 </a>
2717 2718 </td><td>
2718 2719 representation of revlog data
2719 2720 </td></tr>
2720 2721 <tr><td>
2721 2722 <a href="/help/internals.revlogs">
2722 2723 revlogs
2723 2724 </a>
2724 2725 </td><td>
2725 2726 revision storage mechanism
2726 2727 </td></tr>
2727 2728
2728 2729
2729 2730
2730 2731
2731 2732
2732 2733 </table>
2733 2734 </div>
2734 2735 </div>
2735 2736
2736 2737 <script type="text/javascript">process_dates()</script>
2737 2738
2738 2739
2739 2740 </body>
2740 2741 </html>
2741 2742
2742 2743
2743 2744 Sub-topic topics rendered properly
2744 2745
2745 2746 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2746 2747 200 Script output follows
2747 2748
2748 2749 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2749 2750 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2750 2751 <head>
2751 2752 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2752 2753 <meta name="robots" content="index, nofollow" />
2753 2754 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2754 2755 <script type="text/javascript" src="/static/mercurial.js"></script>
2755 2756
2756 2757 <title>Help: internals.changegroups</title>
2757 2758 </head>
2758 2759 <body>
2759 2760
2760 2761 <div class="container">
2761 2762 <div class="menu">
2762 2763 <div class="logo">
2763 2764 <a href="https://mercurial-scm.org/">
2764 2765 <img src="/static/hglogo.png" alt="mercurial" /></a>
2765 2766 </div>
2766 2767 <ul>
2767 2768 <li><a href="/shortlog">log</a></li>
2768 2769 <li><a href="/graph">graph</a></li>
2769 2770 <li><a href="/tags">tags</a></li>
2770 2771 <li><a href="/bookmarks">bookmarks</a></li>
2771 2772 <li><a href="/branches">branches</a></li>
2772 2773 </ul>
2773 2774 <ul>
2774 2775 <li class="active"><a href="/help">help</a></li>
2775 2776 </ul>
2776 2777 </div>
2777 2778
2778 2779 <div class="main">
2779 2780 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2780 2781 <h3>Help: internals.changegroups</h3>
2781 2782
2782 2783 <form class="search" action="/log">
2783 2784
2784 2785 <p><input name="rev" id="search1" type="text" size="30" /></p>
2785 2786 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2786 2787 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2787 2788 </form>
2788 2789 <div id="doc">
2789 2790 <h1>representation of revlog data</h1>
2790 2791 <h2>Changegroups</h2>
2791 2792 <p>
2792 2793 Changegroups are representations of repository revlog data, specifically
2793 2794 the changelog, manifest, and filelogs.
2794 2795 </p>
2795 2796 <p>
2796 2797 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2797 2798 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2798 2799 the only difference being a header on entries in the changeset
2799 2800 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2800 2801 includes revlog flags in the delta header.
2801 2802 </p>
2802 2803 <p>
2803 2804 Changegroups consists of 3 logical segments:
2804 2805 </p>
2805 2806 <pre>
2806 2807 +---------------------------------+
2807 2808 | | | |
2808 2809 | changeset | manifest | filelogs |
2809 2810 | | | |
2810 2811 +---------------------------------+
2811 2812 </pre>
2812 2813 <p>
2813 2814 The principle building block of each segment is a *chunk*. A *chunk*
2814 2815 is a framed piece of data:
2815 2816 </p>
2816 2817 <pre>
2817 2818 +---------------------------------------+
2818 2819 | | |
2819 2820 | length | data |
2820 2821 | (32 bits) | &lt;length&gt; bytes |
2821 2822 | | |
2822 2823 +---------------------------------------+
2823 2824 </pre>
2824 2825 <p>
2825 2826 Each chunk starts with a 32-bit big-endian signed integer indicating
2826 2827 the length of the raw data that follows.
2827 2828 </p>
2828 2829 <p>
2829 2830 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
2830 2831 call this an *empty chunk*.
2831 2832 </p>
2832 2833 <h3>Delta Groups</h3>
2833 2834 <p>
2834 2835 A *delta group* expresses the content of a revlog as a series of deltas,
2835 2836 or patches against previous revisions.
2836 2837 </p>
2837 2838 <p>
2838 2839 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
2839 2840 to signal the end of the delta group:
2840 2841 </p>
2841 2842 <pre>
2842 2843 +------------------------------------------------------------------------+
2843 2844 | | | | | |
2844 2845 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
2845 2846 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
2846 2847 | | | | | |
2847 2848 +------------------------------------------------------------+-----------+
2848 2849 </pre>
2849 2850 <p>
2850 2851 Each *chunk*'s data consists of the following:
2851 2852 </p>
2852 2853 <pre>
2853 2854 +-----------------------------------------+
2854 2855 | | | |
2855 2856 | delta header | mdiff header | delta |
2856 2857 | (various) | (12 bytes) | (various) |
2857 2858 | | | |
2858 2859 +-----------------------------------------+
2859 2860 </pre>
2860 2861 <p>
2861 2862 The *length* field is the byte length of the remaining 3 logical pieces
2862 2863 of data. The *delta* is a diff from an existing entry in the changelog.
2863 2864 </p>
2864 2865 <p>
2865 2866 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
2866 2867 &quot;3&quot; of the changegroup format.
2867 2868 </p>
2868 2869 <p>
2869 2870 Version 1:
2870 2871 </p>
2871 2872 <pre>
2872 2873 +------------------------------------------------------+
2873 2874 | | | | |
2874 2875 | node | p1 node | p2 node | link node |
2875 2876 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
2876 2877 | | | | |
2877 2878 +------------------------------------------------------+
2878 2879 </pre>
2879 2880 <p>
2880 2881 Version 2:
2881 2882 </p>
2882 2883 <pre>
2883 2884 +------------------------------------------------------------------+
2884 2885 | | | | | |
2885 2886 | node | p1 node | p2 node | base node | link node |
2886 2887 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
2887 2888 | | | | | |
2888 2889 +------------------------------------------------------------------+
2889 2890 </pre>
2890 2891 <p>
2891 2892 Version 3:
2892 2893 </p>
2893 2894 <pre>
2894 2895 +------------------------------------------------------------------------------+
2895 2896 | | | | | | |
2896 2897 | node | p1 node | p2 node | base node | link node | flags |
2897 2898 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
2898 2899 | | | | | | |
2899 2900 +------------------------------------------------------------------------------+
2900 2901 </pre>
2901 2902 <p>
2902 2903 The *mdiff header* consists of 3 32-bit big-endian signed integers
2903 2904 describing offsets at which to apply the following delta content:
2904 2905 </p>
2905 2906 <pre>
2906 2907 +-------------------------------------+
2907 2908 | | | |
2908 2909 | offset | old length | new length |
2909 2910 | (32 bits) | (32 bits) | (32 bits) |
2910 2911 | | | |
2911 2912 +-------------------------------------+
2912 2913 </pre>
2913 2914 <p>
2914 2915 In version 1, the delta is always applied against the previous node from
2915 2916 the changegroup or the first parent if this is the first entry in the
2916 2917 changegroup.
2917 2918 </p>
2918 2919 <p>
2919 2920 In version 2, the delta base node is encoded in the entry in the
2920 2921 changegroup. This allows the delta to be expressed against any parent,
2921 2922 which can result in smaller deltas and more efficient encoding of data.
2922 2923 </p>
2923 2924 <h3>Changeset Segment</h3>
2924 2925 <p>
2925 2926 The *changeset segment* consists of a single *delta group* holding
2926 2927 changelog data. It is followed by an *empty chunk* to denote the
2927 2928 boundary to the *manifests segment*.
2928 2929 </p>
2929 2930 <h3>Manifest Segment</h3>
2930 2931 <p>
2931 2932 The *manifest segment* consists of a single *delta group* holding
2932 2933 manifest data. It is followed by an *empty chunk* to denote the boundary
2933 2934 to the *filelogs segment*.
2934 2935 </p>
2935 2936 <h3>Filelogs Segment</h3>
2936 2937 <p>
2937 2938 The *filelogs* segment consists of multiple sub-segments, each
2938 2939 corresponding to an individual file whose data is being described:
2939 2940 </p>
2940 2941 <pre>
2941 2942 +--------------------------------------+
2942 2943 | | | | |
2943 2944 | filelog0 | filelog1 | filelog2 | ... |
2944 2945 | | | | |
2945 2946 +--------------------------------------+
2946 2947 </pre>
2947 2948 <p>
2948 2949 In version &quot;3&quot; of the changegroup format, filelogs may include
2949 2950 directory logs when treemanifests are in use. directory logs are
2950 2951 identified by having a trailing '/' on their filename (see below).
2951 2952 </p>
2952 2953 <p>
2953 2954 The final filelog sub-segment is followed by an *empty chunk* to denote
2954 2955 the end of the segment and the overall changegroup.
2955 2956 </p>
2956 2957 <p>
2957 2958 Each filelog sub-segment consists of the following:
2958 2959 </p>
2959 2960 <pre>
2960 2961 +------------------------------------------+
2961 2962 | | | |
2962 2963 | filename size | filename | delta group |
2963 2964 | (32 bits) | (various) | (various) |
2964 2965 | | | |
2965 2966 +------------------------------------------+
2966 2967 </pre>
2967 2968 <p>
2968 2969 That is, a *chunk* consisting of the filename (not terminated or padded)
2969 2970 followed by N chunks constituting the *delta group* for this file.
2970 2971 </p>
2971 2972
2972 2973 </div>
2973 2974 </div>
2974 2975 </div>
2975 2976
2976 2977 <script type="text/javascript">process_dates()</script>
2977 2978
2978 2979
2979 2980 </body>
2980 2981 </html>
2981 2982
2982 2983
2983 2984 $ killdaemons.py
2984 2985
2985 2986 #endif
@@ -1,276 +1,285 b''
1 1 $ hg init ignorerepo
2 2 $ cd ignorerepo
3 3
4 4 Issue562: .hgignore requires newline at end:
5 5
6 6 $ touch foo
7 7 $ touch bar
8 8 $ touch baz
9 9 $ cat > makeignore.py <<EOF
10 10 > f = open(".hgignore", "w")
11 11 > f.write("ignore\n")
12 12 > f.write("foo\n")
13 13 > # No EOL here
14 14 > f.write("bar")
15 15 > f.close()
16 16 > EOF
17 17
18 18 $ python makeignore.py
19 19
20 20 Should display baz only:
21 21
22 22 $ hg status
23 23 ? baz
24 24
25 25 $ rm foo bar baz .hgignore makeignore.py
26 26
27 27 $ touch a.o
28 28 $ touch a.c
29 29 $ touch syntax
30 30 $ mkdir dir
31 31 $ touch dir/a.o
32 32 $ touch dir/b.o
33 33 $ touch dir/c.o
34 34
35 35 $ hg add dir/a.o
36 36 $ hg commit -m 0
37 37 $ hg add dir/b.o
38 38
39 39 $ hg status
40 40 A dir/b.o
41 41 ? a.c
42 42 ? a.o
43 43 ? dir/c.o
44 44 ? syntax
45 45
46 46 $ echo "*.o" > .hgignore
47 47 $ hg status
48 48 abort: $TESTTMP/ignorerepo/.hgignore: invalid pattern (relre): *.o (glob)
49 49 [255]
50 50
51 51 $ echo ".*\.o" > .hgignore
52 52 $ hg status
53 53 A dir/b.o
54 54 ? .hgignore
55 55 ? a.c
56 56 ? syntax
57 57
58 58 Ensure that comments work:
59 59
60 60 $ touch 'foo#bar' 'quux#'
61 61 #if no-windows
62 62 $ touch 'baz\#wat'
63 63 #endif
64 64 $ cat <<'EOF' >> .hgignore
65 65 > # full-line comment
66 66 > # whitespace-only comment line
67 67 > syntax# pattern, no whitespace, then comment
68 68 > a.c # pattern, then whitespace, then comment
69 69 > baz\\# # escaped comment character
70 70 > foo\#b # escaped comment character
71 71 > quux\## escaped comment character at end of name
72 72 > EOF
73 73 $ hg status
74 74 A dir/b.o
75 75 ? .hgignore
76 76 $ rm 'foo#bar' 'quux#'
77 77 #if no-windows
78 78 $ rm 'baz\#wat'
79 79 #endif
80 80
81 81 Check it does not ignore the current directory '.':
82 82
83 83 $ echo "^\." > .hgignore
84 84 $ hg status
85 85 A dir/b.o
86 86 ? a.c
87 87 ? a.o
88 88 ? dir/c.o
89 89 ? syntax
90 90
91 91 Test that patterns from ui.ignore options are read:
92 92
93 93 $ echo > .hgignore
94 94 $ cat >> $HGRCPATH << EOF
95 95 > [ui]
96 96 > ignore.other = $TESTTMP/ignorerepo/.hg/testhgignore
97 97 > EOF
98 98 $ echo "glob:**.o" > .hg/testhgignore
99 99 $ hg status
100 100 A dir/b.o
101 101 ? .hgignore
102 102 ? a.c
103 103 ? syntax
104 104
105 105 empty out testhgignore
106 106 $ echo > .hg/testhgignore
107 107
108 108 Test relative ignore path (issue4473):
109 109
110 110 $ cat >> $HGRCPATH << EOF
111 111 > [ui]
112 112 > ignore.relative = .hg/testhgignorerel
113 113 > EOF
114 114 $ echo "glob:*.o" > .hg/testhgignorerel
115 115 $ cd dir
116 116 $ hg status
117 117 A dir/b.o
118 118 ? .hgignore
119 119 ? a.c
120 120 ? syntax
121 121
122 122 $ cd ..
123 123 $ echo > .hg/testhgignorerel
124 124 $ echo "syntax: glob" > .hgignore
125 125 $ echo "re:.*\.o" >> .hgignore
126 126 $ hg status
127 127 A dir/b.o
128 128 ? .hgignore
129 129 ? a.c
130 130 ? syntax
131 131
132 132 $ echo "syntax: invalid" > .hgignore
133 133 $ hg status
134 134 $TESTTMP/ignorerepo/.hgignore: ignoring invalid syntax 'invalid' (glob)
135 135 A dir/b.o
136 136 ? .hgignore
137 137 ? a.c
138 138 ? a.o
139 139 ? dir/c.o
140 140 ? syntax
141 141
142 142 $ echo "syntax: glob" > .hgignore
143 143 $ echo "*.o" >> .hgignore
144 144 $ hg status
145 145 A dir/b.o
146 146 ? .hgignore
147 147 ? a.c
148 148 ? syntax
149 149
150 150 $ echo "relglob:syntax*" > .hgignore
151 151 $ hg status
152 152 A dir/b.o
153 153 ? .hgignore
154 154 ? a.c
155 155 ? a.o
156 156 ? dir/c.o
157 157
158 158 $ echo "relglob:*" > .hgignore
159 159 $ hg status
160 160 A dir/b.o
161 161
162 162 $ cd dir
163 163 $ hg status .
164 164 A b.o
165 165
166 166 $ hg debugignore
167 167 (?:(?:|.*/)[^/]*(?:/|$))
168 168
169 $ hg debugignore b.o
170 b.o is ignored
171
169 172 $ cd ..
170 173
171 174 Check patterns that match only the directory
172 175
173 176 $ echo "^dir\$" > .hgignore
174 177 $ hg status
175 178 A dir/b.o
176 179 ? .hgignore
177 180 ? a.c
178 181 ? a.o
179 182 ? syntax
180 183
181 184 Check recursive glob pattern matches no directories (dir/**/c.o matches dir/c.o)
182 185
183 186 $ echo "syntax: glob" > .hgignore
184 187 $ echo "dir/**/c.o" >> .hgignore
185 188 $ touch dir/c.o
186 189 $ mkdir dir/subdir
187 190 $ touch dir/subdir/c.o
188 191 $ hg status
189 192 A dir/b.o
190 193 ? .hgignore
191 194 ? a.c
192 195 ? a.o
193 196 ? syntax
197 $ hg debugignore a.c
198 a.c is not ignored
199 $ hg debugignore dir/c.o
200 dir/c.o is ignored
194 201
195 202 Check using 'include:' in ignore file
196 203
197 204 $ hg purge --all --config extensions.purge=
198 205 $ touch foo.included
199 206
200 207 $ echo ".*.included" > otherignore
201 208 $ hg status -I "include:otherignore"
202 209 ? foo.included
203 210
204 211 $ echo "include:otherignore" >> .hgignore
205 212 $ hg status
206 213 A dir/b.o
207 214 ? .hgignore
208 215 ? otherignore
209 216
210 217 Check recursive uses of 'include:'
211 218
212 219 $ echo "include:nested/ignore" >> otherignore
213 220 $ mkdir nested
214 221 $ echo "glob:*ignore" > nested/ignore
215 222 $ hg status
216 223 A dir/b.o
217 224
218 225 $ cp otherignore goodignore
219 226 $ echo "include:badignore" >> otherignore
220 227 $ hg status
221 228 skipping unreadable pattern file 'badignore': No such file or directory
222 229 A dir/b.o
223 230
224 231 $ mv goodignore otherignore
225 232
226 233 Check using 'include:' while in a non-root directory
227 234
228 235 $ cd ..
229 236 $ hg -R ignorerepo status
230 237 A dir/b.o
231 238 $ cd ignorerepo
232 239
233 240 Check including subincludes
234 241
235 242 $ hg revert -q --all
236 243 $ hg purge --all --config extensions.purge=
237 244 $ echo ".hgignore" > .hgignore
238 245 $ mkdir dir1 dir2
239 246 $ touch dir1/file1 dir1/file2 dir2/file1 dir2/file2
240 247 $ echo "subinclude:dir2/.hgignore" >> .hgignore
241 248 $ echo "glob:file*2" > dir2/.hgignore
242 249 $ hg status
243 250 ? dir1/file1
244 251 ? dir1/file2
245 252 ? dir2/file1
246 253
247 254 Check including subincludes with regexs
248 255
249 256 $ echo "subinclude:dir1/.hgignore" >> .hgignore
250 257 $ echo "regexp:f.le1" > dir1/.hgignore
251 258
252 259 $ hg status
253 260 ? dir1/file2
254 261 ? dir2/file1
255 262
256 263 Check multiple levels of sub-ignores
257 264
258 265 $ mkdir dir1/subdir
259 266 $ touch dir1/subdir/subfile1 dir1/subdir/subfile3 dir1/subdir/subfile4
260 267 $ echo "subinclude:subdir/.hgignore" >> dir1/.hgignore
261 268 $ echo "glob:subfil*3" >> dir1/subdir/.hgignore
262 269
263 270 $ hg status
264 271 ? dir1/file2
265 272 ? dir1/subdir/subfile4
266 273 ? dir2/file1
267 274
268 275 Check include subignore at the same level
269 276
270 277 $ mv dir1/subdir/.hgignore dir1/.hgignoretwo
271 278 $ echo "regexp:f.le1" > dir1/.hgignore
272 279 $ echo "subinclude:.hgignoretwo" >> dir1/.hgignore
273 280 $ echo "glob:file*2" > dir1/.hgignoretwo
274 281
275 282 $ hg status | grep file2
276 283 [1]
284 $ hg debugignore dir1/file2
285 dir1/file2 is ignored
General Comments 0
You need to be logged in to leave comments. Login now