##// END OF EJS Templates
help: basic support for showing only specified topic sections...
Matt Mackall -
r22587:c3c3dd31 default
parent child Browse files
Show More
@@ -1,6315 +1,6324 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, 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, commandserver
17 17 import extensions
18 18 from hgweb import server as hgweb_server
19 19 import merge as mergemod
20 20 import minirst, revset, fileset
21 21 import dagparser, context, simplemerge, graphmod
22 22 import random
23 23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 24 import phases, obsolete, exchange
25 25
26 26 table = {}
27 27
28 28 command = cmdutil.command(table)
29 29
30 30 # Space delimited list of commands that don't require local repositories.
31 31 # This should be populated by passing norepo=True into the @command decorator.
32 32 norepo = ''
33 33 # Space delimited list of commands that optionally require local repositories.
34 34 # This should be populated by passing optionalrepo=True into the @command
35 35 # decorator.
36 36 optionalrepo = ''
37 37 # Space delimited list of commands that will examine arguments looking for
38 38 # a repository. This should be populated by passing inferrepo=True into the
39 39 # @command decorator.
40 40 inferrepo = ''
41 41
42 42 # common command options
43 43
44 44 globalopts = [
45 45 ('R', 'repository', '',
46 46 _('repository root directory or name of overlay bundle file'),
47 47 _('REPO')),
48 48 ('', 'cwd', '',
49 49 _('change working directory'), _('DIR')),
50 50 ('y', 'noninteractive', None,
51 51 _('do not prompt, automatically pick the first choice for all prompts')),
52 52 ('q', 'quiet', None, _('suppress output')),
53 53 ('v', 'verbose', None, _('enable additional output')),
54 54 ('', 'config', [],
55 55 _('set/override config option (use \'section.name=value\')'),
56 56 _('CONFIG')),
57 57 ('', 'debug', None, _('enable debugging output')),
58 58 ('', 'debugger', None, _('start debugger')),
59 59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 60 _('ENCODE')),
61 61 ('', 'encodingmode', encoding.encodingmode,
62 62 _('set the charset encoding mode'), _('MODE')),
63 63 ('', 'traceback', None, _('always print a traceback on exception')),
64 64 ('', 'time', None, _('time how long the command takes')),
65 65 ('', 'profile', None, _('print command execution profile')),
66 66 ('', 'version', None, _('output version information and exit')),
67 67 ('h', 'help', None, _('display help and exit')),
68 68 ('', 'hidden', False, _('consider hidden changesets')),
69 69 ]
70 70
71 71 dryrunopts = [('n', 'dry-run', None,
72 72 _('do not perform actions, just print output'))]
73 73
74 74 remoteopts = [
75 75 ('e', 'ssh', '',
76 76 _('specify ssh command to use'), _('CMD')),
77 77 ('', 'remotecmd', '',
78 78 _('specify hg command to run on the remote side'), _('CMD')),
79 79 ('', 'insecure', None,
80 80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 81 ]
82 82
83 83 walkopts = [
84 84 ('I', 'include', [],
85 85 _('include names matching the given patterns'), _('PATTERN')),
86 86 ('X', 'exclude', [],
87 87 _('exclude names matching the given patterns'), _('PATTERN')),
88 88 ]
89 89
90 90 commitopts = [
91 91 ('m', 'message', '',
92 92 _('use text as commit message'), _('TEXT')),
93 93 ('l', 'logfile', '',
94 94 _('read commit message from file'), _('FILE')),
95 95 ]
96 96
97 97 commitopts2 = [
98 98 ('d', 'date', '',
99 99 _('record the specified date as commit date'), _('DATE')),
100 100 ('u', 'user', '',
101 101 _('record the specified user as committer'), _('USER')),
102 102 ]
103 103
104 104 # hidden for now
105 105 formatteropts = [
106 106 ('T', 'template', '',
107 107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 108 ]
109 109
110 110 templateopts = [
111 111 ('', 'style', '',
112 112 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 113 ('T', 'template', '',
114 114 _('display with template'), _('TEMPLATE')),
115 115 ]
116 116
117 117 logopts = [
118 118 ('p', 'patch', None, _('show patch')),
119 119 ('g', 'git', None, _('use git extended diff format')),
120 120 ('l', 'limit', '',
121 121 _('limit number of changes displayed'), _('NUM')),
122 122 ('M', 'no-merges', None, _('do not show merges')),
123 123 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 124 ('G', 'graph', None, _("show the revision DAG")),
125 125 ] + templateopts
126 126
127 127 diffopts = [
128 128 ('a', 'text', None, _('treat all files as text')),
129 129 ('g', 'git', None, _('use git extended diff format')),
130 130 ('', 'nodates', None, _('omit dates from diff headers'))
131 131 ]
132 132
133 133 diffwsopts = [
134 134 ('w', 'ignore-all-space', None,
135 135 _('ignore white space when comparing lines')),
136 136 ('b', 'ignore-space-change', None,
137 137 _('ignore changes in the amount of white space')),
138 138 ('B', 'ignore-blank-lines', None,
139 139 _('ignore changes whose lines are all blank')),
140 140 ]
141 141
142 142 diffopts2 = [
143 143 ('p', 'show-function', None, _('show which function each change is in')),
144 144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 145 ] + diffwsopts + [
146 146 ('U', 'unified', '',
147 147 _('number of lines of context to show'), _('NUM')),
148 148 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 149 ]
150 150
151 151 mergetoolopts = [
152 152 ('t', 'tool', '', _('specify merge tool')),
153 153 ]
154 154
155 155 similarityopts = [
156 156 ('s', 'similarity', '',
157 157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
158 158 ]
159 159
160 160 subrepoopts = [
161 161 ('S', 'subrepos', None,
162 162 _('recurse into subrepositories'))
163 163 ]
164 164
165 165 # Commands start here, listed alphabetically
166 166
167 167 @command('^add',
168 168 walkopts + subrepoopts + dryrunopts,
169 169 _('[OPTION]... [FILE]...'),
170 170 inferrepo=True)
171 171 def add(ui, repo, *pats, **opts):
172 172 """add the specified files on the next commit
173 173
174 174 Schedule files to be version controlled and added to the
175 175 repository.
176 176
177 177 The files will be added to the repository at the next commit. To
178 178 undo an add before that, see :hg:`forget`.
179 179
180 180 If no names are given, add all files to the repository.
181 181
182 182 .. container:: verbose
183 183
184 184 An example showing how new (unknown) files are added
185 185 automatically by :hg:`add`::
186 186
187 187 $ ls
188 188 foo.c
189 189 $ hg status
190 190 ? foo.c
191 191 $ hg add
192 192 adding foo.c
193 193 $ hg status
194 194 A foo.c
195 195
196 196 Returns 0 if all files are successfully added.
197 197 """
198 198
199 199 m = scmutil.match(repo[None], pats, opts)
200 200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
201 201 opts.get('subrepos'), prefix="", explicitonly=False)
202 202 return rejected and 1 or 0
203 203
204 204 @command('addremove',
205 205 similarityopts + walkopts + dryrunopts,
206 206 _('[OPTION]... [FILE]...'),
207 207 inferrepo=True)
208 208 def addremove(ui, repo, *pats, **opts):
209 209 """add all new files, delete all missing files
210 210
211 211 Add all new files and remove all missing files from the
212 212 repository.
213 213
214 214 New files are ignored if they match any of the patterns in
215 215 ``.hgignore``. As with add, these changes take effect at the next
216 216 commit.
217 217
218 218 Use the -s/--similarity option to detect renamed files. This
219 219 option takes a percentage between 0 (disabled) and 100 (files must
220 220 be identical) as its parameter. With a parameter greater than 0,
221 221 this compares every removed file with every added file and records
222 222 those similar enough as renames. Detecting renamed files this way
223 223 can be expensive. After using this option, :hg:`status -C` can be
224 224 used to check which files were identified as moved or renamed. If
225 225 not specified, -s/--similarity defaults to 100 and only renames of
226 226 identical files are detected.
227 227
228 228 Returns 0 if all files are successfully added.
229 229 """
230 230 try:
231 231 sim = float(opts.get('similarity') or 100)
232 232 except ValueError:
233 233 raise util.Abort(_('similarity must be a number'))
234 234 if sim < 0 or sim > 100:
235 235 raise util.Abort(_('similarity must be between 0 and 100'))
236 236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
237 237
238 238 @command('^annotate|blame',
239 239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
240 240 ('', 'follow', None,
241 241 _('follow copies/renames and list the filename (DEPRECATED)')),
242 242 ('', 'no-follow', None, _("don't follow copies and renames")),
243 243 ('a', 'text', None, _('treat all files as text')),
244 244 ('u', 'user', None, _('list the author (long with -v)')),
245 245 ('f', 'file', None, _('list the filename')),
246 246 ('d', 'date', None, _('list the date (short with -q)')),
247 247 ('n', 'number', None, _('list the revision number (default)')),
248 248 ('c', 'changeset', None, _('list the changeset')),
249 249 ('l', 'line-number', None, _('show line number at the first appearance'))
250 250 ] + diffwsopts + walkopts + formatteropts,
251 251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
252 252 inferrepo=True)
253 253 def annotate(ui, repo, *pats, **opts):
254 254 """show changeset information by line for each file
255 255
256 256 List changes in files, showing the revision id responsible for
257 257 each line
258 258
259 259 This command is useful for discovering when a change was made and
260 260 by whom.
261 261
262 262 Without the -a/--text option, annotate will avoid processing files
263 263 it detects as binary. With -a, annotate will annotate the file
264 264 anyway, although the results will probably be neither useful
265 265 nor desirable.
266 266
267 267 Returns 0 on success.
268 268 """
269 269 if not pats:
270 270 raise util.Abort(_('at least one filename or pattern is required'))
271 271
272 272 if opts.get('follow'):
273 273 # --follow is deprecated and now just an alias for -f/--file
274 274 # to mimic the behavior of Mercurial before version 1.5
275 275 opts['file'] = True
276 276
277 277 fm = ui.formatter('annotate', opts)
278 278 datefunc = ui.quiet and util.shortdate or util.datestr
279 279 if fm or ui.debugflag:
280 280 hexfn = hex
281 281 else:
282 282 hexfn = short
283 283
284 284 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
285 285 ('number', ' ', lambda x: x[0].rev(), str),
286 286 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
287 287 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
288 288 ('file', ' ', lambda x: x[0].path(), str),
289 289 ('line_number', ':', lambda x: x[1], str),
290 290 ]
291 291 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
292 292
293 293 if (not opts.get('user') and not opts.get('changeset')
294 294 and not opts.get('date') and not opts.get('file')):
295 295 opts['number'] = True
296 296
297 297 linenumber = opts.get('line_number') is not None
298 298 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
299 299 raise util.Abort(_('at least one of -n/-c is required for -l'))
300 300
301 301 if fm:
302 302 def makefunc(get, fmt):
303 303 return get
304 304 else:
305 305 def makefunc(get, fmt):
306 306 return lambda x: fmt(get(x))
307 307 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
308 308 if opts.get(op)]
309 309 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
310 310 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
311 311 if opts.get(op))
312 312
313 313 def bad(x, y):
314 314 raise util.Abort("%s: %s" % (x, y))
315 315
316 316 ctx = scmutil.revsingle(repo, opts.get('rev'))
317 317 m = scmutil.match(ctx, pats, opts)
318 318 m.bad = bad
319 319 follow = not opts.get('no_follow')
320 320 diffopts = patch.diffopts(ui, opts, section='annotate')
321 321 for abs in ctx.walk(m):
322 322 fctx = ctx[abs]
323 323 if not opts.get('text') and util.binary(fctx.data()):
324 324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 325 continue
326 326
327 327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 328 diffopts=diffopts)
329 329 formats = []
330 330 pieces = []
331 331
332 332 for f, sep in funcmap:
333 333 l = [f(n) for n, dummy in lines]
334 334 if l:
335 335 if fm:
336 336 formats.append(['%s' for x in l])
337 337 else:
338 338 sizes = [encoding.colwidth(x) for x in l]
339 339 ml = max(sizes)
340 340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 341 pieces.append(l)
342 342
343 343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 344 fm.startitem()
345 345 fm.write(fields, "".join(f), *p)
346 346 fm.write('line', ": %s", l[1])
347 347
348 348 if lines and not lines[-1][1].endswith('\n'):
349 349 fm.plain('\n')
350 350
351 351 fm.end()
352 352
353 353 @command('archive',
354 354 [('', 'no-decode', None, _('do not pass files through decoders')),
355 355 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 356 _('PREFIX')),
357 357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 359 ] + subrepoopts + walkopts,
360 360 _('[OPTION]... DEST'))
361 361 def archive(ui, repo, dest, **opts):
362 362 '''create an unversioned archive of a repository revision
363 363
364 364 By default, the revision used is the parent of the working
365 365 directory; use -r/--rev to specify a different revision.
366 366
367 367 The archive type is automatically detected based on file
368 368 extension (or override using -t/--type).
369 369
370 370 .. container:: verbose
371 371
372 372 Examples:
373 373
374 374 - create a zip file containing the 1.0 release::
375 375
376 376 hg archive -r 1.0 project-1.0.zip
377 377
378 378 - create a tarball excluding .hg files::
379 379
380 380 hg archive project.tar.gz -X ".hg*"
381 381
382 382 Valid types are:
383 383
384 384 :``files``: a directory full of files (default)
385 385 :``tar``: tar archive, uncompressed
386 386 :``tbz2``: tar archive, compressed using bzip2
387 387 :``tgz``: tar archive, compressed using gzip
388 388 :``uzip``: zip archive, uncompressed
389 389 :``zip``: zip archive, compressed using deflate
390 390
391 391 The exact name of the destination archive or directory is given
392 392 using a format string; see :hg:`help export` for details.
393 393
394 394 Each member added to an archive file has a directory prefix
395 395 prepended. Use -p/--prefix to specify a format string for the
396 396 prefix. The default is the basename of the archive, with suffixes
397 397 removed.
398 398
399 399 Returns 0 on success.
400 400 '''
401 401
402 402 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 403 if not ctx:
404 404 raise util.Abort(_('no working directory: please specify a revision'))
405 405 node = ctx.node()
406 406 dest = cmdutil.makefilename(repo, dest, node)
407 407 if os.path.realpath(dest) == repo.root:
408 408 raise util.Abort(_('repository root cannot be destination'))
409 409
410 410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 411 prefix = opts.get('prefix')
412 412
413 413 if dest == '-':
414 414 if kind == 'files':
415 415 raise util.Abort(_('cannot archive plain files to stdout'))
416 416 dest = cmdutil.makefileobj(repo, dest)
417 417 if not prefix:
418 418 prefix = os.path.basename(repo.root) + '-%h'
419 419
420 420 prefix = cmdutil.makefilename(repo, prefix, node)
421 421 matchfn = scmutil.match(ctx, [], opts)
422 422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 423 matchfn, prefix, subrepos=opts.get('subrepos'))
424 424
425 425 @command('backout',
426 426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 427 ('', 'parent', '',
428 428 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
429 429 ('r', 'rev', '', _('revision to backout'), _('REV')),
430 430 ('e', 'edit', False, _('invoke editor on commit messages')),
431 431 ] + mergetoolopts + walkopts + commitopts + commitopts2,
432 432 _('[OPTION]... [-r] REV'))
433 433 def backout(ui, repo, node=None, rev=None, **opts):
434 434 '''reverse effect of earlier changeset
435 435
436 436 Prepare a new changeset with the effect of REV undone in the
437 437 current working directory.
438 438
439 439 If REV is the parent of the working directory, then this new changeset
440 440 is committed automatically. Otherwise, hg needs to merge the
441 441 changes and the merged result is left uncommitted.
442 442
443 443 .. note::
444 444
445 445 backout cannot be used to fix either an unwanted or
446 446 incorrect merge.
447 447
448 448 .. container:: verbose
449 449
450 450 By default, the pending changeset will have one parent,
451 451 maintaining a linear history. With --merge, the pending
452 452 changeset will instead have two parents: the old parent of the
453 453 working directory and a new child of REV that simply undoes REV.
454 454
455 455 Before version 1.7, the behavior without --merge was equivalent
456 456 to specifying --merge followed by :hg:`update --clean .` to
457 457 cancel the merge and leave the child of REV as a head to be
458 458 merged separately.
459 459
460 460 See :hg:`help dates` for a list of formats valid for -d/--date.
461 461
462 462 Returns 0 on success, 1 if nothing to backout or there are unresolved
463 463 files.
464 464 '''
465 465 if rev and node:
466 466 raise util.Abort(_("please specify just one revision"))
467 467
468 468 if not rev:
469 469 rev = node
470 470
471 471 if not rev:
472 472 raise util.Abort(_("please specify a revision to backout"))
473 473
474 474 date = opts.get('date')
475 475 if date:
476 476 opts['date'] = util.parsedate(date)
477 477
478 478 cmdutil.checkunfinished(repo)
479 479 cmdutil.bailifchanged(repo)
480 480 node = scmutil.revsingle(repo, rev).node()
481 481
482 482 op1, op2 = repo.dirstate.parents()
483 483 if not repo.changelog.isancestor(node, op1):
484 484 raise util.Abort(_('cannot backout change that is not an ancestor'))
485 485
486 486 p1, p2 = repo.changelog.parents(node)
487 487 if p1 == nullid:
488 488 raise util.Abort(_('cannot backout a change with no parents'))
489 489 if p2 != nullid:
490 490 if not opts.get('parent'):
491 491 raise util.Abort(_('cannot backout a merge changeset'))
492 492 p = repo.lookup(opts['parent'])
493 493 if p not in (p1, p2):
494 494 raise util.Abort(_('%s is not a parent of %s') %
495 495 (short(p), short(node)))
496 496 parent = p
497 497 else:
498 498 if opts.get('parent'):
499 499 raise util.Abort(_('cannot use --parent on non-merge changeset'))
500 500 parent = p1
501 501
502 502 # the backout should appear on the same branch
503 503 wlock = repo.wlock()
504 504 try:
505 505 branch = repo.dirstate.branch()
506 506 bheads = repo.branchheads(branch)
507 507 rctx = scmutil.revsingle(repo, hex(parent))
508 508 if not opts.get('merge') and op1 != node:
509 509 try:
510 510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
511 511 'backout')
512 512 repo.dirstate.beginparentchange()
513 513 stats = mergemod.update(repo, parent, True, True, False,
514 514 node, False)
515 515 repo.setparents(op1, op2)
516 516 repo.dirstate.endparentchange()
517 517 hg._showstats(repo, stats)
518 518 if stats[3]:
519 519 repo.ui.status(_("use 'hg resolve' to retry unresolved "
520 520 "file merges\n"))
521 521 else:
522 522 msg = _("changeset %s backed out, "
523 523 "don't forget to commit.\n")
524 524 ui.status(msg % short(node))
525 525 return stats[3] > 0
526 526 finally:
527 527 ui.setconfig('ui', 'forcemerge', '', '')
528 528 else:
529 529 hg.clean(repo, node, show_stats=False)
530 530 repo.dirstate.setbranch(branch)
531 531 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
532 532
533 533
534 534 def commitfunc(ui, repo, message, match, opts):
535 535 editform = 'backout'
536 536 e = cmdutil.getcommiteditor(editform=editform, **opts)
537 537 if not message:
538 538 # we don't translate commit messages
539 539 message = "Backed out changeset %s" % short(node)
540 540 e = cmdutil.getcommiteditor(edit=True, editform=editform)
541 541 return repo.commit(message, opts.get('user'), opts.get('date'),
542 542 match, editor=e)
543 543 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
544 544 if not newnode:
545 545 ui.status(_("nothing changed\n"))
546 546 return 1
547 547 cmdutil.commitstatus(repo, newnode, branch, bheads)
548 548
549 549 def nice(node):
550 550 return '%d:%s' % (repo.changelog.rev(node), short(node))
551 551 ui.status(_('changeset %s backs out changeset %s\n') %
552 552 (nice(repo.changelog.tip()), nice(node)))
553 553 if opts.get('merge') and op1 != node:
554 554 hg.clean(repo, op1, show_stats=False)
555 555 ui.status(_('merging with changeset %s\n')
556 556 % nice(repo.changelog.tip()))
557 557 try:
558 558 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
559 559 'backout')
560 560 return hg.merge(repo, hex(repo.changelog.tip()))
561 561 finally:
562 562 ui.setconfig('ui', 'forcemerge', '', '')
563 563 finally:
564 564 wlock.release()
565 565 return 0
566 566
567 567 @command('bisect',
568 568 [('r', 'reset', False, _('reset bisect state')),
569 569 ('g', 'good', False, _('mark changeset good')),
570 570 ('b', 'bad', False, _('mark changeset bad')),
571 571 ('s', 'skip', False, _('skip testing changeset')),
572 572 ('e', 'extend', False, _('extend the bisect range')),
573 573 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
574 574 ('U', 'noupdate', False, _('do not update to target'))],
575 575 _("[-gbsr] [-U] [-c CMD] [REV]"))
576 576 def bisect(ui, repo, rev=None, extra=None, command=None,
577 577 reset=None, good=None, bad=None, skip=None, extend=None,
578 578 noupdate=None):
579 579 """subdivision search of changesets
580 580
581 581 This command helps to find changesets which introduce problems. To
582 582 use, mark the earliest changeset you know exhibits the problem as
583 583 bad, then mark the latest changeset which is free from the problem
584 584 as good. Bisect will update your working directory to a revision
585 585 for testing (unless the -U/--noupdate option is specified). Once
586 586 you have performed tests, mark the working directory as good or
587 587 bad, and bisect will either update to another candidate changeset
588 588 or announce that it has found the bad revision.
589 589
590 590 As a shortcut, you can also use the revision argument to mark a
591 591 revision as good or bad without checking it out first.
592 592
593 593 If you supply a command, it will be used for automatic bisection.
594 594 The environment variable HG_NODE will contain the ID of the
595 595 changeset being tested. The exit status of the command will be
596 596 used to mark revisions as good or bad: status 0 means good, 125
597 597 means to skip the revision, 127 (command not found) will abort the
598 598 bisection, and any other non-zero exit status means the revision
599 599 is bad.
600 600
601 601 .. container:: verbose
602 602
603 603 Some examples:
604 604
605 605 - start a bisection with known bad revision 34, and good revision 12::
606 606
607 607 hg bisect --bad 34
608 608 hg bisect --good 12
609 609
610 610 - advance the current bisection by marking current revision as good or
611 611 bad::
612 612
613 613 hg bisect --good
614 614 hg bisect --bad
615 615
616 616 - mark the current revision, or a known revision, to be skipped (e.g. if
617 617 that revision is not usable because of another issue)::
618 618
619 619 hg bisect --skip
620 620 hg bisect --skip 23
621 621
622 622 - skip all revisions that do not touch directories ``foo`` or ``bar``::
623 623
624 624 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
625 625
626 626 - forget the current bisection::
627 627
628 628 hg bisect --reset
629 629
630 630 - use 'make && make tests' to automatically find the first broken
631 631 revision::
632 632
633 633 hg bisect --reset
634 634 hg bisect --bad 34
635 635 hg bisect --good 12
636 636 hg bisect --command "make && make tests"
637 637
638 638 - see all changesets whose states are already known in the current
639 639 bisection::
640 640
641 641 hg log -r "bisect(pruned)"
642 642
643 643 - see the changeset currently being bisected (especially useful
644 644 if running with -U/--noupdate)::
645 645
646 646 hg log -r "bisect(current)"
647 647
648 648 - see all changesets that took part in the current bisection::
649 649
650 650 hg log -r "bisect(range)"
651 651
652 652 - you can even get a nice graph::
653 653
654 654 hg log --graph -r "bisect(range)"
655 655
656 656 See :hg:`help revsets` for more about the `bisect()` keyword.
657 657
658 658 Returns 0 on success.
659 659 """
660 660 def extendbisectrange(nodes, good):
661 661 # bisect is incomplete when it ends on a merge node and
662 662 # one of the parent was not checked.
663 663 parents = repo[nodes[0]].parents()
664 664 if len(parents) > 1:
665 665 side = good and state['bad'] or state['good']
666 666 num = len(set(i.node() for i in parents) & set(side))
667 667 if num == 1:
668 668 return parents[0].ancestor(parents[1])
669 669 return None
670 670
671 671 def print_result(nodes, good):
672 672 displayer = cmdutil.show_changeset(ui, repo, {})
673 673 if len(nodes) == 1:
674 674 # narrowed it down to a single revision
675 675 if good:
676 676 ui.write(_("The first good revision is:\n"))
677 677 else:
678 678 ui.write(_("The first bad revision is:\n"))
679 679 displayer.show(repo[nodes[0]])
680 680 extendnode = extendbisectrange(nodes, good)
681 681 if extendnode is not None:
682 682 ui.write(_('Not all ancestors of this changeset have been'
683 683 ' checked.\nUse bisect --extend to continue the '
684 684 'bisection from\nthe common ancestor, %s.\n')
685 685 % extendnode)
686 686 else:
687 687 # multiple possible revisions
688 688 if good:
689 689 ui.write(_("Due to skipped revisions, the first "
690 690 "good revision could be any of:\n"))
691 691 else:
692 692 ui.write(_("Due to skipped revisions, the first "
693 693 "bad revision could be any of:\n"))
694 694 for n in nodes:
695 695 displayer.show(repo[n])
696 696 displayer.close()
697 697
698 698 def check_state(state, interactive=True):
699 699 if not state['good'] or not state['bad']:
700 700 if (good or bad or skip or reset) and interactive:
701 701 return
702 702 if not state['good']:
703 703 raise util.Abort(_('cannot bisect (no known good revisions)'))
704 704 else:
705 705 raise util.Abort(_('cannot bisect (no known bad revisions)'))
706 706 return True
707 707
708 708 # backward compatibility
709 709 if rev in "good bad reset init".split():
710 710 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
711 711 cmd, rev, extra = rev, extra, None
712 712 if cmd == "good":
713 713 good = True
714 714 elif cmd == "bad":
715 715 bad = True
716 716 else:
717 717 reset = True
718 718 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
719 719 raise util.Abort(_('incompatible arguments'))
720 720
721 721 cmdutil.checkunfinished(repo)
722 722
723 723 if reset:
724 724 p = repo.join("bisect.state")
725 725 if os.path.exists(p):
726 726 os.unlink(p)
727 727 return
728 728
729 729 state = hbisect.load_state(repo)
730 730
731 731 if command:
732 732 changesets = 1
733 733 if noupdate:
734 734 try:
735 735 node = state['current'][0]
736 736 except LookupError:
737 737 raise util.Abort(_('current bisect revision is unknown - '
738 738 'start a new bisect to fix'))
739 739 else:
740 740 node, p2 = repo.dirstate.parents()
741 741 if p2 != nullid:
742 742 raise util.Abort(_('current bisect revision is a merge'))
743 743 try:
744 744 while changesets:
745 745 # update state
746 746 state['current'] = [node]
747 747 hbisect.save_state(repo, state)
748 748 status = util.system(command,
749 749 environ={'HG_NODE': hex(node)},
750 750 out=ui.fout)
751 751 if status == 125:
752 752 transition = "skip"
753 753 elif status == 0:
754 754 transition = "good"
755 755 # status < 0 means process was killed
756 756 elif status == 127:
757 757 raise util.Abort(_("failed to execute %s") % command)
758 758 elif status < 0:
759 759 raise util.Abort(_("%s killed") % command)
760 760 else:
761 761 transition = "bad"
762 762 ctx = scmutil.revsingle(repo, rev, node)
763 763 rev = None # clear for future iterations
764 764 state[transition].append(ctx.node())
765 765 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
766 766 check_state(state, interactive=False)
767 767 # bisect
768 768 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
769 769 # update to next check
770 770 node = nodes[0]
771 771 if not noupdate:
772 772 cmdutil.bailifchanged(repo)
773 773 hg.clean(repo, node, show_stats=False)
774 774 finally:
775 775 state['current'] = [node]
776 776 hbisect.save_state(repo, state)
777 777 print_result(nodes, bgood)
778 778 return
779 779
780 780 # update state
781 781
782 782 if rev:
783 783 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
784 784 else:
785 785 nodes = [repo.lookup('.')]
786 786
787 787 if good or bad or skip:
788 788 if good:
789 789 state['good'] += nodes
790 790 elif bad:
791 791 state['bad'] += nodes
792 792 elif skip:
793 793 state['skip'] += nodes
794 794 hbisect.save_state(repo, state)
795 795
796 796 if not check_state(state):
797 797 return
798 798
799 799 # actually bisect
800 800 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
801 801 if extend:
802 802 if not changesets:
803 803 extendnode = extendbisectrange(nodes, good)
804 804 if extendnode is not None:
805 805 ui.write(_("Extending search to changeset %d:%s\n")
806 806 % (extendnode.rev(), extendnode))
807 807 state['current'] = [extendnode.node()]
808 808 hbisect.save_state(repo, state)
809 809 if noupdate:
810 810 return
811 811 cmdutil.bailifchanged(repo)
812 812 return hg.clean(repo, extendnode.node())
813 813 raise util.Abort(_("nothing to extend"))
814 814
815 815 if changesets == 0:
816 816 print_result(nodes, good)
817 817 else:
818 818 assert len(nodes) == 1 # only a single node can be tested next
819 819 node = nodes[0]
820 820 # compute the approximate number of remaining tests
821 821 tests, size = 0, 2
822 822 while size <= changesets:
823 823 tests, size = tests + 1, size * 2
824 824 rev = repo.changelog.rev(node)
825 825 ui.write(_("Testing changeset %d:%s "
826 826 "(%d changesets remaining, ~%d tests)\n")
827 827 % (rev, short(node), changesets, tests))
828 828 state['current'] = [node]
829 829 hbisect.save_state(repo, state)
830 830 if not noupdate:
831 831 cmdutil.bailifchanged(repo)
832 832 return hg.clean(repo, node)
833 833
834 834 @command('bookmarks|bookmark',
835 835 [('f', 'force', False, _('force')),
836 836 ('r', 'rev', '', _('revision'), _('REV')),
837 837 ('d', 'delete', False, _('delete a given bookmark')),
838 838 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
839 839 ('i', 'inactive', False, _('mark a bookmark inactive'))],
840 840 _('hg bookmarks [OPTIONS]... [NAME]...'))
841 841 def bookmark(ui, repo, *names, **opts):
842 842 '''create a new bookmark or list existing bookmarks
843 843
844 844 Bookmarks are labels on changesets to help track lines of development.
845 845 Bookmarks are unversioned and can be moved, renamed and deleted.
846 846 Deleting or moving a bookmark has no effect on the associated changesets.
847 847
848 848 Creating or updating to a bookmark causes it to be marked as 'active'.
849 849 The active bookmark is indicated with a '*'.
850 850 When a commit is made, the active bookmark will advance to the new commit.
851 851 A plain :hg:`update` will also advance an active bookmark, if possible.
852 852 Updating away from a bookmark will cause it to be deactivated.
853 853
854 854 Bookmarks can be pushed and pulled between repositories (see
855 855 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
856 856 diverged, a new 'divergent bookmark' of the form 'name@path' will
857 857 be created. Using :hg:'merge' will resolve the divergence.
858 858
859 859 A bookmark named '@' has the special property that :hg:`clone` will
860 860 check it out by default if it exists.
861 861
862 862 .. container:: verbose
863 863
864 864 Examples:
865 865
866 866 - create an active bookmark for a new line of development::
867 867
868 868 hg book new-feature
869 869
870 870 - create an inactive bookmark as a place marker::
871 871
872 872 hg book -i reviewed
873 873
874 874 - create an inactive bookmark on another changeset::
875 875
876 876 hg book -r .^ tested
877 877
878 878 - move the '@' bookmark from another branch::
879 879
880 880 hg book -f @
881 881 '''
882 882 force = opts.get('force')
883 883 rev = opts.get('rev')
884 884 delete = opts.get('delete')
885 885 rename = opts.get('rename')
886 886 inactive = opts.get('inactive')
887 887
888 888 def checkformat(mark):
889 889 mark = mark.strip()
890 890 if not mark:
891 891 raise util.Abort(_("bookmark names cannot consist entirely of "
892 892 "whitespace"))
893 893 scmutil.checknewlabel(repo, mark, 'bookmark')
894 894 return mark
895 895
896 896 def checkconflict(repo, mark, cur, force=False, target=None):
897 897 if mark in marks and not force:
898 898 if target:
899 899 if marks[mark] == target and target == cur:
900 900 # re-activating a bookmark
901 901 return
902 902 anc = repo.changelog.ancestors([repo[target].rev()])
903 903 bmctx = repo[marks[mark]]
904 904 divs = [repo[b].node() for b in marks
905 905 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
906 906
907 907 # allow resolving a single divergent bookmark even if moving
908 908 # the bookmark across branches when a revision is specified
909 909 # that contains a divergent bookmark
910 910 if bmctx.rev() not in anc and target in divs:
911 911 bookmarks.deletedivergent(repo, [target], mark)
912 912 return
913 913
914 914 deletefrom = [b for b in divs
915 915 if repo[b].rev() in anc or b == target]
916 916 bookmarks.deletedivergent(repo, deletefrom, mark)
917 917 if bookmarks.validdest(repo, bmctx, repo[target]):
918 918 ui.status(_("moving bookmark '%s' forward from %s\n") %
919 919 (mark, short(bmctx.node())))
920 920 return
921 921 raise util.Abort(_("bookmark '%s' already exists "
922 922 "(use -f to force)") % mark)
923 923 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
924 924 and not force):
925 925 raise util.Abort(
926 926 _("a bookmark cannot have the name of an existing branch"))
927 927
928 928 if delete and rename:
929 929 raise util.Abort(_("--delete and --rename are incompatible"))
930 930 if delete and rev:
931 931 raise util.Abort(_("--rev is incompatible with --delete"))
932 932 if rename and rev:
933 933 raise util.Abort(_("--rev is incompatible with --rename"))
934 934 if not names and (delete or rev):
935 935 raise util.Abort(_("bookmark name required"))
936 936
937 937 if delete or rename or names or inactive:
938 938 wlock = repo.wlock()
939 939 try:
940 940 cur = repo.changectx('.').node()
941 941 marks = repo._bookmarks
942 942 if delete:
943 943 for mark in names:
944 944 if mark not in marks:
945 945 raise util.Abort(_("bookmark '%s' does not exist") %
946 946 mark)
947 947 if mark == repo._bookmarkcurrent:
948 948 bookmarks.unsetcurrent(repo)
949 949 del marks[mark]
950 950 marks.write()
951 951
952 952 elif rename:
953 953 if not names:
954 954 raise util.Abort(_("new bookmark name required"))
955 955 elif len(names) > 1:
956 956 raise util.Abort(_("only one new bookmark name allowed"))
957 957 mark = checkformat(names[0])
958 958 if rename not in marks:
959 959 raise util.Abort(_("bookmark '%s' does not exist") % rename)
960 960 checkconflict(repo, mark, cur, force)
961 961 marks[mark] = marks[rename]
962 962 if repo._bookmarkcurrent == rename and not inactive:
963 963 bookmarks.setcurrent(repo, mark)
964 964 del marks[rename]
965 965 marks.write()
966 966
967 967 elif names:
968 968 newact = None
969 969 for mark in names:
970 970 mark = checkformat(mark)
971 971 if newact is None:
972 972 newact = mark
973 973 if inactive and mark == repo._bookmarkcurrent:
974 974 bookmarks.unsetcurrent(repo)
975 975 return
976 976 tgt = cur
977 977 if rev:
978 978 tgt = scmutil.revsingle(repo, rev).node()
979 979 checkconflict(repo, mark, cur, force, tgt)
980 980 marks[mark] = tgt
981 981 if not inactive and cur == marks[newact] and not rev:
982 982 bookmarks.setcurrent(repo, newact)
983 983 elif cur != tgt and newact == repo._bookmarkcurrent:
984 984 bookmarks.unsetcurrent(repo)
985 985 marks.write()
986 986
987 987 elif inactive:
988 988 if len(marks) == 0:
989 989 ui.status(_("no bookmarks set\n"))
990 990 elif not repo._bookmarkcurrent:
991 991 ui.status(_("no active bookmark\n"))
992 992 else:
993 993 bookmarks.unsetcurrent(repo)
994 994 finally:
995 995 wlock.release()
996 996 else: # show bookmarks
997 997 hexfn = ui.debugflag and hex or short
998 998 marks = repo._bookmarks
999 999 if len(marks) == 0:
1000 1000 ui.status(_("no bookmarks set\n"))
1001 1001 else:
1002 1002 for bmark, n in sorted(marks.iteritems()):
1003 1003 current = repo._bookmarkcurrent
1004 1004 if bmark == current:
1005 1005 prefix, label = '*', 'bookmarks.current'
1006 1006 else:
1007 1007 prefix, label = ' ', ''
1008 1008
1009 1009 if ui.quiet:
1010 1010 ui.write("%s\n" % bmark, label=label)
1011 1011 else:
1012 1012 pad = " " * (25 - encoding.colwidth(bmark))
1013 1013 ui.write(" %s %s%s %d:%s\n" % (
1014 1014 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1015 1015 label=label)
1016 1016
1017 1017 @command('branch',
1018 1018 [('f', 'force', None,
1019 1019 _('set branch name even if it shadows an existing branch')),
1020 1020 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1021 1021 _('[-fC] [NAME]'))
1022 1022 def branch(ui, repo, label=None, **opts):
1023 1023 """set or show the current branch name
1024 1024
1025 1025 .. note::
1026 1026
1027 1027 Branch names are permanent and global. Use :hg:`bookmark` to create a
1028 1028 light-weight bookmark instead. See :hg:`help glossary` for more
1029 1029 information about named branches and bookmarks.
1030 1030
1031 1031 With no argument, show the current branch name. With one argument,
1032 1032 set the working directory branch name (the branch will not exist
1033 1033 in the repository until the next commit). Standard practice
1034 1034 recommends that primary development take place on the 'default'
1035 1035 branch.
1036 1036
1037 1037 Unless -f/--force is specified, branch will not let you set a
1038 1038 branch name that already exists, even if it's inactive.
1039 1039
1040 1040 Use -C/--clean to reset the working directory branch to that of
1041 1041 the parent of the working directory, negating a previous branch
1042 1042 change.
1043 1043
1044 1044 Use the command :hg:`update` to switch to an existing branch. Use
1045 1045 :hg:`commit --close-branch` to mark this branch as closed.
1046 1046
1047 1047 Returns 0 on success.
1048 1048 """
1049 1049 if label:
1050 1050 label = label.strip()
1051 1051
1052 1052 if not opts.get('clean') and not label:
1053 1053 ui.write("%s\n" % repo.dirstate.branch())
1054 1054 return
1055 1055
1056 1056 wlock = repo.wlock()
1057 1057 try:
1058 1058 if opts.get('clean'):
1059 1059 label = repo[None].p1().branch()
1060 1060 repo.dirstate.setbranch(label)
1061 1061 ui.status(_('reset working directory to branch %s\n') % label)
1062 1062 elif label:
1063 1063 if not opts.get('force') and label in repo.branchmap():
1064 1064 if label not in [p.branch() for p in repo.parents()]:
1065 1065 raise util.Abort(_('a branch of the same name already'
1066 1066 ' exists'),
1067 1067 # i18n: "it" refers to an existing branch
1068 1068 hint=_("use 'hg update' to switch to it"))
1069 1069 scmutil.checknewlabel(repo, label, 'branch')
1070 1070 repo.dirstate.setbranch(label)
1071 1071 ui.status(_('marked working directory as branch %s\n') % label)
1072 1072 ui.status(_('(branches are permanent and global, '
1073 1073 'did you want a bookmark?)\n'))
1074 1074 finally:
1075 1075 wlock.release()
1076 1076
1077 1077 @command('branches',
1078 1078 [('a', 'active', False, _('show only branches that have unmerged heads')),
1079 1079 ('c', 'closed', False, _('show normal and closed branches'))],
1080 1080 _('[-ac]'))
1081 1081 def branches(ui, repo, active=False, closed=False):
1082 1082 """list repository named branches
1083 1083
1084 1084 List the repository's named branches, indicating which ones are
1085 1085 inactive. If -c/--closed is specified, also list branches which have
1086 1086 been marked closed (see :hg:`commit --close-branch`).
1087 1087
1088 1088 If -a/--active is specified, only show active branches. A branch
1089 1089 is considered active if it contains repository heads.
1090 1090
1091 1091 Use the command :hg:`update` to switch to an existing branch.
1092 1092
1093 1093 Returns 0.
1094 1094 """
1095 1095
1096 1096 hexfunc = ui.debugflag and hex or short
1097 1097
1098 1098 allheads = set(repo.heads())
1099 1099 branches = []
1100 1100 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1101 1101 isactive = not isclosed and bool(set(heads) & allheads)
1102 1102 branches.append((tag, repo[tip], isactive, not isclosed))
1103 1103 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1104 1104 reverse=True)
1105 1105
1106 1106 for tag, ctx, isactive, isopen in branches:
1107 1107 if (not active) or isactive:
1108 1108 if isactive:
1109 1109 label = 'branches.active'
1110 1110 notice = ''
1111 1111 elif not isopen:
1112 1112 if not closed:
1113 1113 continue
1114 1114 label = 'branches.closed'
1115 1115 notice = _(' (closed)')
1116 1116 else:
1117 1117 label = 'branches.inactive'
1118 1118 notice = _(' (inactive)')
1119 1119 if tag == repo.dirstate.branch():
1120 1120 label = 'branches.current'
1121 1121 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1122 1122 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1123 1123 'log.changeset changeset.%s' % ctx.phasestr())
1124 1124 labeledtag = ui.label(tag, label)
1125 1125 if ui.quiet:
1126 1126 ui.write("%s\n" % labeledtag)
1127 1127 else:
1128 1128 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1129 1129
1130 1130 @command('bundle',
1131 1131 [('f', 'force', None, _('run even when the destination is unrelated')),
1132 1132 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1133 1133 _('REV')),
1134 1134 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1135 1135 _('BRANCH')),
1136 1136 ('', 'base', [],
1137 1137 _('a base changeset assumed to be available at the destination'),
1138 1138 _('REV')),
1139 1139 ('a', 'all', None, _('bundle all changesets in the repository')),
1140 1140 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1141 1141 ] + remoteopts,
1142 1142 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1143 1143 def bundle(ui, repo, fname, dest=None, **opts):
1144 1144 """create a changegroup file
1145 1145
1146 1146 Generate a compressed changegroup file collecting changesets not
1147 1147 known to be in another repository.
1148 1148
1149 1149 If you omit the destination repository, then hg assumes the
1150 1150 destination will have all the nodes you specify with --base
1151 1151 parameters. To create a bundle containing all changesets, use
1152 1152 -a/--all (or --base null).
1153 1153
1154 1154 You can change compression method with the -t/--type option.
1155 1155 The available compression methods are: none, bzip2, and
1156 1156 gzip (by default, bundles are compressed using bzip2).
1157 1157
1158 1158 The bundle file can then be transferred using conventional means
1159 1159 and applied to another repository with the unbundle or pull
1160 1160 command. This is useful when direct push and pull are not
1161 1161 available or when exporting an entire repository is undesirable.
1162 1162
1163 1163 Applying bundles preserves all changeset contents including
1164 1164 permissions, copy/rename information, and revision history.
1165 1165
1166 1166 Returns 0 on success, 1 if no changes found.
1167 1167 """
1168 1168 revs = None
1169 1169 if 'rev' in opts:
1170 1170 revs = scmutil.revrange(repo, opts['rev'])
1171 1171
1172 1172 bundletype = opts.get('type', 'bzip2').lower()
1173 1173 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1174 1174 bundletype = btypes.get(bundletype)
1175 1175 if bundletype not in changegroup.bundletypes:
1176 1176 raise util.Abort(_('unknown bundle type specified with --type'))
1177 1177
1178 1178 if opts.get('all'):
1179 1179 base = ['null']
1180 1180 else:
1181 1181 base = scmutil.revrange(repo, opts.get('base'))
1182 1182 # TODO: get desired bundlecaps from command line.
1183 1183 bundlecaps = None
1184 1184 if base:
1185 1185 if dest:
1186 1186 raise util.Abort(_("--base is incompatible with specifying "
1187 1187 "a destination"))
1188 1188 common = [repo.lookup(rev) for rev in base]
1189 1189 heads = revs and map(repo.lookup, revs) or revs
1190 1190 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1191 1191 common=common, bundlecaps=bundlecaps)
1192 1192 outgoing = None
1193 1193 else:
1194 1194 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1195 1195 dest, branches = hg.parseurl(dest, opts.get('branch'))
1196 1196 other = hg.peer(repo, opts, dest)
1197 1197 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1198 1198 heads = revs and map(repo.lookup, revs) or revs
1199 1199 outgoing = discovery.findcommonoutgoing(repo, other,
1200 1200 onlyheads=heads,
1201 1201 force=opts.get('force'),
1202 1202 portable=True)
1203 1203 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1204 1204 bundlecaps)
1205 1205 if not cg:
1206 1206 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1207 1207 return 1
1208 1208
1209 1209 changegroup.writebundle(cg, fname, bundletype)
1210 1210
1211 1211 @command('cat',
1212 1212 [('o', 'output', '',
1213 1213 _('print output to file with formatted name'), _('FORMAT')),
1214 1214 ('r', 'rev', '', _('print the given revision'), _('REV')),
1215 1215 ('', 'decode', None, _('apply any matching decode filter')),
1216 1216 ] + walkopts,
1217 1217 _('[OPTION]... FILE...'),
1218 1218 inferrepo=True)
1219 1219 def cat(ui, repo, file1, *pats, **opts):
1220 1220 """output the current or given revision of files
1221 1221
1222 1222 Print the specified files as they were at the given revision. If
1223 1223 no revision is given, the parent of the working directory is used.
1224 1224
1225 1225 Output may be to a file, in which case the name of the file is
1226 1226 given using a format string. The formatting rules as follows:
1227 1227
1228 1228 :``%%``: literal "%" character
1229 1229 :``%s``: basename of file being printed
1230 1230 :``%d``: dirname of file being printed, or '.' if in repository root
1231 1231 :``%p``: root-relative path name of file being printed
1232 1232 :``%H``: changeset hash (40 hexadecimal digits)
1233 1233 :``%R``: changeset revision number
1234 1234 :``%h``: short-form changeset hash (12 hexadecimal digits)
1235 1235 :``%r``: zero-padded changeset revision number
1236 1236 :``%b``: basename of the exporting repository
1237 1237
1238 1238 Returns 0 on success.
1239 1239 """
1240 1240 ctx = scmutil.revsingle(repo, opts.get('rev'))
1241 1241 m = scmutil.match(ctx, (file1,) + pats, opts)
1242 1242
1243 1243 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1244 1244
1245 1245 @command('^clone',
1246 1246 [('U', 'noupdate', None,
1247 1247 _('the clone will include an empty working copy (only a repository)')),
1248 1248 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1249 1249 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1250 1250 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1251 1251 ('', 'pull', None, _('use pull protocol to copy metadata')),
1252 1252 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1253 1253 ] + remoteopts,
1254 1254 _('[OPTION]... SOURCE [DEST]'),
1255 1255 norepo=True)
1256 1256 def clone(ui, source, dest=None, **opts):
1257 1257 """make a copy of an existing repository
1258 1258
1259 1259 Create a copy of an existing repository in a new directory.
1260 1260
1261 1261 If no destination directory name is specified, it defaults to the
1262 1262 basename of the source.
1263 1263
1264 1264 The location of the source is added to the new repository's
1265 1265 ``.hg/hgrc`` file, as the default to be used for future pulls.
1266 1266
1267 1267 Only local paths and ``ssh://`` URLs are supported as
1268 1268 destinations. For ``ssh://`` destinations, no working directory or
1269 1269 ``.hg/hgrc`` will be created on the remote side.
1270 1270
1271 1271 To pull only a subset of changesets, specify one or more revisions
1272 1272 identifiers with -r/--rev or branches with -b/--branch. The
1273 1273 resulting clone will contain only the specified changesets and
1274 1274 their ancestors. These options (or 'clone src#rev dest') imply
1275 1275 --pull, even for local source repositories. Note that specifying a
1276 1276 tag will include the tagged changeset but not the changeset
1277 1277 containing the tag.
1278 1278
1279 1279 If the source repository has a bookmark called '@' set, that
1280 1280 revision will be checked out in the new repository by default.
1281 1281
1282 1282 To check out a particular version, use -u/--update, or
1283 1283 -U/--noupdate to create a clone with no working directory.
1284 1284
1285 1285 .. container:: verbose
1286 1286
1287 1287 For efficiency, hardlinks are used for cloning whenever the
1288 1288 source and destination are on the same filesystem (note this
1289 1289 applies only to the repository data, not to the working
1290 1290 directory). Some filesystems, such as AFS, implement hardlinking
1291 1291 incorrectly, but do not report errors. In these cases, use the
1292 1292 --pull option to avoid hardlinking.
1293 1293
1294 1294 In some cases, you can clone repositories and the working
1295 1295 directory using full hardlinks with ::
1296 1296
1297 1297 $ cp -al REPO REPOCLONE
1298 1298
1299 1299 This is the fastest way to clone, but it is not always safe. The
1300 1300 operation is not atomic (making sure REPO is not modified during
1301 1301 the operation is up to you) and you have to make sure your
1302 1302 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1303 1303 so). Also, this is not compatible with certain extensions that
1304 1304 place their metadata under the .hg directory, such as mq.
1305 1305
1306 1306 Mercurial will update the working directory to the first applicable
1307 1307 revision from this list:
1308 1308
1309 1309 a) null if -U or the source repository has no changesets
1310 1310 b) if -u . and the source repository is local, the first parent of
1311 1311 the source repository's working directory
1312 1312 c) the changeset specified with -u (if a branch name, this means the
1313 1313 latest head of that branch)
1314 1314 d) the changeset specified with -r
1315 1315 e) the tipmost head specified with -b
1316 1316 f) the tipmost head specified with the url#branch source syntax
1317 1317 g) the revision marked with the '@' bookmark, if present
1318 1318 h) the tipmost head of the default branch
1319 1319 i) tip
1320 1320
1321 1321 Examples:
1322 1322
1323 1323 - clone a remote repository to a new directory named hg/::
1324 1324
1325 1325 hg clone http://selenic.com/hg
1326 1326
1327 1327 - create a lightweight local clone::
1328 1328
1329 1329 hg clone project/ project-feature/
1330 1330
1331 1331 - clone from an absolute path on an ssh server (note double-slash)::
1332 1332
1333 1333 hg clone ssh://user@server//home/projects/alpha/
1334 1334
1335 1335 - do a high-speed clone over a LAN while checking out a
1336 1336 specified version::
1337 1337
1338 1338 hg clone --uncompressed http://server/repo -u 1.5
1339 1339
1340 1340 - create a repository without changesets after a particular revision::
1341 1341
1342 1342 hg clone -r 04e544 experimental/ good/
1343 1343
1344 1344 - clone (and track) a particular named branch::
1345 1345
1346 1346 hg clone http://selenic.com/hg#stable
1347 1347
1348 1348 See :hg:`help urls` for details on specifying URLs.
1349 1349
1350 1350 Returns 0 on success.
1351 1351 """
1352 1352 if opts.get('noupdate') and opts.get('updaterev'):
1353 1353 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1354 1354
1355 1355 r = hg.clone(ui, opts, source, dest,
1356 1356 pull=opts.get('pull'),
1357 1357 stream=opts.get('uncompressed'),
1358 1358 rev=opts.get('rev'),
1359 1359 update=opts.get('updaterev') or not opts.get('noupdate'),
1360 1360 branch=opts.get('branch'))
1361 1361
1362 1362 return r is None
1363 1363
1364 1364 @command('^commit|ci',
1365 1365 [('A', 'addremove', None,
1366 1366 _('mark new/missing files as added/removed before committing')),
1367 1367 ('', 'close-branch', None,
1368 1368 _('mark a branch as closed, hiding it from the branch list')),
1369 1369 ('', 'amend', None, _('amend the parent of the working dir')),
1370 1370 ('s', 'secret', None, _('use the secret phase for committing')),
1371 1371 ('e', 'edit', None, _('invoke editor on commit messages')),
1372 1372 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1373 1373 _('[OPTION]... [FILE]...'),
1374 1374 inferrepo=True)
1375 1375 def commit(ui, repo, *pats, **opts):
1376 1376 """commit the specified files or all outstanding changes
1377 1377
1378 1378 Commit changes to the given files into the repository. Unlike a
1379 1379 centralized SCM, this operation is a local operation. See
1380 1380 :hg:`push` for a way to actively distribute your changes.
1381 1381
1382 1382 If a list of files is omitted, all changes reported by :hg:`status`
1383 1383 will be committed.
1384 1384
1385 1385 If you are committing the result of a merge, do not provide any
1386 1386 filenames or -I/-X filters.
1387 1387
1388 1388 If no commit message is specified, Mercurial starts your
1389 1389 configured editor where you can enter a message. In case your
1390 1390 commit fails, you will find a backup of your message in
1391 1391 ``.hg/last-message.txt``.
1392 1392
1393 1393 The --amend flag can be used to amend the parent of the
1394 1394 working directory with a new commit that contains the changes
1395 1395 in the parent in addition to those currently reported by :hg:`status`,
1396 1396 if there are any. The old commit is stored in a backup bundle in
1397 1397 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1398 1398 on how to restore it).
1399 1399
1400 1400 Message, user and date are taken from the amended commit unless
1401 1401 specified. When a message isn't specified on the command line,
1402 1402 the editor will open with the message of the amended commit.
1403 1403
1404 1404 It is not possible to amend public changesets (see :hg:`help phases`)
1405 1405 or changesets that have children.
1406 1406
1407 1407 See :hg:`help dates` for a list of formats valid for -d/--date.
1408 1408
1409 1409 Returns 0 on success, 1 if nothing changed.
1410 1410 """
1411 1411 if opts.get('subrepos'):
1412 1412 if opts.get('amend'):
1413 1413 raise util.Abort(_('cannot amend with --subrepos'))
1414 1414 # Let --subrepos on the command line override config setting.
1415 1415 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1416 1416
1417 1417 cmdutil.checkunfinished(repo, commit=True)
1418 1418
1419 1419 branch = repo[None].branch()
1420 1420 bheads = repo.branchheads(branch)
1421 1421
1422 1422 extra = {}
1423 1423 if opts.get('close_branch'):
1424 1424 extra['close'] = 1
1425 1425
1426 1426 if not bheads:
1427 1427 raise util.Abort(_('can only close branch heads'))
1428 1428 elif opts.get('amend'):
1429 1429 if repo.parents()[0].p1().branch() != branch and \
1430 1430 repo.parents()[0].p2().branch() != branch:
1431 1431 raise util.Abort(_('can only close branch heads'))
1432 1432
1433 1433 if opts.get('amend'):
1434 1434 if ui.configbool('ui', 'commitsubrepos'):
1435 1435 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1436 1436
1437 1437 old = repo['.']
1438 1438 if not old.mutable():
1439 1439 raise util.Abort(_('cannot amend public changesets'))
1440 1440 if len(repo[None].parents()) > 1:
1441 1441 raise util.Abort(_('cannot amend while merging'))
1442 1442 if (not obsolete._enabled) and old.children():
1443 1443 raise util.Abort(_('cannot amend changeset with children'))
1444 1444
1445 1445 # commitfunc is used only for temporary amend commit by cmdutil.amend
1446 1446 def commitfunc(ui, repo, message, match, opts):
1447 1447 return repo.commit(message,
1448 1448 opts.get('user') or old.user(),
1449 1449 opts.get('date') or old.date(),
1450 1450 match,
1451 1451 extra=extra)
1452 1452
1453 1453 current = repo._bookmarkcurrent
1454 1454 marks = old.bookmarks()
1455 1455 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1456 1456 if node == old.node():
1457 1457 ui.status(_("nothing changed\n"))
1458 1458 return 1
1459 1459 elif marks:
1460 1460 ui.debug('moving bookmarks %r from %s to %s\n' %
1461 1461 (marks, old.hex(), hex(node)))
1462 1462 newmarks = repo._bookmarks
1463 1463 for bm in marks:
1464 1464 newmarks[bm] = node
1465 1465 if bm == current:
1466 1466 bookmarks.setcurrent(repo, bm)
1467 1467 newmarks.write()
1468 1468 else:
1469 1469 def commitfunc(ui, repo, message, match, opts):
1470 1470 backup = ui.backupconfig('phases', 'new-commit')
1471 1471 baseui = repo.baseui
1472 1472 basebackup = baseui.backupconfig('phases', 'new-commit')
1473 1473 try:
1474 1474 if opts.get('secret'):
1475 1475 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1476 1476 # Propagate to subrepos
1477 1477 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1478 1478
1479 1479 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1480 1480 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1481 1481 return repo.commit(message, opts.get('user'), opts.get('date'),
1482 1482 match,
1483 1483 editor=editor,
1484 1484 extra=extra)
1485 1485 finally:
1486 1486 ui.restoreconfig(backup)
1487 1487 repo.baseui.restoreconfig(basebackup)
1488 1488
1489 1489
1490 1490 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1491 1491
1492 1492 if not node:
1493 1493 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1494 1494 if stat[3]:
1495 1495 ui.status(_("nothing changed (%d missing files, see "
1496 1496 "'hg status')\n") % len(stat[3]))
1497 1497 else:
1498 1498 ui.status(_("nothing changed\n"))
1499 1499 return 1
1500 1500
1501 1501 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1502 1502
1503 1503 @command('config|showconfig|debugconfig',
1504 1504 [('u', 'untrusted', None, _('show untrusted configuration options')),
1505 1505 ('e', 'edit', None, _('edit user config')),
1506 1506 ('l', 'local', None, _('edit repository config')),
1507 1507 ('g', 'global', None, _('edit global config'))],
1508 1508 _('[-u] [NAME]...'),
1509 1509 optionalrepo=True)
1510 1510 def config(ui, repo, *values, **opts):
1511 1511 """show combined config settings from all hgrc files
1512 1512
1513 1513 With no arguments, print names and values of all config items.
1514 1514
1515 1515 With one argument of the form section.name, print just the value
1516 1516 of that config item.
1517 1517
1518 1518 With multiple arguments, print names and values of all config
1519 1519 items with matching section names.
1520 1520
1521 1521 With --edit, start an editor on the user-level config file. With
1522 1522 --global, edit the system-wide config file. With --local, edit the
1523 1523 repository-level config file.
1524 1524
1525 1525 With --debug, the source (filename and line number) is printed
1526 1526 for each config item.
1527 1527
1528 1528 See :hg:`help config` for more information about config files.
1529 1529
1530 1530 Returns 0 on success, 1 if NAME does not exist.
1531 1531
1532 1532 """
1533 1533
1534 1534 if opts.get('edit') or opts.get('local') or opts.get('global'):
1535 1535 if opts.get('local') and opts.get('global'):
1536 1536 raise util.Abort(_("can't use --local and --global together"))
1537 1537
1538 1538 if opts.get('local'):
1539 1539 if not repo:
1540 1540 raise util.Abort(_("can't use --local outside a repository"))
1541 1541 paths = [repo.join('hgrc')]
1542 1542 elif opts.get('global'):
1543 1543 paths = scmutil.systemrcpath()
1544 1544 else:
1545 1545 paths = scmutil.userrcpath()
1546 1546
1547 1547 for f in paths:
1548 1548 if os.path.exists(f):
1549 1549 break
1550 1550 else:
1551 1551 from ui import samplehgrcs
1552 1552
1553 1553 if opts.get('global'):
1554 1554 samplehgrc = samplehgrcs['global']
1555 1555 elif opts.get('local'):
1556 1556 samplehgrc = samplehgrcs['local']
1557 1557 else:
1558 1558 samplehgrc = samplehgrcs['user']
1559 1559
1560 1560 f = paths[0]
1561 1561 fp = open(f, "w")
1562 1562 fp.write(samplehgrc)
1563 1563 fp.close()
1564 1564
1565 1565 editor = ui.geteditor()
1566 1566 util.system("%s \"%s\"" % (editor, f),
1567 1567 onerr=util.Abort, errprefix=_("edit failed"),
1568 1568 out=ui.fout)
1569 1569 return
1570 1570
1571 1571 for f in scmutil.rcpath():
1572 1572 ui.debug('read config from: %s\n' % f)
1573 1573 untrusted = bool(opts.get('untrusted'))
1574 1574 if values:
1575 1575 sections = [v for v in values if '.' not in v]
1576 1576 items = [v for v in values if '.' in v]
1577 1577 if len(items) > 1 or items and sections:
1578 1578 raise util.Abort(_('only one config item permitted'))
1579 1579 matched = False
1580 1580 for section, name, value in ui.walkconfig(untrusted=untrusted):
1581 1581 value = str(value).replace('\n', '\\n')
1582 1582 sectname = section + '.' + name
1583 1583 if values:
1584 1584 for v in values:
1585 1585 if v == section:
1586 1586 ui.debug('%s: ' %
1587 1587 ui.configsource(section, name, untrusted))
1588 1588 ui.write('%s=%s\n' % (sectname, value))
1589 1589 matched = True
1590 1590 elif v == sectname:
1591 1591 ui.debug('%s: ' %
1592 1592 ui.configsource(section, name, untrusted))
1593 1593 ui.write(value, '\n')
1594 1594 matched = True
1595 1595 else:
1596 1596 ui.debug('%s: ' %
1597 1597 ui.configsource(section, name, untrusted))
1598 1598 ui.write('%s=%s\n' % (sectname, value))
1599 1599 matched = True
1600 1600 if matched:
1601 1601 return 0
1602 1602 return 1
1603 1603
1604 1604 @command('copy|cp',
1605 1605 [('A', 'after', None, _('record a copy that has already occurred')),
1606 1606 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1607 1607 ] + walkopts + dryrunopts,
1608 1608 _('[OPTION]... [SOURCE]... DEST'))
1609 1609 def copy(ui, repo, *pats, **opts):
1610 1610 """mark files as copied for the next commit
1611 1611
1612 1612 Mark dest as having copies of source files. If dest is a
1613 1613 directory, copies are put in that directory. If dest is a file,
1614 1614 the source must be a single file.
1615 1615
1616 1616 By default, this command copies the contents of files as they
1617 1617 exist in the working directory. If invoked with -A/--after, the
1618 1618 operation is recorded, but no copying is performed.
1619 1619
1620 1620 This command takes effect with the next commit. To undo a copy
1621 1621 before that, see :hg:`revert`.
1622 1622
1623 1623 Returns 0 on success, 1 if errors are encountered.
1624 1624 """
1625 1625 wlock = repo.wlock(False)
1626 1626 try:
1627 1627 return cmdutil.copy(ui, repo, pats, opts)
1628 1628 finally:
1629 1629 wlock.release()
1630 1630
1631 1631 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1632 1632 def debugancestor(ui, repo, *args):
1633 1633 """find the ancestor revision of two revisions in a given index"""
1634 1634 if len(args) == 3:
1635 1635 index, rev1, rev2 = args
1636 1636 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1637 1637 lookup = r.lookup
1638 1638 elif len(args) == 2:
1639 1639 if not repo:
1640 1640 raise util.Abort(_("there is no Mercurial repository here "
1641 1641 "(.hg not found)"))
1642 1642 rev1, rev2 = args
1643 1643 r = repo.changelog
1644 1644 lookup = repo.lookup
1645 1645 else:
1646 1646 raise util.Abort(_('either two or three arguments required'))
1647 1647 a = r.ancestor(lookup(rev1), lookup(rev2))
1648 1648 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1649 1649
1650 1650 @command('debugbuilddag',
1651 1651 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1652 1652 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1653 1653 ('n', 'new-file', None, _('add new file at each rev'))],
1654 1654 _('[OPTION]... [TEXT]'))
1655 1655 def debugbuilddag(ui, repo, text=None,
1656 1656 mergeable_file=False,
1657 1657 overwritten_file=False,
1658 1658 new_file=False):
1659 1659 """builds a repo with a given DAG from scratch in the current empty repo
1660 1660
1661 1661 The description of the DAG is read from stdin if not given on the
1662 1662 command line.
1663 1663
1664 1664 Elements:
1665 1665
1666 1666 - "+n" is a linear run of n nodes based on the current default parent
1667 1667 - "." is a single node based on the current default parent
1668 1668 - "$" resets the default parent to null (implied at the start);
1669 1669 otherwise the default parent is always the last node created
1670 1670 - "<p" sets the default parent to the backref p
1671 1671 - "*p" is a fork at parent p, which is a backref
1672 1672 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1673 1673 - "/p2" is a merge of the preceding node and p2
1674 1674 - ":tag" defines a local tag for the preceding node
1675 1675 - "@branch" sets the named branch for subsequent nodes
1676 1676 - "#...\\n" is a comment up to the end of the line
1677 1677
1678 1678 Whitespace between the above elements is ignored.
1679 1679
1680 1680 A backref is either
1681 1681
1682 1682 - a number n, which references the node curr-n, where curr is the current
1683 1683 node, or
1684 1684 - the name of a local tag you placed earlier using ":tag", or
1685 1685 - empty to denote the default parent.
1686 1686
1687 1687 All string valued-elements are either strictly alphanumeric, or must
1688 1688 be enclosed in double quotes ("..."), with "\\" as escape character.
1689 1689 """
1690 1690
1691 1691 if text is None:
1692 1692 ui.status(_("reading DAG from stdin\n"))
1693 1693 text = ui.fin.read()
1694 1694
1695 1695 cl = repo.changelog
1696 1696 if len(cl) > 0:
1697 1697 raise util.Abort(_('repository is not empty'))
1698 1698
1699 1699 # determine number of revs in DAG
1700 1700 total = 0
1701 1701 for type, data in dagparser.parsedag(text):
1702 1702 if type == 'n':
1703 1703 total += 1
1704 1704
1705 1705 if mergeable_file:
1706 1706 linesperrev = 2
1707 1707 # make a file with k lines per rev
1708 1708 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1709 1709 initialmergedlines.append("")
1710 1710
1711 1711 tags = []
1712 1712
1713 1713 lock = tr = None
1714 1714 try:
1715 1715 lock = repo.lock()
1716 1716 tr = repo.transaction("builddag")
1717 1717
1718 1718 at = -1
1719 1719 atbranch = 'default'
1720 1720 nodeids = []
1721 1721 id = 0
1722 1722 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1723 1723 for type, data in dagparser.parsedag(text):
1724 1724 if type == 'n':
1725 1725 ui.note(('node %s\n' % str(data)))
1726 1726 id, ps = data
1727 1727
1728 1728 files = []
1729 1729 fctxs = {}
1730 1730
1731 1731 p2 = None
1732 1732 if mergeable_file:
1733 1733 fn = "mf"
1734 1734 p1 = repo[ps[0]]
1735 1735 if len(ps) > 1:
1736 1736 p2 = repo[ps[1]]
1737 1737 pa = p1.ancestor(p2)
1738 1738 base, local, other = [x[fn].data() for x in (pa, p1,
1739 1739 p2)]
1740 1740 m3 = simplemerge.Merge3Text(base, local, other)
1741 1741 ml = [l.strip() for l in m3.merge_lines()]
1742 1742 ml.append("")
1743 1743 elif at > 0:
1744 1744 ml = p1[fn].data().split("\n")
1745 1745 else:
1746 1746 ml = initialmergedlines
1747 1747 ml[id * linesperrev] += " r%i" % id
1748 1748 mergedtext = "\n".join(ml)
1749 1749 files.append(fn)
1750 1750 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1751 1751
1752 1752 if overwritten_file:
1753 1753 fn = "of"
1754 1754 files.append(fn)
1755 1755 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1756 1756
1757 1757 if new_file:
1758 1758 fn = "nf%i" % id
1759 1759 files.append(fn)
1760 1760 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1761 1761 if len(ps) > 1:
1762 1762 if not p2:
1763 1763 p2 = repo[ps[1]]
1764 1764 for fn in p2:
1765 1765 if fn.startswith("nf"):
1766 1766 files.append(fn)
1767 1767 fctxs[fn] = p2[fn]
1768 1768
1769 1769 def fctxfn(repo, cx, path):
1770 1770 return fctxs.get(path)
1771 1771
1772 1772 if len(ps) == 0 or ps[0] < 0:
1773 1773 pars = [None, None]
1774 1774 elif len(ps) == 1:
1775 1775 pars = [nodeids[ps[0]], None]
1776 1776 else:
1777 1777 pars = [nodeids[p] for p in ps]
1778 1778 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1779 1779 date=(id, 0),
1780 1780 user="debugbuilddag",
1781 1781 extra={'branch': atbranch})
1782 1782 nodeid = repo.commitctx(cx)
1783 1783 nodeids.append(nodeid)
1784 1784 at = id
1785 1785 elif type == 'l':
1786 1786 id, name = data
1787 1787 ui.note(('tag %s\n' % name))
1788 1788 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1789 1789 elif type == 'a':
1790 1790 ui.note(('branch %s\n' % data))
1791 1791 atbranch = data
1792 1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1793 1793 tr.close()
1794 1794
1795 1795 if tags:
1796 1796 repo.opener.write("localtags", "".join(tags))
1797 1797 finally:
1798 1798 ui.progress(_('building'), None)
1799 1799 release(tr, lock)
1800 1800
1801 1801 @command('debugbundle',
1802 1802 [('a', 'all', None, _('show all details'))],
1803 1803 _('FILE'),
1804 1804 norepo=True)
1805 1805 def debugbundle(ui, bundlepath, all=None, **opts):
1806 1806 """lists the contents of a bundle"""
1807 1807 f = hg.openpath(ui, bundlepath)
1808 1808 try:
1809 1809 gen = exchange.readbundle(ui, f, bundlepath)
1810 1810 if all:
1811 1811 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1812 1812
1813 1813 def showchunks(named):
1814 1814 ui.write("\n%s\n" % named)
1815 1815 chain = None
1816 1816 while True:
1817 1817 chunkdata = gen.deltachunk(chain)
1818 1818 if not chunkdata:
1819 1819 break
1820 1820 node = chunkdata['node']
1821 1821 p1 = chunkdata['p1']
1822 1822 p2 = chunkdata['p2']
1823 1823 cs = chunkdata['cs']
1824 1824 deltabase = chunkdata['deltabase']
1825 1825 delta = chunkdata['delta']
1826 1826 ui.write("%s %s %s %s %s %s\n" %
1827 1827 (hex(node), hex(p1), hex(p2),
1828 1828 hex(cs), hex(deltabase), len(delta)))
1829 1829 chain = node
1830 1830
1831 1831 chunkdata = gen.changelogheader()
1832 1832 showchunks("changelog")
1833 1833 chunkdata = gen.manifestheader()
1834 1834 showchunks("manifest")
1835 1835 while True:
1836 1836 chunkdata = gen.filelogheader()
1837 1837 if not chunkdata:
1838 1838 break
1839 1839 fname = chunkdata['filename']
1840 1840 showchunks(fname)
1841 1841 else:
1842 1842 chunkdata = gen.changelogheader()
1843 1843 chain = None
1844 1844 while True:
1845 1845 chunkdata = gen.deltachunk(chain)
1846 1846 if not chunkdata:
1847 1847 break
1848 1848 node = chunkdata['node']
1849 1849 ui.write("%s\n" % hex(node))
1850 1850 chain = node
1851 1851 finally:
1852 1852 f.close()
1853 1853
1854 1854 @command('debugcheckstate', [], '')
1855 1855 def debugcheckstate(ui, repo):
1856 1856 """validate the correctness of the current dirstate"""
1857 1857 parent1, parent2 = repo.dirstate.parents()
1858 1858 m1 = repo[parent1].manifest()
1859 1859 m2 = repo[parent2].manifest()
1860 1860 errors = 0
1861 1861 for f in repo.dirstate:
1862 1862 state = repo.dirstate[f]
1863 1863 if state in "nr" and f not in m1:
1864 1864 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1865 1865 errors += 1
1866 1866 if state in "a" and f in m1:
1867 1867 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1868 1868 errors += 1
1869 1869 if state in "m" and f not in m1 and f not in m2:
1870 1870 ui.warn(_("%s in state %s, but not in either manifest\n") %
1871 1871 (f, state))
1872 1872 errors += 1
1873 1873 for f in m1:
1874 1874 state = repo.dirstate[f]
1875 1875 if state not in "nrm":
1876 1876 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1877 1877 errors += 1
1878 1878 if errors:
1879 1879 error = _(".hg/dirstate inconsistent with current parent's manifest")
1880 1880 raise util.Abort(error)
1881 1881
1882 1882 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1883 1883 def debugcommands(ui, cmd='', *args):
1884 1884 """list all available commands and options"""
1885 1885 for cmd, vals in sorted(table.iteritems()):
1886 1886 cmd = cmd.split('|')[0].strip('^')
1887 1887 opts = ', '.join([i[1] for i in vals[1]])
1888 1888 ui.write('%s: %s\n' % (cmd, opts))
1889 1889
1890 1890 @command('debugcomplete',
1891 1891 [('o', 'options', None, _('show the command options'))],
1892 1892 _('[-o] CMD'),
1893 1893 norepo=True)
1894 1894 def debugcomplete(ui, cmd='', **opts):
1895 1895 """returns the completion list associated with the given command"""
1896 1896
1897 1897 if opts.get('options'):
1898 1898 options = []
1899 1899 otables = [globalopts]
1900 1900 if cmd:
1901 1901 aliases, entry = cmdutil.findcmd(cmd, table, False)
1902 1902 otables.append(entry[1])
1903 1903 for t in otables:
1904 1904 for o in t:
1905 1905 if "(DEPRECATED)" in o[3]:
1906 1906 continue
1907 1907 if o[0]:
1908 1908 options.append('-%s' % o[0])
1909 1909 options.append('--%s' % o[1])
1910 1910 ui.write("%s\n" % "\n".join(options))
1911 1911 return
1912 1912
1913 1913 cmdlist = cmdutil.findpossible(cmd, table)
1914 1914 if ui.verbose:
1915 1915 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1916 1916 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1917 1917
1918 1918 @command('debugdag',
1919 1919 [('t', 'tags', None, _('use tags as labels')),
1920 1920 ('b', 'branches', None, _('annotate with branch names')),
1921 1921 ('', 'dots', None, _('use dots for runs')),
1922 1922 ('s', 'spaces', None, _('separate elements by spaces'))],
1923 1923 _('[OPTION]... [FILE [REV]...]'),
1924 1924 optionalrepo=True)
1925 1925 def debugdag(ui, repo, file_=None, *revs, **opts):
1926 1926 """format the changelog or an index DAG as a concise textual description
1927 1927
1928 1928 If you pass a revlog index, the revlog's DAG is emitted. If you list
1929 1929 revision numbers, they get labeled in the output as rN.
1930 1930
1931 1931 Otherwise, the changelog DAG of the current repo is emitted.
1932 1932 """
1933 1933 spaces = opts.get('spaces')
1934 1934 dots = opts.get('dots')
1935 1935 if file_:
1936 1936 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1937 1937 revs = set((int(r) for r in revs))
1938 1938 def events():
1939 1939 for r in rlog:
1940 1940 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1941 1941 if p != -1))
1942 1942 if r in revs:
1943 1943 yield 'l', (r, "r%i" % r)
1944 1944 elif repo:
1945 1945 cl = repo.changelog
1946 1946 tags = opts.get('tags')
1947 1947 branches = opts.get('branches')
1948 1948 if tags:
1949 1949 labels = {}
1950 1950 for l, n in repo.tags().items():
1951 1951 labels.setdefault(cl.rev(n), []).append(l)
1952 1952 def events():
1953 1953 b = "default"
1954 1954 for r in cl:
1955 1955 if branches:
1956 1956 newb = cl.read(cl.node(r))[5]['branch']
1957 1957 if newb != b:
1958 1958 yield 'a', newb
1959 1959 b = newb
1960 1960 yield 'n', (r, list(p for p in cl.parentrevs(r)
1961 1961 if p != -1))
1962 1962 if tags:
1963 1963 ls = labels.get(r)
1964 1964 if ls:
1965 1965 for l in ls:
1966 1966 yield 'l', (r, l)
1967 1967 else:
1968 1968 raise util.Abort(_('need repo for changelog dag'))
1969 1969
1970 1970 for line in dagparser.dagtextlines(events(),
1971 1971 addspaces=spaces,
1972 1972 wraplabels=True,
1973 1973 wrapannotations=True,
1974 1974 wrapnonlinear=dots,
1975 1975 usedots=dots,
1976 1976 maxlinewidth=70):
1977 1977 ui.write(line)
1978 1978 ui.write("\n")
1979 1979
1980 1980 @command('debugdata',
1981 1981 [('c', 'changelog', False, _('open changelog')),
1982 1982 ('m', 'manifest', False, _('open manifest'))],
1983 1983 _('-c|-m|FILE REV'))
1984 1984 def debugdata(ui, repo, file_, rev=None, **opts):
1985 1985 """dump the contents of a data file revision"""
1986 1986 if opts.get('changelog') or opts.get('manifest'):
1987 1987 file_, rev = None, file_
1988 1988 elif rev is None:
1989 1989 raise error.CommandError('debugdata', _('invalid arguments'))
1990 1990 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1991 1991 try:
1992 1992 ui.write(r.revision(r.lookup(rev)))
1993 1993 except KeyError:
1994 1994 raise util.Abort(_('invalid revision identifier %s') % rev)
1995 1995
1996 1996 @command('debugdate',
1997 1997 [('e', 'extended', None, _('try extended date formats'))],
1998 1998 _('[-e] DATE [RANGE]'),
1999 1999 norepo=True, optionalrepo=True)
2000 2000 def debugdate(ui, date, range=None, **opts):
2001 2001 """parse and display a date"""
2002 2002 if opts["extended"]:
2003 2003 d = util.parsedate(date, util.extendeddateformats)
2004 2004 else:
2005 2005 d = util.parsedate(date)
2006 2006 ui.write(("internal: %s %s\n") % d)
2007 2007 ui.write(("standard: %s\n") % util.datestr(d))
2008 2008 if range:
2009 2009 m = util.matchdate(range)
2010 2010 ui.write(("match: %s\n") % m(d[0]))
2011 2011
2012 2012 @command('debugdiscovery',
2013 2013 [('', 'old', None, _('use old-style discovery')),
2014 2014 ('', 'nonheads', None,
2015 2015 _('use old-style discovery with non-heads included')),
2016 2016 ] + remoteopts,
2017 2017 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2018 2018 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2019 2019 """runs the changeset discovery protocol in isolation"""
2020 2020 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2021 2021 opts.get('branch'))
2022 2022 remote = hg.peer(repo, opts, remoteurl)
2023 2023 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2024 2024
2025 2025 # make sure tests are repeatable
2026 2026 random.seed(12323)
2027 2027
2028 2028 def doit(localheads, remoteheads, remote=remote):
2029 2029 if opts.get('old'):
2030 2030 if localheads:
2031 2031 raise util.Abort('cannot use localheads with old style '
2032 2032 'discovery')
2033 2033 if not util.safehasattr(remote, 'branches'):
2034 2034 # enable in-client legacy support
2035 2035 remote = localrepo.locallegacypeer(remote.local())
2036 2036 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2037 2037 force=True)
2038 2038 common = set(common)
2039 2039 if not opts.get('nonheads'):
2040 2040 ui.write(("unpruned common: %s\n") %
2041 2041 " ".join(sorted(short(n) for n in common)))
2042 2042 dag = dagutil.revlogdag(repo.changelog)
2043 2043 all = dag.ancestorset(dag.internalizeall(common))
2044 2044 common = dag.externalizeall(dag.headsetofconnecteds(all))
2045 2045 else:
2046 2046 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2047 2047 common = set(common)
2048 2048 rheads = set(hds)
2049 2049 lheads = set(repo.heads())
2050 2050 ui.write(("common heads: %s\n") %
2051 2051 " ".join(sorted(short(n) for n in common)))
2052 2052 if lheads <= common:
2053 2053 ui.write(("local is subset\n"))
2054 2054 elif rheads <= common:
2055 2055 ui.write(("remote is subset\n"))
2056 2056
2057 2057 serverlogs = opts.get('serverlog')
2058 2058 if serverlogs:
2059 2059 for filename in serverlogs:
2060 2060 logfile = open(filename, 'r')
2061 2061 try:
2062 2062 line = logfile.readline()
2063 2063 while line:
2064 2064 parts = line.strip().split(';')
2065 2065 op = parts[1]
2066 2066 if op == 'cg':
2067 2067 pass
2068 2068 elif op == 'cgss':
2069 2069 doit(parts[2].split(' '), parts[3].split(' '))
2070 2070 elif op == 'unb':
2071 2071 doit(parts[3].split(' '), parts[2].split(' '))
2072 2072 line = logfile.readline()
2073 2073 finally:
2074 2074 logfile.close()
2075 2075
2076 2076 else:
2077 2077 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2078 2078 opts.get('remote_head'))
2079 2079 localrevs = opts.get('local_head')
2080 2080 doit(localrevs, remoterevs)
2081 2081
2082 2082 @command('debugfileset',
2083 2083 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2084 2084 _('[-r REV] FILESPEC'))
2085 2085 def debugfileset(ui, repo, expr, **opts):
2086 2086 '''parse and apply a fileset specification'''
2087 2087 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2088 2088 if ui.verbose:
2089 2089 tree = fileset.parse(expr)[0]
2090 2090 ui.note(tree, "\n")
2091 2091
2092 2092 for f in ctx.getfileset(expr):
2093 2093 ui.write("%s\n" % f)
2094 2094
2095 2095 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2096 2096 def debugfsinfo(ui, path="."):
2097 2097 """show information detected about current filesystem"""
2098 2098 util.writefile('.debugfsinfo', '')
2099 2099 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2100 2100 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2101 2101 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2102 2102 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2103 2103 and 'yes' or 'no'))
2104 2104 os.unlink('.debugfsinfo')
2105 2105
2106 2106 @command('debuggetbundle',
2107 2107 [('H', 'head', [], _('id of head node'), _('ID')),
2108 2108 ('C', 'common', [], _('id of common node'), _('ID')),
2109 2109 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2110 2110 _('REPO FILE [-H|-C ID]...'),
2111 2111 norepo=True)
2112 2112 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2113 2113 """retrieves a bundle from a repo
2114 2114
2115 2115 Every ID must be a full-length hex node id string. Saves the bundle to the
2116 2116 given file.
2117 2117 """
2118 2118 repo = hg.peer(ui, opts, repopath)
2119 2119 if not repo.capable('getbundle'):
2120 2120 raise util.Abort("getbundle() not supported by target repository")
2121 2121 args = {}
2122 2122 if common:
2123 2123 args['common'] = [bin(s) for s in common]
2124 2124 if head:
2125 2125 args['heads'] = [bin(s) for s in head]
2126 2126 # TODO: get desired bundlecaps from command line.
2127 2127 args['bundlecaps'] = None
2128 2128 bundle = repo.getbundle('debug', **args)
2129 2129
2130 2130 bundletype = opts.get('type', 'bzip2').lower()
2131 2131 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2132 2132 bundletype = btypes.get(bundletype)
2133 2133 if bundletype not in changegroup.bundletypes:
2134 2134 raise util.Abort(_('unknown bundle type specified with --type'))
2135 2135 changegroup.writebundle(bundle, bundlepath, bundletype)
2136 2136
2137 2137 @command('debugignore', [], '')
2138 2138 def debugignore(ui, repo, *values, **opts):
2139 2139 """display the combined ignore pattern"""
2140 2140 ignore = repo.dirstate._ignore
2141 2141 includepat = getattr(ignore, 'includepat', None)
2142 2142 if includepat is not None:
2143 2143 ui.write("%s\n" % includepat)
2144 2144 else:
2145 2145 raise util.Abort(_("no ignore patterns found"))
2146 2146
2147 2147 @command('debugindex',
2148 2148 [('c', 'changelog', False, _('open changelog')),
2149 2149 ('m', 'manifest', False, _('open manifest')),
2150 2150 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2151 2151 _('[-f FORMAT] -c|-m|FILE'),
2152 2152 optionalrepo=True)
2153 2153 def debugindex(ui, repo, file_=None, **opts):
2154 2154 """dump the contents of an index file"""
2155 2155 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2156 2156 format = opts.get('format', 0)
2157 2157 if format not in (0, 1):
2158 2158 raise util.Abort(_("unknown format %d") % format)
2159 2159
2160 2160 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2161 2161 if generaldelta:
2162 2162 basehdr = ' delta'
2163 2163 else:
2164 2164 basehdr = ' base'
2165 2165
2166 2166 if format == 0:
2167 2167 ui.write(" rev offset length " + basehdr + " linkrev"
2168 2168 " nodeid p1 p2\n")
2169 2169 elif format == 1:
2170 2170 ui.write(" rev flag offset length"
2171 2171 " size " + basehdr + " link p1 p2"
2172 2172 " nodeid\n")
2173 2173
2174 2174 for i in r:
2175 2175 node = r.node(i)
2176 2176 if generaldelta:
2177 2177 base = r.deltaparent(i)
2178 2178 else:
2179 2179 base = r.chainbase(i)
2180 2180 if format == 0:
2181 2181 try:
2182 2182 pp = r.parents(node)
2183 2183 except Exception:
2184 2184 pp = [nullid, nullid]
2185 2185 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2186 2186 i, r.start(i), r.length(i), base, r.linkrev(i),
2187 2187 short(node), short(pp[0]), short(pp[1])))
2188 2188 elif format == 1:
2189 2189 pr = r.parentrevs(i)
2190 2190 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2191 2191 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2192 2192 base, r.linkrev(i), pr[0], pr[1], short(node)))
2193 2193
2194 2194 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2195 2195 def debugindexdot(ui, repo, file_):
2196 2196 """dump an index DAG as a graphviz dot file"""
2197 2197 r = None
2198 2198 if repo:
2199 2199 filelog = repo.file(file_)
2200 2200 if len(filelog):
2201 2201 r = filelog
2202 2202 if not r:
2203 2203 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2204 2204 ui.write(("digraph G {\n"))
2205 2205 for i in r:
2206 2206 node = r.node(i)
2207 2207 pp = r.parents(node)
2208 2208 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2209 2209 if pp[1] != nullid:
2210 2210 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2211 2211 ui.write("}\n")
2212 2212
2213 2213 @command('debuginstall', [], '', norepo=True)
2214 2214 def debuginstall(ui):
2215 2215 '''test Mercurial installation
2216 2216
2217 2217 Returns 0 on success.
2218 2218 '''
2219 2219
2220 2220 def writetemp(contents):
2221 2221 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2222 2222 f = os.fdopen(fd, "wb")
2223 2223 f.write(contents)
2224 2224 f.close()
2225 2225 return name
2226 2226
2227 2227 problems = 0
2228 2228
2229 2229 # encoding
2230 2230 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2231 2231 try:
2232 2232 encoding.fromlocal("test")
2233 2233 except util.Abort, inst:
2234 2234 ui.write(" %s\n" % inst)
2235 2235 ui.write(_(" (check that your locale is properly set)\n"))
2236 2236 problems += 1
2237 2237
2238 2238 # Python
2239 2239 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2240 2240 ui.status(_("checking Python version (%s)\n")
2241 2241 % ("%s.%s.%s" % sys.version_info[:3]))
2242 2242 ui.status(_("checking Python lib (%s)...\n")
2243 2243 % os.path.dirname(os.__file__))
2244 2244
2245 2245 # compiled modules
2246 2246 ui.status(_("checking installed modules (%s)...\n")
2247 2247 % os.path.dirname(__file__))
2248 2248 try:
2249 2249 import bdiff, mpatch, base85, osutil
2250 2250 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2251 2251 except Exception, inst:
2252 2252 ui.write(" %s\n" % inst)
2253 2253 ui.write(_(" One or more extensions could not be found"))
2254 2254 ui.write(_(" (check that you compiled the extensions)\n"))
2255 2255 problems += 1
2256 2256
2257 2257 # templates
2258 2258 import templater
2259 2259 p = templater.templatepath()
2260 2260 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2261 2261 if p:
2262 2262 m = templater.templatepath("map-cmdline.default")
2263 2263 if m:
2264 2264 # template found, check if it is working
2265 2265 try:
2266 2266 templater.templater(m)
2267 2267 except Exception, inst:
2268 2268 ui.write(" %s\n" % inst)
2269 2269 p = None
2270 2270 else:
2271 2271 ui.write(_(" template 'default' not found\n"))
2272 2272 p = None
2273 2273 else:
2274 2274 ui.write(_(" no template directories found\n"))
2275 2275 if not p:
2276 2276 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2277 2277 problems += 1
2278 2278
2279 2279 # editor
2280 2280 ui.status(_("checking commit editor...\n"))
2281 2281 editor = ui.geteditor()
2282 2282 cmdpath = util.findexe(shlex.split(editor)[0])
2283 2283 if not cmdpath:
2284 2284 if editor == 'vi':
2285 2285 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2286 2286 ui.write(_(" (specify a commit editor in your configuration"
2287 2287 " file)\n"))
2288 2288 else:
2289 2289 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2290 2290 ui.write(_(" (specify a commit editor in your configuration"
2291 2291 " file)\n"))
2292 2292 problems += 1
2293 2293
2294 2294 # check username
2295 2295 ui.status(_("checking username...\n"))
2296 2296 try:
2297 2297 ui.username()
2298 2298 except util.Abort, e:
2299 2299 ui.write(" %s\n" % e)
2300 2300 ui.write(_(" (specify a username in your configuration file)\n"))
2301 2301 problems += 1
2302 2302
2303 2303 if not problems:
2304 2304 ui.status(_("no problems detected\n"))
2305 2305 else:
2306 2306 ui.write(_("%s problems detected,"
2307 2307 " please check your install!\n") % problems)
2308 2308
2309 2309 return problems
2310 2310
2311 2311 @command('debugknown', [], _('REPO ID...'), norepo=True)
2312 2312 def debugknown(ui, repopath, *ids, **opts):
2313 2313 """test whether node ids are known to a repo
2314 2314
2315 2315 Every ID must be a full-length hex node id string. Returns a list of 0s
2316 2316 and 1s indicating unknown/known.
2317 2317 """
2318 2318 repo = hg.peer(ui, opts, repopath)
2319 2319 if not repo.capable('known'):
2320 2320 raise util.Abort("known() not supported by target repository")
2321 2321 flags = repo.known([bin(s) for s in ids])
2322 2322 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2323 2323
2324 2324 @command('debuglabelcomplete', [], _('LABEL...'))
2325 2325 def debuglabelcomplete(ui, repo, *args):
2326 2326 '''complete "labels" - tags, open branch names, bookmark names'''
2327 2327
2328 2328 labels = set()
2329 2329 labels.update(t[0] for t in repo.tagslist())
2330 2330 labels.update(repo._bookmarks.keys())
2331 2331 labels.update(tag for (tag, heads, tip, closed)
2332 2332 in repo.branchmap().iterbranches() if not closed)
2333 2333 completions = set()
2334 2334 if not args:
2335 2335 args = ['']
2336 2336 for a in args:
2337 2337 completions.update(l for l in labels if l.startswith(a))
2338 2338 ui.write('\n'.join(sorted(completions)))
2339 2339 ui.write('\n')
2340 2340
2341 2341 @command('debuglocks',
2342 2342 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2343 2343 ('W', 'force-wlock', None,
2344 2344 _('free the working state lock (DANGEROUS)'))],
2345 2345 _(''))
2346 2346 def debuglocks(ui, repo, **opts):
2347 2347 """show or modify state of locks
2348 2348
2349 2349 By default, this command will show which locks are held. This
2350 2350 includes the user and process holding the lock, the amount of time
2351 2351 the lock has been held, and the machine name where the process is
2352 2352 running if it's not local.
2353 2353
2354 2354 Locks protect the integrity of Mercurial's data, so should be
2355 2355 treated with care. System crashes or other interruptions may cause
2356 2356 locks to not be properly released, though Mercurial will usually
2357 2357 detect and remove such stale locks automatically.
2358 2358
2359 2359 However, detecting stale locks may not always be possible (for
2360 2360 instance, on a shared filesystem). Removing locks may also be
2361 2361 blocked by filesystem permissions.
2362 2362
2363 2363 Returns 0 if no locks are held.
2364 2364
2365 2365 """
2366 2366
2367 2367 if opts.get('force_lock'):
2368 2368 repo.svfs.unlink('lock')
2369 2369 if opts.get('force_wlock'):
2370 2370 repo.vfs.unlink('wlock')
2371 2371 if opts.get('force_lock') or opts.get('force_lock'):
2372 2372 return 0
2373 2373
2374 2374 now = time.time()
2375 2375 held = 0
2376 2376
2377 2377 def report(vfs, name, method):
2378 2378 # this causes stale locks to get reaped for more accurate reporting
2379 2379 try:
2380 2380 l = method(False)
2381 2381 except error.LockHeld:
2382 2382 l = None
2383 2383
2384 2384 if l:
2385 2385 l.release()
2386 2386 else:
2387 2387 try:
2388 2388 stat = repo.svfs.lstat(name)
2389 2389 age = now - stat.st_mtime
2390 2390 user = util.username(stat.st_uid)
2391 2391 locker = vfs.readlock(name)
2392 2392 if ":" in locker:
2393 2393 host, pid = locker.split(':')
2394 2394 if host == socket.gethostname():
2395 2395 locker = 'user %s, process %s' % (user, pid)
2396 2396 else:
2397 2397 locker = 'user %s, process %s, host %s' \
2398 2398 % (user, pid, host)
2399 2399 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2400 2400 return 1
2401 2401 except OSError, e:
2402 2402 if e.errno != errno.ENOENT:
2403 2403 raise
2404 2404
2405 2405 ui.write("%-6s free\n" % (name + ":"))
2406 2406 return 0
2407 2407
2408 2408 held += report(repo.svfs, "lock", repo.lock)
2409 2409 held += report(repo.vfs, "wlock", repo.wlock)
2410 2410
2411 2411 return held
2412 2412
2413 2413 @command('debugobsolete',
2414 2414 [('', 'flags', 0, _('markers flag')),
2415 2415 ('', 'record-parents', False,
2416 2416 _('record parent information for the precursor')),
2417 2417 ('r', 'rev', [], _('display markers relevant to REV')),
2418 2418 ] + commitopts2,
2419 2419 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2420 2420 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2421 2421 """create arbitrary obsolete marker
2422 2422
2423 2423 With no arguments, displays the list of obsolescence markers."""
2424 2424
2425 2425 def parsenodeid(s):
2426 2426 try:
2427 2427 # We do not use revsingle/revrange functions here to accept
2428 2428 # arbitrary node identifiers, possibly not present in the
2429 2429 # local repository.
2430 2430 n = bin(s)
2431 2431 if len(n) != len(nullid):
2432 2432 raise TypeError()
2433 2433 return n
2434 2434 except TypeError:
2435 2435 raise util.Abort('changeset references must be full hexadecimal '
2436 2436 'node identifiers')
2437 2437
2438 2438 if precursor is not None:
2439 2439 if opts['rev']:
2440 2440 raise util.Abort('cannot select revision when creating marker')
2441 2441 metadata = {}
2442 2442 metadata['user'] = opts['user'] or ui.username()
2443 2443 succs = tuple(parsenodeid(succ) for succ in successors)
2444 2444 l = repo.lock()
2445 2445 try:
2446 2446 tr = repo.transaction('debugobsolete')
2447 2447 try:
2448 2448 try:
2449 2449 date = opts.get('date')
2450 2450 if date:
2451 2451 date = util.parsedate(date)
2452 2452 else:
2453 2453 date = None
2454 2454 prec = parsenodeid(precursor)
2455 2455 parents = None
2456 2456 if opts['record_parents']:
2457 2457 if prec not in repo.unfiltered():
2458 2458 raise util.Abort('cannot used --record-parents on '
2459 2459 'unknown changesets')
2460 2460 parents = repo.unfiltered()[prec].parents()
2461 2461 parents = tuple(p.node() for p in parents)
2462 2462 repo.obsstore.create(tr, prec, succs, opts['flags'],
2463 2463 parents=parents, date=date,
2464 2464 metadata=metadata)
2465 2465 tr.close()
2466 2466 except ValueError, exc:
2467 2467 raise util.Abort(_('bad obsmarker input: %s') % exc)
2468 2468 finally:
2469 2469 tr.release()
2470 2470 finally:
2471 2471 l.release()
2472 2472 else:
2473 2473 if opts['rev']:
2474 2474 revs = scmutil.revrange(repo, opts['rev'])
2475 2475 nodes = [repo[r].node() for r in revs]
2476 2476 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2477 2477 markers.sort(key=lambda x: x._data)
2478 2478 else:
2479 2479 markers = obsolete.getmarkers(repo)
2480 2480
2481 2481 for m in markers:
2482 2482 cmdutil.showmarker(ui, m)
2483 2483
2484 2484 @command('debugpathcomplete',
2485 2485 [('f', 'full', None, _('complete an entire path')),
2486 2486 ('n', 'normal', None, _('show only normal files')),
2487 2487 ('a', 'added', None, _('show only added files')),
2488 2488 ('r', 'removed', None, _('show only removed files'))],
2489 2489 _('FILESPEC...'))
2490 2490 def debugpathcomplete(ui, repo, *specs, **opts):
2491 2491 '''complete part or all of a tracked path
2492 2492
2493 2493 This command supports shells that offer path name completion. It
2494 2494 currently completes only files already known to the dirstate.
2495 2495
2496 2496 Completion extends only to the next path segment unless
2497 2497 --full is specified, in which case entire paths are used.'''
2498 2498
2499 2499 def complete(path, acceptable):
2500 2500 dirstate = repo.dirstate
2501 2501 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2502 2502 rootdir = repo.root + os.sep
2503 2503 if spec != repo.root and not spec.startswith(rootdir):
2504 2504 return [], []
2505 2505 if os.path.isdir(spec):
2506 2506 spec += '/'
2507 2507 spec = spec[len(rootdir):]
2508 2508 fixpaths = os.sep != '/'
2509 2509 if fixpaths:
2510 2510 spec = spec.replace(os.sep, '/')
2511 2511 speclen = len(spec)
2512 2512 fullpaths = opts['full']
2513 2513 files, dirs = set(), set()
2514 2514 adddir, addfile = dirs.add, files.add
2515 2515 for f, st in dirstate.iteritems():
2516 2516 if f.startswith(spec) and st[0] in acceptable:
2517 2517 if fixpaths:
2518 2518 f = f.replace('/', os.sep)
2519 2519 if fullpaths:
2520 2520 addfile(f)
2521 2521 continue
2522 2522 s = f.find(os.sep, speclen)
2523 2523 if s >= 0:
2524 2524 adddir(f[:s])
2525 2525 else:
2526 2526 addfile(f)
2527 2527 return files, dirs
2528 2528
2529 2529 acceptable = ''
2530 2530 if opts['normal']:
2531 2531 acceptable += 'nm'
2532 2532 if opts['added']:
2533 2533 acceptable += 'a'
2534 2534 if opts['removed']:
2535 2535 acceptable += 'r'
2536 2536 cwd = repo.getcwd()
2537 2537 if not specs:
2538 2538 specs = ['.']
2539 2539
2540 2540 files, dirs = set(), set()
2541 2541 for spec in specs:
2542 2542 f, d = complete(spec, acceptable or 'nmar')
2543 2543 files.update(f)
2544 2544 dirs.update(d)
2545 2545 files.update(dirs)
2546 2546 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2547 2547 ui.write('\n')
2548 2548
2549 2549 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2550 2550 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2551 2551 '''access the pushkey key/value protocol
2552 2552
2553 2553 With two args, list the keys in the given namespace.
2554 2554
2555 2555 With five args, set a key to new if it currently is set to old.
2556 2556 Reports success or failure.
2557 2557 '''
2558 2558
2559 2559 target = hg.peer(ui, {}, repopath)
2560 2560 if keyinfo:
2561 2561 key, old, new = keyinfo
2562 2562 r = target.pushkey(namespace, key, old, new)
2563 2563 ui.status(str(r) + '\n')
2564 2564 return not r
2565 2565 else:
2566 2566 for k, v in sorted(target.listkeys(namespace).iteritems()):
2567 2567 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2568 2568 v.encode('string-escape')))
2569 2569
2570 2570 @command('debugpvec', [], _('A B'))
2571 2571 def debugpvec(ui, repo, a, b=None):
2572 2572 ca = scmutil.revsingle(repo, a)
2573 2573 cb = scmutil.revsingle(repo, b)
2574 2574 pa = pvec.ctxpvec(ca)
2575 2575 pb = pvec.ctxpvec(cb)
2576 2576 if pa == pb:
2577 2577 rel = "="
2578 2578 elif pa > pb:
2579 2579 rel = ">"
2580 2580 elif pa < pb:
2581 2581 rel = "<"
2582 2582 elif pa | pb:
2583 2583 rel = "|"
2584 2584 ui.write(_("a: %s\n") % pa)
2585 2585 ui.write(_("b: %s\n") % pb)
2586 2586 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2587 2587 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2588 2588 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2589 2589 pa.distance(pb), rel))
2590 2590
2591 2591 @command('debugrebuilddirstate|debugrebuildstate',
2592 2592 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2593 2593 _('[-r REV]'))
2594 2594 def debugrebuilddirstate(ui, repo, rev):
2595 2595 """rebuild the dirstate as it would look like for the given revision
2596 2596
2597 2597 If no revision is specified the first current parent will be used.
2598 2598
2599 2599 The dirstate will be set to the files of the given revision.
2600 2600 The actual working directory content or existing dirstate
2601 2601 information such as adds or removes is not considered.
2602 2602
2603 2603 One use of this command is to make the next :hg:`status` invocation
2604 2604 check the actual file content.
2605 2605 """
2606 2606 ctx = scmutil.revsingle(repo, rev)
2607 2607 wlock = repo.wlock()
2608 2608 try:
2609 2609 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2610 2610 finally:
2611 2611 wlock.release()
2612 2612
2613 2613 @command('debugrename',
2614 2614 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2615 2615 _('[-r REV] FILE'))
2616 2616 def debugrename(ui, repo, file1, *pats, **opts):
2617 2617 """dump rename information"""
2618 2618
2619 2619 ctx = scmutil.revsingle(repo, opts.get('rev'))
2620 2620 m = scmutil.match(ctx, (file1,) + pats, opts)
2621 2621 for abs in ctx.walk(m):
2622 2622 fctx = ctx[abs]
2623 2623 o = fctx.filelog().renamed(fctx.filenode())
2624 2624 rel = m.rel(abs)
2625 2625 if o:
2626 2626 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2627 2627 else:
2628 2628 ui.write(_("%s not renamed\n") % rel)
2629 2629
2630 2630 @command('debugrevlog',
2631 2631 [('c', 'changelog', False, _('open changelog')),
2632 2632 ('m', 'manifest', False, _('open manifest')),
2633 2633 ('d', 'dump', False, _('dump index data'))],
2634 2634 _('-c|-m|FILE'),
2635 2635 optionalrepo=True)
2636 2636 def debugrevlog(ui, repo, file_=None, **opts):
2637 2637 """show data and statistics about a revlog"""
2638 2638 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2639 2639
2640 2640 if opts.get("dump"):
2641 2641 numrevs = len(r)
2642 2642 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2643 2643 " rawsize totalsize compression heads chainlen\n")
2644 2644 ts = 0
2645 2645 heads = set()
2646 2646 rindex = r.index
2647 2647
2648 2648 def chainbaseandlen(rev):
2649 2649 clen = 0
2650 2650 base = rindex[rev][3]
2651 2651 while base != rev:
2652 2652 clen += 1
2653 2653 rev = base
2654 2654 base = rindex[rev][3]
2655 2655 return base, clen
2656 2656
2657 2657 for rev in xrange(numrevs):
2658 2658 dbase = r.deltaparent(rev)
2659 2659 if dbase == -1:
2660 2660 dbase = rev
2661 2661 cbase, clen = chainbaseandlen(rev)
2662 2662 p1, p2 = r.parentrevs(rev)
2663 2663 rs = r.rawsize(rev)
2664 2664 ts = ts + rs
2665 2665 heads -= set(r.parentrevs(rev))
2666 2666 heads.add(rev)
2667 2667 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2668 2668 "%11d %5d %8d\n" %
2669 2669 (rev, p1, p2, r.start(rev), r.end(rev),
2670 2670 r.start(dbase), r.start(cbase),
2671 2671 r.start(p1), r.start(p2),
2672 2672 rs, ts, ts / r.end(rev), len(heads), clen))
2673 2673 return 0
2674 2674
2675 2675 v = r.version
2676 2676 format = v & 0xFFFF
2677 2677 flags = []
2678 2678 gdelta = False
2679 2679 if v & revlog.REVLOGNGINLINEDATA:
2680 2680 flags.append('inline')
2681 2681 if v & revlog.REVLOGGENERALDELTA:
2682 2682 gdelta = True
2683 2683 flags.append('generaldelta')
2684 2684 if not flags:
2685 2685 flags = ['(none)']
2686 2686
2687 2687 nummerges = 0
2688 2688 numfull = 0
2689 2689 numprev = 0
2690 2690 nump1 = 0
2691 2691 nump2 = 0
2692 2692 numother = 0
2693 2693 nump1prev = 0
2694 2694 nump2prev = 0
2695 2695 chainlengths = []
2696 2696
2697 2697 datasize = [None, 0, 0L]
2698 2698 fullsize = [None, 0, 0L]
2699 2699 deltasize = [None, 0, 0L]
2700 2700
2701 2701 def addsize(size, l):
2702 2702 if l[0] is None or size < l[0]:
2703 2703 l[0] = size
2704 2704 if size > l[1]:
2705 2705 l[1] = size
2706 2706 l[2] += size
2707 2707
2708 2708 numrevs = len(r)
2709 2709 for rev in xrange(numrevs):
2710 2710 p1, p2 = r.parentrevs(rev)
2711 2711 delta = r.deltaparent(rev)
2712 2712 if format > 0:
2713 2713 addsize(r.rawsize(rev), datasize)
2714 2714 if p2 != nullrev:
2715 2715 nummerges += 1
2716 2716 size = r.length(rev)
2717 2717 if delta == nullrev:
2718 2718 chainlengths.append(0)
2719 2719 numfull += 1
2720 2720 addsize(size, fullsize)
2721 2721 else:
2722 2722 chainlengths.append(chainlengths[delta] + 1)
2723 2723 addsize(size, deltasize)
2724 2724 if delta == rev - 1:
2725 2725 numprev += 1
2726 2726 if delta == p1:
2727 2727 nump1prev += 1
2728 2728 elif delta == p2:
2729 2729 nump2prev += 1
2730 2730 elif delta == p1:
2731 2731 nump1 += 1
2732 2732 elif delta == p2:
2733 2733 nump2 += 1
2734 2734 elif delta != nullrev:
2735 2735 numother += 1
2736 2736
2737 2737 # Adjust size min value for empty cases
2738 2738 for size in (datasize, fullsize, deltasize):
2739 2739 if size[0] is None:
2740 2740 size[0] = 0
2741 2741
2742 2742 numdeltas = numrevs - numfull
2743 2743 numoprev = numprev - nump1prev - nump2prev
2744 2744 totalrawsize = datasize[2]
2745 2745 datasize[2] /= numrevs
2746 2746 fulltotal = fullsize[2]
2747 2747 fullsize[2] /= numfull
2748 2748 deltatotal = deltasize[2]
2749 2749 if numrevs - numfull > 0:
2750 2750 deltasize[2] /= numrevs - numfull
2751 2751 totalsize = fulltotal + deltatotal
2752 2752 avgchainlen = sum(chainlengths) / numrevs
2753 2753 compratio = totalrawsize / totalsize
2754 2754
2755 2755 basedfmtstr = '%%%dd\n'
2756 2756 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2757 2757
2758 2758 def dfmtstr(max):
2759 2759 return basedfmtstr % len(str(max))
2760 2760 def pcfmtstr(max, padding=0):
2761 2761 return basepcfmtstr % (len(str(max)), ' ' * padding)
2762 2762
2763 2763 def pcfmt(value, total):
2764 2764 return (value, 100 * float(value) / total)
2765 2765
2766 2766 ui.write(('format : %d\n') % format)
2767 2767 ui.write(('flags : %s\n') % ', '.join(flags))
2768 2768
2769 2769 ui.write('\n')
2770 2770 fmt = pcfmtstr(totalsize)
2771 2771 fmt2 = dfmtstr(totalsize)
2772 2772 ui.write(('revisions : ') + fmt2 % numrevs)
2773 2773 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2774 2774 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2775 2775 ui.write(('revisions : ') + fmt2 % numrevs)
2776 2776 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2777 2777 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2778 2778 ui.write(('revision size : ') + fmt2 % totalsize)
2779 2779 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2780 2780 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2781 2781
2782 2782 ui.write('\n')
2783 2783 fmt = dfmtstr(max(avgchainlen, compratio))
2784 2784 ui.write(('avg chain length : ') + fmt % avgchainlen)
2785 2785 ui.write(('compression ratio : ') + fmt % compratio)
2786 2786
2787 2787 if format > 0:
2788 2788 ui.write('\n')
2789 2789 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2790 2790 % tuple(datasize))
2791 2791 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2792 2792 % tuple(fullsize))
2793 2793 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2794 2794 % tuple(deltasize))
2795 2795
2796 2796 if numdeltas > 0:
2797 2797 ui.write('\n')
2798 2798 fmt = pcfmtstr(numdeltas)
2799 2799 fmt2 = pcfmtstr(numdeltas, 4)
2800 2800 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2801 2801 if numprev > 0:
2802 2802 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2803 2803 numprev))
2804 2804 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2805 2805 numprev))
2806 2806 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2807 2807 numprev))
2808 2808 if gdelta:
2809 2809 ui.write(('deltas against p1 : ')
2810 2810 + fmt % pcfmt(nump1, numdeltas))
2811 2811 ui.write(('deltas against p2 : ')
2812 2812 + fmt % pcfmt(nump2, numdeltas))
2813 2813 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2814 2814 numdeltas))
2815 2815
2816 2816 @command('debugrevspec',
2817 2817 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2818 2818 ('REVSPEC'))
2819 2819 def debugrevspec(ui, repo, expr, **opts):
2820 2820 """parse and apply a revision specification
2821 2821
2822 2822 Use --verbose to print the parsed tree before and after aliases
2823 2823 expansion.
2824 2824 """
2825 2825 if ui.verbose:
2826 2826 tree = revset.parse(expr)[0]
2827 2827 ui.note(revset.prettyformat(tree), "\n")
2828 2828 newtree = revset.findaliases(ui, tree)
2829 2829 if newtree != tree:
2830 2830 ui.note(revset.prettyformat(newtree), "\n")
2831 2831 if opts["optimize"]:
2832 2832 weight, optimizedtree = revset.optimize(newtree, True)
2833 2833 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2834 2834 func = revset.match(ui, expr)
2835 2835 for c in func(repo, revset.spanset(repo)):
2836 2836 ui.write("%s\n" % c)
2837 2837
2838 2838 @command('debugsetparents', [], _('REV1 [REV2]'))
2839 2839 def debugsetparents(ui, repo, rev1, rev2=None):
2840 2840 """manually set the parents of the current working directory
2841 2841
2842 2842 This is useful for writing repository conversion tools, but should
2843 2843 be used with care.
2844 2844
2845 2845 Returns 0 on success.
2846 2846 """
2847 2847
2848 2848 r1 = scmutil.revsingle(repo, rev1).node()
2849 2849 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2850 2850
2851 2851 wlock = repo.wlock()
2852 2852 try:
2853 2853 repo.dirstate.beginparentchange()
2854 2854 repo.setparents(r1, r2)
2855 2855 repo.dirstate.endparentchange()
2856 2856 finally:
2857 2857 wlock.release()
2858 2858
2859 2859 @command('debugdirstate|debugstate',
2860 2860 [('', 'nodates', None, _('do not display the saved mtime')),
2861 2861 ('', 'datesort', None, _('sort by saved mtime'))],
2862 2862 _('[OPTION]...'))
2863 2863 def debugstate(ui, repo, nodates=None, datesort=None):
2864 2864 """show the contents of the current dirstate"""
2865 2865 timestr = ""
2866 2866 showdate = not nodates
2867 2867 if datesort:
2868 2868 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2869 2869 else:
2870 2870 keyfunc = None # sort by filename
2871 2871 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2872 2872 if showdate:
2873 2873 if ent[3] == -1:
2874 2874 # Pad or slice to locale representation
2875 2875 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2876 2876 time.localtime(0)))
2877 2877 timestr = 'unset'
2878 2878 timestr = (timestr[:locale_len] +
2879 2879 ' ' * (locale_len - len(timestr)))
2880 2880 else:
2881 2881 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2882 2882 time.localtime(ent[3]))
2883 2883 if ent[1] & 020000:
2884 2884 mode = 'lnk'
2885 2885 else:
2886 2886 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2887 2887 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2888 2888 for f in repo.dirstate.copies():
2889 2889 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2890 2890
2891 2891 @command('debugsub',
2892 2892 [('r', 'rev', '',
2893 2893 _('revision to check'), _('REV'))],
2894 2894 _('[-r REV] [REV]'))
2895 2895 def debugsub(ui, repo, rev=None):
2896 2896 ctx = scmutil.revsingle(repo, rev, None)
2897 2897 for k, v in sorted(ctx.substate.items()):
2898 2898 ui.write(('path %s\n') % k)
2899 2899 ui.write((' source %s\n') % v[0])
2900 2900 ui.write((' revision %s\n') % v[1])
2901 2901
2902 2902 @command('debugsuccessorssets',
2903 2903 [],
2904 2904 _('[REV]'))
2905 2905 def debugsuccessorssets(ui, repo, *revs):
2906 2906 """show set of successors for revision
2907 2907
2908 2908 A successors set of changeset A is a consistent group of revisions that
2909 2909 succeed A. It contains non-obsolete changesets only.
2910 2910
2911 2911 In most cases a changeset A has a single successors set containing a single
2912 2912 successor (changeset A replaced by A').
2913 2913
2914 2914 A changeset that is made obsolete with no successors are called "pruned".
2915 2915 Such changesets have no successors sets at all.
2916 2916
2917 2917 A changeset that has been "split" will have a successors set containing
2918 2918 more than one successor.
2919 2919
2920 2920 A changeset that has been rewritten in multiple different ways is called
2921 2921 "divergent". Such changesets have multiple successor sets (each of which
2922 2922 may also be split, i.e. have multiple successors).
2923 2923
2924 2924 Results are displayed as follows::
2925 2925
2926 2926 <rev1>
2927 2927 <successors-1A>
2928 2928 <rev2>
2929 2929 <successors-2A>
2930 2930 <successors-2B1> <successors-2B2> <successors-2B3>
2931 2931
2932 2932 Here rev2 has two possible (i.e. divergent) successors sets. The first
2933 2933 holds one element, whereas the second holds three (i.e. the changeset has
2934 2934 been split).
2935 2935 """
2936 2936 # passed to successorssets caching computation from one call to another
2937 2937 cache = {}
2938 2938 ctx2str = str
2939 2939 node2str = short
2940 2940 if ui.debug():
2941 2941 def ctx2str(ctx):
2942 2942 return ctx.hex()
2943 2943 node2str = hex
2944 2944 for rev in scmutil.revrange(repo, revs):
2945 2945 ctx = repo[rev]
2946 2946 ui.write('%s\n'% ctx2str(ctx))
2947 2947 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2948 2948 if succsset:
2949 2949 ui.write(' ')
2950 2950 ui.write(node2str(succsset[0]))
2951 2951 for node in succsset[1:]:
2952 2952 ui.write(' ')
2953 2953 ui.write(node2str(node))
2954 2954 ui.write('\n')
2955 2955
2956 2956 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2957 2957 def debugwalk(ui, repo, *pats, **opts):
2958 2958 """show how files match on given patterns"""
2959 2959 m = scmutil.match(repo[None], pats, opts)
2960 2960 items = list(repo.walk(m))
2961 2961 if not items:
2962 2962 return
2963 2963 f = lambda fn: fn
2964 2964 if ui.configbool('ui', 'slash') and os.sep != '/':
2965 2965 f = lambda fn: util.normpath(fn)
2966 2966 fmt = 'f %%-%ds %%-%ds %%s' % (
2967 2967 max([len(abs) for abs in items]),
2968 2968 max([len(m.rel(abs)) for abs in items]))
2969 2969 for abs in items:
2970 2970 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2971 2971 ui.write("%s\n" % line.rstrip())
2972 2972
2973 2973 @command('debugwireargs',
2974 2974 [('', 'three', '', 'three'),
2975 2975 ('', 'four', '', 'four'),
2976 2976 ('', 'five', '', 'five'),
2977 2977 ] + remoteopts,
2978 2978 _('REPO [OPTIONS]... [ONE [TWO]]'),
2979 2979 norepo=True)
2980 2980 def debugwireargs(ui, repopath, *vals, **opts):
2981 2981 repo = hg.peer(ui, opts, repopath)
2982 2982 for opt in remoteopts:
2983 2983 del opts[opt[1]]
2984 2984 args = {}
2985 2985 for k, v in opts.iteritems():
2986 2986 if v:
2987 2987 args[k] = v
2988 2988 # run twice to check that we don't mess up the stream for the next command
2989 2989 res1 = repo.debugwireargs(*vals, **args)
2990 2990 res2 = repo.debugwireargs(*vals, **args)
2991 2991 ui.write("%s\n" % res1)
2992 2992 if res1 != res2:
2993 2993 ui.warn("%s\n" % res2)
2994 2994
2995 2995 @command('^diff',
2996 2996 [('r', 'rev', [], _('revision'), _('REV')),
2997 2997 ('c', 'change', '', _('change made by revision'), _('REV'))
2998 2998 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2999 2999 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3000 3000 inferrepo=True)
3001 3001 def diff(ui, repo, *pats, **opts):
3002 3002 """diff repository (or selected files)
3003 3003
3004 3004 Show differences between revisions for the specified files.
3005 3005
3006 3006 Differences between files are shown using the unified diff format.
3007 3007
3008 3008 .. note::
3009 3009
3010 3010 diff may generate unexpected results for merges, as it will
3011 3011 default to comparing against the working directory's first
3012 3012 parent changeset if no revisions are specified.
3013 3013
3014 3014 When two revision arguments are given, then changes are shown
3015 3015 between those revisions. If only one revision is specified then
3016 3016 that revision is compared to the working directory, and, when no
3017 3017 revisions are specified, the working directory files are compared
3018 3018 to its parent.
3019 3019
3020 3020 Alternatively you can specify -c/--change with a revision to see
3021 3021 the changes in that changeset relative to its first parent.
3022 3022
3023 3023 Without the -a/--text option, diff will avoid generating diffs of
3024 3024 files it detects as binary. With -a, diff will generate a diff
3025 3025 anyway, probably with undesirable results.
3026 3026
3027 3027 Use the -g/--git option to generate diffs in the git extended diff
3028 3028 format. For more information, read :hg:`help diffs`.
3029 3029
3030 3030 .. container:: verbose
3031 3031
3032 3032 Examples:
3033 3033
3034 3034 - compare a file in the current working directory to its parent::
3035 3035
3036 3036 hg diff foo.c
3037 3037
3038 3038 - compare two historical versions of a directory, with rename info::
3039 3039
3040 3040 hg diff --git -r 1.0:1.2 lib/
3041 3041
3042 3042 - get change stats relative to the last change on some date::
3043 3043
3044 3044 hg diff --stat -r "date('may 2')"
3045 3045
3046 3046 - diff all newly-added files that contain a keyword::
3047 3047
3048 3048 hg diff "set:added() and grep(GNU)"
3049 3049
3050 3050 - compare a revision and its parents::
3051 3051
3052 3052 hg diff -c 9353 # compare against first parent
3053 3053 hg diff -r 9353^:9353 # same using revset syntax
3054 3054 hg diff -r 9353^2:9353 # compare against the second parent
3055 3055
3056 3056 Returns 0 on success.
3057 3057 """
3058 3058
3059 3059 revs = opts.get('rev')
3060 3060 change = opts.get('change')
3061 3061 stat = opts.get('stat')
3062 3062 reverse = opts.get('reverse')
3063 3063
3064 3064 if revs and change:
3065 3065 msg = _('cannot specify --rev and --change at the same time')
3066 3066 raise util.Abort(msg)
3067 3067 elif change:
3068 3068 node2 = scmutil.revsingle(repo, change, None).node()
3069 3069 node1 = repo[node2].p1().node()
3070 3070 else:
3071 3071 node1, node2 = scmutil.revpair(repo, revs)
3072 3072
3073 3073 if reverse:
3074 3074 node1, node2 = node2, node1
3075 3075
3076 3076 diffopts = patch.diffopts(ui, opts)
3077 3077 m = scmutil.match(repo[node2], pats, opts)
3078 3078 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3079 3079 listsubrepos=opts.get('subrepos'))
3080 3080
3081 3081 @command('^export',
3082 3082 [('o', 'output', '',
3083 3083 _('print output to file with formatted name'), _('FORMAT')),
3084 3084 ('', 'switch-parent', None, _('diff against the second parent')),
3085 3085 ('r', 'rev', [], _('revisions to export'), _('REV')),
3086 3086 ] + diffopts,
3087 3087 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3088 3088 def export(ui, repo, *changesets, **opts):
3089 3089 """dump the header and diffs for one or more changesets
3090 3090
3091 3091 Print the changeset header and diffs for one or more revisions.
3092 3092 If no revision is given, the parent of the working directory is used.
3093 3093
3094 3094 The information shown in the changeset header is: author, date,
3095 3095 branch name (if non-default), changeset hash, parent(s) and commit
3096 3096 comment.
3097 3097
3098 3098 .. note::
3099 3099
3100 3100 export may generate unexpected diff output for merge
3101 3101 changesets, as it will compare the merge changeset against its
3102 3102 first parent only.
3103 3103
3104 3104 Output may be to a file, in which case the name of the file is
3105 3105 given using a format string. The formatting rules are as follows:
3106 3106
3107 3107 :``%%``: literal "%" character
3108 3108 :``%H``: changeset hash (40 hexadecimal digits)
3109 3109 :``%N``: number of patches being generated
3110 3110 :``%R``: changeset revision number
3111 3111 :``%b``: basename of the exporting repository
3112 3112 :``%h``: short-form changeset hash (12 hexadecimal digits)
3113 3113 :``%m``: first line of the commit message (only alphanumeric characters)
3114 3114 :``%n``: zero-padded sequence number, starting at 1
3115 3115 :``%r``: zero-padded changeset revision number
3116 3116
3117 3117 Without the -a/--text option, export will avoid generating diffs
3118 3118 of files it detects as binary. With -a, export will generate a
3119 3119 diff anyway, probably with undesirable results.
3120 3120
3121 3121 Use the -g/--git option to generate diffs in the git extended diff
3122 3122 format. See :hg:`help diffs` for more information.
3123 3123
3124 3124 With the --switch-parent option, the diff will be against the
3125 3125 second parent. It can be useful to review a merge.
3126 3126
3127 3127 .. container:: verbose
3128 3128
3129 3129 Examples:
3130 3130
3131 3131 - use export and import to transplant a bugfix to the current
3132 3132 branch::
3133 3133
3134 3134 hg export -r 9353 | hg import -
3135 3135
3136 3136 - export all the changesets between two revisions to a file with
3137 3137 rename information::
3138 3138
3139 3139 hg export --git -r 123:150 > changes.txt
3140 3140
3141 3141 - split outgoing changes into a series of patches with
3142 3142 descriptive names::
3143 3143
3144 3144 hg export -r "outgoing()" -o "%n-%m.patch"
3145 3145
3146 3146 Returns 0 on success.
3147 3147 """
3148 3148 changesets += tuple(opts.get('rev', []))
3149 3149 if not changesets:
3150 3150 changesets = ['.']
3151 3151 revs = scmutil.revrange(repo, changesets)
3152 3152 if not revs:
3153 3153 raise util.Abort(_("export requires at least one changeset"))
3154 3154 if len(revs) > 1:
3155 3155 ui.note(_('exporting patches:\n'))
3156 3156 else:
3157 3157 ui.note(_('exporting patch:\n'))
3158 3158 cmdutil.export(repo, revs, template=opts.get('output'),
3159 3159 switch_parent=opts.get('switch_parent'),
3160 3160 opts=patch.diffopts(ui, opts))
3161 3161
3162 3162 @command('files',
3163 3163 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3164 3164 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3165 3165 ] + walkopts + formatteropts,
3166 3166 _('[OPTION]... [PATTERN]...'))
3167 3167 def files(ui, repo, *pats, **opts):
3168 3168 """list tracked files
3169 3169
3170 3170 Print files under Mercurial control in the working directory or
3171 3171 specified revision whose names match the given patterns (excluding
3172 3172 removed files).
3173 3173
3174 3174 If no patterns are given to match, this command prints the names
3175 3175 of all files under Mercurial control in the working copy.
3176 3176
3177 3177 .. container:: verbose
3178 3178
3179 3179 Examples:
3180 3180
3181 3181 - list all files under the current directory::
3182 3182
3183 3183 hg files .
3184 3184
3185 3185 - shows sizes and flags for current revision::
3186 3186
3187 3187 hg files -vr .
3188 3188
3189 3189 - list all files named README::
3190 3190
3191 3191 hg files -I "**/README"
3192 3192
3193 3193 - list all binary files::
3194 3194
3195 3195 hg files "set:binary()"
3196 3196
3197 3197 - find files containing a regular expression:
3198 3198
3199 3199 hg files "set:grep('bob')"
3200 3200
3201 3201 - search tracked file contents with xargs and grep::
3202 3202
3203 3203 hg files -0 | xargs -0 grep foo
3204 3204
3205 3205 See :hg:'help pattern' and :hg:'help revsets' for more information
3206 3206 on specifying file patterns.
3207 3207
3208 3208 Returns 0 if a match is found, 1 otherwise.
3209 3209
3210 3210 """
3211 3211 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3212 3212 rev = ctx.rev()
3213 3213 ret = 1
3214 3214
3215 3215 end = '\n'
3216 3216 if opts.get('print0'):
3217 3217 end = '\0'
3218 3218 fm = ui.formatter('files', opts)
3219 3219 fmt = '%s' + end
3220 3220
3221 3221 m = scmutil.match(ctx, pats, opts)
3222 3222 for f in ctx.walk(m):
3223 3223 if rev is None and repo.dirstate[f] in 'R?!':
3224 3224 continue
3225 3225 fm.startitem()
3226 3226 if ui.verbose:
3227 3227 fc = ctx[f]
3228 3228 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3229 3229 fm.data(abspath=f)
3230 3230 fm.write('path', fmt, m.rel(f))
3231 3231 ret = 0
3232 3232
3233 3233 fm.end()
3234 3234
3235 3235 return ret
3236 3236
3237 3237 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3238 3238 def forget(ui, repo, *pats, **opts):
3239 3239 """forget the specified files on the next commit
3240 3240
3241 3241 Mark the specified files so they will no longer be tracked
3242 3242 after the next commit.
3243 3243
3244 3244 This only removes files from the current branch, not from the
3245 3245 entire project history, and it does not delete them from the
3246 3246 working directory.
3247 3247
3248 3248 To undo a forget before the next commit, see :hg:`add`.
3249 3249
3250 3250 .. container:: verbose
3251 3251
3252 3252 Examples:
3253 3253
3254 3254 - forget newly-added binary files::
3255 3255
3256 3256 hg forget "set:added() and binary()"
3257 3257
3258 3258 - forget files that would be excluded by .hgignore::
3259 3259
3260 3260 hg forget "set:hgignore()"
3261 3261
3262 3262 Returns 0 on success.
3263 3263 """
3264 3264
3265 3265 if not pats:
3266 3266 raise util.Abort(_('no files specified'))
3267 3267
3268 3268 m = scmutil.match(repo[None], pats, opts)
3269 3269 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3270 3270 return rejected and 1 or 0
3271 3271
3272 3272 @command(
3273 3273 'graft',
3274 3274 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3275 3275 ('c', 'continue', False, _('resume interrupted graft')),
3276 3276 ('e', 'edit', False, _('invoke editor on commit messages')),
3277 3277 ('', 'log', None, _('append graft info to log message')),
3278 3278 ('f', 'force', False, _('force graft')),
3279 3279 ('D', 'currentdate', False,
3280 3280 _('record the current date as commit date')),
3281 3281 ('U', 'currentuser', False,
3282 3282 _('record the current user as committer'), _('DATE'))]
3283 3283 + commitopts2 + mergetoolopts + dryrunopts,
3284 3284 _('[OPTION]... [-r] REV...'))
3285 3285 def graft(ui, repo, *revs, **opts):
3286 3286 '''copy changes from other branches onto the current branch
3287 3287
3288 3288 This command uses Mercurial's merge logic to copy individual
3289 3289 changes from other branches without merging branches in the
3290 3290 history graph. This is sometimes known as 'backporting' or
3291 3291 'cherry-picking'. By default, graft will copy user, date, and
3292 3292 description from the source changesets.
3293 3293
3294 3294 Changesets that are ancestors of the current revision, that have
3295 3295 already been grafted, or that are merges will be skipped.
3296 3296
3297 3297 If --log is specified, log messages will have a comment appended
3298 3298 of the form::
3299 3299
3300 3300 (grafted from CHANGESETHASH)
3301 3301
3302 3302 If --force is specified, revisions will be grafted even if they
3303 3303 are already ancestors of or have been grafted to the destination.
3304 3304 This is useful when the revisions have since been backed out.
3305 3305
3306 3306 If a graft merge results in conflicts, the graft process is
3307 3307 interrupted so that the current merge can be manually resolved.
3308 3308 Once all conflicts are addressed, the graft process can be
3309 3309 continued with the -c/--continue option.
3310 3310
3311 3311 .. note::
3312 3312
3313 3313 The -c/--continue option does not reapply earlier options, except
3314 3314 for --force.
3315 3315
3316 3316 .. container:: verbose
3317 3317
3318 3318 Examples:
3319 3319
3320 3320 - copy a single change to the stable branch and edit its description::
3321 3321
3322 3322 hg update stable
3323 3323 hg graft --edit 9393
3324 3324
3325 3325 - graft a range of changesets with one exception, updating dates::
3326 3326
3327 3327 hg graft -D "2085::2093 and not 2091"
3328 3328
3329 3329 - continue a graft after resolving conflicts::
3330 3330
3331 3331 hg graft -c
3332 3332
3333 3333 - show the source of a grafted changeset::
3334 3334
3335 3335 hg log --debug -r .
3336 3336
3337 3337 See :hg:`help revisions` and :hg:`help revsets` for more about
3338 3338 specifying revisions.
3339 3339
3340 3340 Returns 0 on successful completion.
3341 3341 '''
3342 3342
3343 3343 revs = list(revs)
3344 3344 revs.extend(opts['rev'])
3345 3345
3346 3346 if not opts.get('user') and opts.get('currentuser'):
3347 3347 opts['user'] = ui.username()
3348 3348 if not opts.get('date') and opts.get('currentdate'):
3349 3349 opts['date'] = "%d %d" % util.makedate()
3350 3350
3351 3351 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3352 3352
3353 3353 cont = False
3354 3354 if opts['continue']:
3355 3355 cont = True
3356 3356 if revs:
3357 3357 raise util.Abort(_("can't specify --continue and revisions"))
3358 3358 # read in unfinished revisions
3359 3359 try:
3360 3360 nodes = repo.opener.read('graftstate').splitlines()
3361 3361 revs = [repo[node].rev() for node in nodes]
3362 3362 except IOError, inst:
3363 3363 if inst.errno != errno.ENOENT:
3364 3364 raise
3365 3365 raise util.Abort(_("no graft state found, can't continue"))
3366 3366 else:
3367 3367 cmdutil.checkunfinished(repo)
3368 3368 cmdutil.bailifchanged(repo)
3369 3369 if not revs:
3370 3370 raise util.Abort(_('no revisions specified'))
3371 3371 revs = scmutil.revrange(repo, revs)
3372 3372
3373 3373 # check for merges
3374 3374 for rev in repo.revs('%ld and merge()', revs):
3375 3375 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3376 3376 revs.remove(rev)
3377 3377 if not revs:
3378 3378 return -1
3379 3379
3380 3380 # Don't check in the --continue case, in effect retaining --force across
3381 3381 # --continues. That's because without --force, any revisions we decided to
3382 3382 # skip would have been filtered out here, so they wouldn't have made their
3383 3383 # way to the graftstate. With --force, any revisions we would have otherwise
3384 3384 # skipped would not have been filtered out, and if they hadn't been applied
3385 3385 # already, they'd have been in the graftstate.
3386 3386 if not (cont or opts.get('force')):
3387 3387 # check for ancestors of dest branch
3388 3388 crev = repo['.'].rev()
3389 3389 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3390 3390 # Cannot use x.remove(y) on smart set, this has to be a list.
3391 3391 # XXX make this lazy in the future
3392 3392 revs = list(revs)
3393 3393 # don't mutate while iterating, create a copy
3394 3394 for rev in list(revs):
3395 3395 if rev in ancestors:
3396 3396 ui.warn(_('skipping ancestor revision %s\n') % rev)
3397 3397 # XXX remove on list is slow
3398 3398 revs.remove(rev)
3399 3399 if not revs:
3400 3400 return -1
3401 3401
3402 3402 # analyze revs for earlier grafts
3403 3403 ids = {}
3404 3404 for ctx in repo.set("%ld", revs):
3405 3405 ids[ctx.hex()] = ctx.rev()
3406 3406 n = ctx.extra().get('source')
3407 3407 if n:
3408 3408 ids[n] = ctx.rev()
3409 3409
3410 3410 # check ancestors for earlier grafts
3411 3411 ui.debug('scanning for duplicate grafts\n')
3412 3412
3413 3413 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3414 3414 ctx = repo[rev]
3415 3415 n = ctx.extra().get('source')
3416 3416 if n in ids:
3417 3417 try:
3418 3418 r = repo[n].rev()
3419 3419 except error.RepoLookupError:
3420 3420 r = None
3421 3421 if r in revs:
3422 3422 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3423 3423 % (r, rev))
3424 3424 revs.remove(r)
3425 3425 elif ids[n] in revs:
3426 3426 if r is None:
3427 3427 ui.warn(_('skipping already grafted revision %s '
3428 3428 '(%s also has unknown origin %s)\n')
3429 3429 % (ids[n], rev, n))
3430 3430 else:
3431 3431 ui.warn(_('skipping already grafted revision %s '
3432 3432 '(%s also has origin %d)\n')
3433 3433 % (ids[n], rev, r))
3434 3434 revs.remove(ids[n])
3435 3435 elif ctx.hex() in ids:
3436 3436 r = ids[ctx.hex()]
3437 3437 ui.warn(_('skipping already grafted revision %s '
3438 3438 '(was grafted from %d)\n') % (r, rev))
3439 3439 revs.remove(r)
3440 3440 if not revs:
3441 3441 return -1
3442 3442
3443 3443 wlock = repo.wlock()
3444 3444 try:
3445 3445 current = repo['.']
3446 3446 for pos, ctx in enumerate(repo.set("%ld", revs)):
3447 3447
3448 3448 ui.status(_('grafting revision %s\n') % ctx.rev())
3449 3449 if opts.get('dry_run'):
3450 3450 continue
3451 3451
3452 3452 source = ctx.extra().get('source')
3453 3453 if not source:
3454 3454 source = ctx.hex()
3455 3455 extra = {'source': source}
3456 3456 user = ctx.user()
3457 3457 if opts.get('user'):
3458 3458 user = opts['user']
3459 3459 date = ctx.date()
3460 3460 if opts.get('date'):
3461 3461 date = opts['date']
3462 3462 message = ctx.description()
3463 3463 if opts.get('log'):
3464 3464 message += '\n(grafted from %s)' % ctx.hex()
3465 3465
3466 3466 # we don't merge the first commit when continuing
3467 3467 if not cont:
3468 3468 # perform the graft merge with p1(rev) as 'ancestor'
3469 3469 try:
3470 3470 # ui.forcemerge is an internal variable, do not document
3471 3471 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3472 3472 'graft')
3473 3473 stats = mergemod.update(repo, ctx.node(), True, True, False,
3474 3474 ctx.p1().node(),
3475 3475 labels=['local', 'graft'])
3476 3476 finally:
3477 3477 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3478 3478 # report any conflicts
3479 3479 if stats and stats[3] > 0:
3480 3480 # write out state for --continue
3481 3481 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3482 3482 repo.opener.write('graftstate', ''.join(nodelines))
3483 3483 raise util.Abort(
3484 3484 _("unresolved conflicts, can't continue"),
3485 3485 hint=_('use hg resolve and hg graft --continue'))
3486 3486 else:
3487 3487 cont = False
3488 3488
3489 3489 # drop the second merge parent
3490 3490 repo.dirstate.beginparentchange()
3491 3491 repo.setparents(current.node(), nullid)
3492 3492 repo.dirstate.write()
3493 3493 # fix up dirstate for copies and renames
3494 3494 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3495 3495 repo.dirstate.endparentchange()
3496 3496
3497 3497 # commit
3498 3498 node = repo.commit(text=message, user=user,
3499 3499 date=date, extra=extra, editor=editor)
3500 3500 if node is None:
3501 3501 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3502 3502 else:
3503 3503 current = repo[node]
3504 3504 finally:
3505 3505 wlock.release()
3506 3506
3507 3507 # remove state when we complete successfully
3508 3508 if not opts.get('dry_run'):
3509 3509 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3510 3510
3511 3511 return 0
3512 3512
3513 3513 @command('grep',
3514 3514 [('0', 'print0', None, _('end fields with NUL')),
3515 3515 ('', 'all', None, _('print all revisions that match')),
3516 3516 ('a', 'text', None, _('treat all files as text')),
3517 3517 ('f', 'follow', None,
3518 3518 _('follow changeset history,'
3519 3519 ' or file history across copies and renames')),
3520 3520 ('i', 'ignore-case', None, _('ignore case when matching')),
3521 3521 ('l', 'files-with-matches', None,
3522 3522 _('print only filenames and revisions that match')),
3523 3523 ('n', 'line-number', None, _('print matching line numbers')),
3524 3524 ('r', 'rev', [],
3525 3525 _('only search files changed within revision range'), _('REV')),
3526 3526 ('u', 'user', None, _('list the author (long with -v)')),
3527 3527 ('d', 'date', None, _('list the date (short with -q)')),
3528 3528 ] + walkopts,
3529 3529 _('[OPTION]... PATTERN [FILE]...'),
3530 3530 inferrepo=True)
3531 3531 def grep(ui, repo, pattern, *pats, **opts):
3532 3532 """search for a pattern in specified files and revisions
3533 3533
3534 3534 Search revisions of files for a regular expression.
3535 3535
3536 3536 This command behaves differently than Unix grep. It only accepts
3537 3537 Python/Perl regexps. It searches repository history, not the
3538 3538 working directory. It always prints the revision number in which a
3539 3539 match appears.
3540 3540
3541 3541 By default, grep only prints output for the first revision of a
3542 3542 file in which it finds a match. To get it to print every revision
3543 3543 that contains a change in match status ("-" for a match that
3544 3544 becomes a non-match, or "+" for a non-match that becomes a match),
3545 3545 use the --all flag.
3546 3546
3547 3547 Returns 0 if a match is found, 1 otherwise.
3548 3548 """
3549 3549 reflags = re.M
3550 3550 if opts.get('ignore_case'):
3551 3551 reflags |= re.I
3552 3552 try:
3553 3553 regexp = util.re.compile(pattern, reflags)
3554 3554 except re.error, inst:
3555 3555 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3556 3556 return 1
3557 3557 sep, eol = ':', '\n'
3558 3558 if opts.get('print0'):
3559 3559 sep = eol = '\0'
3560 3560
3561 3561 getfile = util.lrucachefunc(repo.file)
3562 3562
3563 3563 def matchlines(body):
3564 3564 begin = 0
3565 3565 linenum = 0
3566 3566 while begin < len(body):
3567 3567 match = regexp.search(body, begin)
3568 3568 if not match:
3569 3569 break
3570 3570 mstart, mend = match.span()
3571 3571 linenum += body.count('\n', begin, mstart) + 1
3572 3572 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3573 3573 begin = body.find('\n', mend) + 1 or len(body) + 1
3574 3574 lend = begin - 1
3575 3575 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3576 3576
3577 3577 class linestate(object):
3578 3578 def __init__(self, line, linenum, colstart, colend):
3579 3579 self.line = line
3580 3580 self.linenum = linenum
3581 3581 self.colstart = colstart
3582 3582 self.colend = colend
3583 3583
3584 3584 def __hash__(self):
3585 3585 return hash((self.linenum, self.line))
3586 3586
3587 3587 def __eq__(self, other):
3588 3588 return self.line == other.line
3589 3589
3590 3590 def __iter__(self):
3591 3591 yield (self.line[:self.colstart], '')
3592 3592 yield (self.line[self.colstart:self.colend], 'grep.match')
3593 3593 rest = self.line[self.colend:]
3594 3594 while rest != '':
3595 3595 match = regexp.search(rest)
3596 3596 if not match:
3597 3597 yield (rest, '')
3598 3598 break
3599 3599 mstart, mend = match.span()
3600 3600 yield (rest[:mstart], '')
3601 3601 yield (rest[mstart:mend], 'grep.match')
3602 3602 rest = rest[mend:]
3603 3603
3604 3604 matches = {}
3605 3605 copies = {}
3606 3606 def grepbody(fn, rev, body):
3607 3607 matches[rev].setdefault(fn, [])
3608 3608 m = matches[rev][fn]
3609 3609 for lnum, cstart, cend, line in matchlines(body):
3610 3610 s = linestate(line, lnum, cstart, cend)
3611 3611 m.append(s)
3612 3612
3613 3613 def difflinestates(a, b):
3614 3614 sm = difflib.SequenceMatcher(None, a, b)
3615 3615 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3616 3616 if tag == 'insert':
3617 3617 for i in xrange(blo, bhi):
3618 3618 yield ('+', b[i])
3619 3619 elif tag == 'delete':
3620 3620 for i in xrange(alo, ahi):
3621 3621 yield ('-', a[i])
3622 3622 elif tag == 'replace':
3623 3623 for i in xrange(alo, ahi):
3624 3624 yield ('-', a[i])
3625 3625 for i in xrange(blo, bhi):
3626 3626 yield ('+', b[i])
3627 3627
3628 3628 def display(fn, ctx, pstates, states):
3629 3629 rev = ctx.rev()
3630 3630 datefunc = ui.quiet and util.shortdate or util.datestr
3631 3631 found = False
3632 3632 @util.cachefunc
3633 3633 def binary():
3634 3634 flog = getfile(fn)
3635 3635 return util.binary(flog.read(ctx.filenode(fn)))
3636 3636
3637 3637 if opts.get('all'):
3638 3638 iter = difflinestates(pstates, states)
3639 3639 else:
3640 3640 iter = [('', l) for l in states]
3641 3641 for change, l in iter:
3642 3642 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3643 3643
3644 3644 if opts.get('line_number'):
3645 3645 cols.append((str(l.linenum), 'grep.linenumber'))
3646 3646 if opts.get('all'):
3647 3647 cols.append((change, 'grep.change'))
3648 3648 if opts.get('user'):
3649 3649 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3650 3650 if opts.get('date'):
3651 3651 cols.append((datefunc(ctx.date()), 'grep.date'))
3652 3652 for col, label in cols[:-1]:
3653 3653 ui.write(col, label=label)
3654 3654 ui.write(sep, label='grep.sep')
3655 3655 ui.write(cols[-1][0], label=cols[-1][1])
3656 3656 if not opts.get('files_with_matches'):
3657 3657 ui.write(sep, label='grep.sep')
3658 3658 if not opts.get('text') and binary():
3659 3659 ui.write(" Binary file matches")
3660 3660 else:
3661 3661 for s, label in l:
3662 3662 ui.write(s, label=label)
3663 3663 ui.write(eol)
3664 3664 found = True
3665 3665 if opts.get('files_with_matches'):
3666 3666 break
3667 3667 return found
3668 3668
3669 3669 skip = {}
3670 3670 revfiles = {}
3671 3671 matchfn = scmutil.match(repo[None], pats, opts)
3672 3672 found = False
3673 3673 follow = opts.get('follow')
3674 3674
3675 3675 def prep(ctx, fns):
3676 3676 rev = ctx.rev()
3677 3677 pctx = ctx.p1()
3678 3678 parent = pctx.rev()
3679 3679 matches.setdefault(rev, {})
3680 3680 matches.setdefault(parent, {})
3681 3681 files = revfiles.setdefault(rev, [])
3682 3682 for fn in fns:
3683 3683 flog = getfile(fn)
3684 3684 try:
3685 3685 fnode = ctx.filenode(fn)
3686 3686 except error.LookupError:
3687 3687 continue
3688 3688
3689 3689 copied = flog.renamed(fnode)
3690 3690 copy = follow and copied and copied[0]
3691 3691 if copy:
3692 3692 copies.setdefault(rev, {})[fn] = copy
3693 3693 if fn in skip:
3694 3694 if copy:
3695 3695 skip[copy] = True
3696 3696 continue
3697 3697 files.append(fn)
3698 3698
3699 3699 if fn not in matches[rev]:
3700 3700 grepbody(fn, rev, flog.read(fnode))
3701 3701
3702 3702 pfn = copy or fn
3703 3703 if pfn not in matches[parent]:
3704 3704 try:
3705 3705 fnode = pctx.filenode(pfn)
3706 3706 grepbody(pfn, parent, flog.read(fnode))
3707 3707 except error.LookupError:
3708 3708 pass
3709 3709
3710 3710 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3711 3711 rev = ctx.rev()
3712 3712 parent = ctx.p1().rev()
3713 3713 for fn in sorted(revfiles.get(rev, [])):
3714 3714 states = matches[rev][fn]
3715 3715 copy = copies.get(rev, {}).get(fn)
3716 3716 if fn in skip:
3717 3717 if copy:
3718 3718 skip[copy] = True
3719 3719 continue
3720 3720 pstates = matches.get(parent, {}).get(copy or fn, [])
3721 3721 if pstates or states:
3722 3722 r = display(fn, ctx, pstates, states)
3723 3723 found = found or r
3724 3724 if r and not opts.get('all'):
3725 3725 skip[fn] = True
3726 3726 if copy:
3727 3727 skip[copy] = True
3728 3728 del matches[rev]
3729 3729 del revfiles[rev]
3730 3730
3731 3731 return not found
3732 3732
3733 3733 @command('heads',
3734 3734 [('r', 'rev', '',
3735 3735 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3736 3736 ('t', 'topo', False, _('show topological heads only')),
3737 3737 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3738 3738 ('c', 'closed', False, _('show normal and closed branch heads')),
3739 3739 ] + templateopts,
3740 3740 _('[-ct] [-r STARTREV] [REV]...'))
3741 3741 def heads(ui, repo, *branchrevs, **opts):
3742 3742 """show branch heads
3743 3743
3744 3744 With no arguments, show all open branch heads in the repository.
3745 3745 Branch heads are changesets that have no descendants on the
3746 3746 same branch. They are where development generally takes place and
3747 3747 are the usual targets for update and merge operations.
3748 3748
3749 3749 If one or more REVs are given, only open branch heads on the
3750 3750 branches associated with the specified changesets are shown. This
3751 3751 means that you can use :hg:`heads .` to see the heads on the
3752 3752 currently checked-out branch.
3753 3753
3754 3754 If -c/--closed is specified, also show branch heads marked closed
3755 3755 (see :hg:`commit --close-branch`).
3756 3756
3757 3757 If STARTREV is specified, only those heads that are descendants of
3758 3758 STARTREV will be displayed.
3759 3759
3760 3760 If -t/--topo is specified, named branch mechanics will be ignored and only
3761 3761 topological heads (changesets with no children) will be shown.
3762 3762
3763 3763 Returns 0 if matching heads are found, 1 if not.
3764 3764 """
3765 3765
3766 3766 start = None
3767 3767 if 'rev' in opts:
3768 3768 start = scmutil.revsingle(repo, opts['rev'], None).node()
3769 3769
3770 3770 if opts.get('topo'):
3771 3771 heads = [repo[h] for h in repo.heads(start)]
3772 3772 else:
3773 3773 heads = []
3774 3774 for branch in repo.branchmap():
3775 3775 heads += repo.branchheads(branch, start, opts.get('closed'))
3776 3776 heads = [repo[h] for h in heads]
3777 3777
3778 3778 if branchrevs:
3779 3779 branches = set(repo[br].branch() for br in branchrevs)
3780 3780 heads = [h for h in heads if h.branch() in branches]
3781 3781
3782 3782 if opts.get('active') and branchrevs:
3783 3783 dagheads = repo.heads(start)
3784 3784 heads = [h for h in heads if h.node() in dagheads]
3785 3785
3786 3786 if branchrevs:
3787 3787 haveheads = set(h.branch() for h in heads)
3788 3788 if branches - haveheads:
3789 3789 headless = ', '.join(b for b in branches - haveheads)
3790 3790 msg = _('no open branch heads found on branches %s')
3791 3791 if opts.get('rev'):
3792 3792 msg += _(' (started at %s)') % opts['rev']
3793 3793 ui.warn((msg + '\n') % headless)
3794 3794
3795 3795 if not heads:
3796 3796 return 1
3797 3797
3798 3798 heads = sorted(heads, key=lambda x: -x.rev())
3799 3799 displayer = cmdutil.show_changeset(ui, repo, opts)
3800 3800 for ctx in heads:
3801 3801 displayer.show(ctx)
3802 3802 displayer.close()
3803 3803
3804 3804 @command('help',
3805 3805 [('e', 'extension', None, _('show only help for extensions')),
3806 3806 ('c', 'command', None, _('show only help for commands')),
3807 3807 ('k', 'keyword', '', _('show topics matching keyword')),
3808 3808 ],
3809 3809 _('[-ec] [TOPIC]'),
3810 3810 norepo=True)
3811 3811 def help_(ui, name=None, **opts):
3812 3812 """show help for a given topic or a help overview
3813 3813
3814 3814 With no arguments, print a list of commands with short help messages.
3815 3815
3816 3816 Given a topic, extension, or command name, print help for that
3817 3817 topic.
3818 3818
3819 3819 Returns 0 if successful.
3820 3820 """
3821 3821
3822 3822 textwidth = min(ui.termwidth(), 80) - 2
3823 3823
3824 3824 keep = []
3825 3825 if ui.verbose:
3826 3826 keep.append('verbose')
3827 3827 if sys.platform.startswith('win'):
3828 3828 keep.append('windows')
3829 3829 elif sys.platform == 'OpenVMS':
3830 3830 keep.append('vms')
3831 3831 elif sys.platform == 'plan9':
3832 3832 keep.append('plan9')
3833 3833 else:
3834 3834 keep.append('unix')
3835 3835 keep.append(sys.platform.lower())
3836 3836
3837 section = None
3838 if name and '.' in name:
3839 name, section = name.split('.')
3840
3837 3841 text = help.help_(ui, name, **opts)
3838 3842
3839 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3843 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3844 section=section)
3845 if section and not formatted:
3846 raise util.Abort(_("help section not found"))
3847
3840 3848 if 'verbose' in pruned:
3841 3849 keep.append('omitted')
3842 3850 else:
3843 3851 keep.append('notomitted')
3844 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3852 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3853 section=section)
3845 3854 ui.write(formatted)
3846 3855
3847 3856
3848 3857 @command('identify|id',
3849 3858 [('r', 'rev', '',
3850 3859 _('identify the specified revision'), _('REV')),
3851 3860 ('n', 'num', None, _('show local revision number')),
3852 3861 ('i', 'id', None, _('show global revision id')),
3853 3862 ('b', 'branch', None, _('show branch')),
3854 3863 ('t', 'tags', None, _('show tags')),
3855 3864 ('B', 'bookmarks', None, _('show bookmarks')),
3856 3865 ] + remoteopts,
3857 3866 _('[-nibtB] [-r REV] [SOURCE]'),
3858 3867 optionalrepo=True)
3859 3868 def identify(ui, repo, source=None, rev=None,
3860 3869 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3861 3870 """identify the working copy or specified revision
3862 3871
3863 3872 Print a summary identifying the repository state at REV using one or
3864 3873 two parent hash identifiers, followed by a "+" if the working
3865 3874 directory has uncommitted changes, the branch name (if not default),
3866 3875 a list of tags, and a list of bookmarks.
3867 3876
3868 3877 When REV is not given, print a summary of the current state of the
3869 3878 repository.
3870 3879
3871 3880 Specifying a path to a repository root or Mercurial bundle will
3872 3881 cause lookup to operate on that repository/bundle.
3873 3882
3874 3883 .. container:: verbose
3875 3884
3876 3885 Examples:
3877 3886
3878 3887 - generate a build identifier for the working directory::
3879 3888
3880 3889 hg id --id > build-id.dat
3881 3890
3882 3891 - find the revision corresponding to a tag::
3883 3892
3884 3893 hg id -n -r 1.3
3885 3894
3886 3895 - check the most recent revision of a remote repository::
3887 3896
3888 3897 hg id -r tip http://selenic.com/hg/
3889 3898
3890 3899 Returns 0 if successful.
3891 3900 """
3892 3901
3893 3902 if not repo and not source:
3894 3903 raise util.Abort(_("there is no Mercurial repository here "
3895 3904 "(.hg not found)"))
3896 3905
3897 3906 hexfunc = ui.debugflag and hex or short
3898 3907 default = not (num or id or branch or tags or bookmarks)
3899 3908 output = []
3900 3909 revs = []
3901 3910
3902 3911 if source:
3903 3912 source, branches = hg.parseurl(ui.expandpath(source))
3904 3913 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3905 3914 repo = peer.local()
3906 3915 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3907 3916
3908 3917 if not repo:
3909 3918 if num or branch or tags:
3910 3919 raise util.Abort(
3911 3920 _("can't query remote revision number, branch, or tags"))
3912 3921 if not rev and revs:
3913 3922 rev = revs[0]
3914 3923 if not rev:
3915 3924 rev = "tip"
3916 3925
3917 3926 remoterev = peer.lookup(rev)
3918 3927 if default or id:
3919 3928 output = [hexfunc(remoterev)]
3920 3929
3921 3930 def getbms():
3922 3931 bms = []
3923 3932
3924 3933 if 'bookmarks' in peer.listkeys('namespaces'):
3925 3934 hexremoterev = hex(remoterev)
3926 3935 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3927 3936 if bmr == hexremoterev]
3928 3937
3929 3938 return sorted(bms)
3930 3939
3931 3940 if bookmarks:
3932 3941 output.extend(getbms())
3933 3942 elif default and not ui.quiet:
3934 3943 # multiple bookmarks for a single parent separated by '/'
3935 3944 bm = '/'.join(getbms())
3936 3945 if bm:
3937 3946 output.append(bm)
3938 3947 else:
3939 3948 if not rev:
3940 3949 ctx = repo[None]
3941 3950 parents = ctx.parents()
3942 3951 changed = ""
3943 3952 if default or id or num:
3944 3953 if (util.any(repo.status())
3945 3954 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3946 3955 changed = '+'
3947 3956 if default or id:
3948 3957 output = ["%s%s" %
3949 3958 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3950 3959 if num:
3951 3960 output.append("%s%s" %
3952 3961 ('+'.join([str(p.rev()) for p in parents]), changed))
3953 3962 else:
3954 3963 ctx = scmutil.revsingle(repo, rev)
3955 3964 if default or id:
3956 3965 output = [hexfunc(ctx.node())]
3957 3966 if num:
3958 3967 output.append(str(ctx.rev()))
3959 3968
3960 3969 if default and not ui.quiet:
3961 3970 b = ctx.branch()
3962 3971 if b != 'default':
3963 3972 output.append("(%s)" % b)
3964 3973
3965 3974 # multiple tags for a single parent separated by '/'
3966 3975 t = '/'.join(ctx.tags())
3967 3976 if t:
3968 3977 output.append(t)
3969 3978
3970 3979 # multiple bookmarks for a single parent separated by '/'
3971 3980 bm = '/'.join(ctx.bookmarks())
3972 3981 if bm:
3973 3982 output.append(bm)
3974 3983 else:
3975 3984 if branch:
3976 3985 output.append(ctx.branch())
3977 3986
3978 3987 if tags:
3979 3988 output.extend(ctx.tags())
3980 3989
3981 3990 if bookmarks:
3982 3991 output.extend(ctx.bookmarks())
3983 3992
3984 3993 ui.write("%s\n" % ' '.join(output))
3985 3994
3986 3995 @command('import|patch',
3987 3996 [('p', 'strip', 1,
3988 3997 _('directory strip option for patch. This has the same '
3989 3998 'meaning as the corresponding patch option'), _('NUM')),
3990 3999 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3991 4000 ('e', 'edit', False, _('invoke editor on commit messages')),
3992 4001 ('f', 'force', None,
3993 4002 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3994 4003 ('', 'no-commit', None,
3995 4004 _("don't commit, just update the working directory")),
3996 4005 ('', 'bypass', None,
3997 4006 _("apply patch without touching the working directory")),
3998 4007 ('', 'partial', None,
3999 4008 _('commit even if some hunks fail')),
4000 4009 ('', 'exact', None,
4001 4010 _('apply patch to the nodes from which it was generated')),
4002 4011 ('', 'import-branch', None,
4003 4012 _('use any branch information in patch (implied by --exact)'))] +
4004 4013 commitopts + commitopts2 + similarityopts,
4005 4014 _('[OPTION]... PATCH...'))
4006 4015 def import_(ui, repo, patch1=None, *patches, **opts):
4007 4016 """import an ordered set of patches
4008 4017
4009 4018 Import a list of patches and commit them individually (unless
4010 4019 --no-commit is specified).
4011 4020
4012 4021 Because import first applies changes to the working directory,
4013 4022 import will abort if there are outstanding changes.
4014 4023
4015 4024 You can import a patch straight from a mail message. Even patches
4016 4025 as attachments work (to use the body part, it must have type
4017 4026 text/plain or text/x-patch). From and Subject headers of email
4018 4027 message are used as default committer and commit message. All
4019 4028 text/plain body parts before first diff are added to commit
4020 4029 message.
4021 4030
4022 4031 If the imported patch was generated by :hg:`export`, user and
4023 4032 description from patch override values from message headers and
4024 4033 body. Values given on command line with -m/--message and -u/--user
4025 4034 override these.
4026 4035
4027 4036 If --exact is specified, import will set the working directory to
4028 4037 the parent of each patch before applying it, and will abort if the
4029 4038 resulting changeset has a different ID than the one recorded in
4030 4039 the patch. This may happen due to character set problems or other
4031 4040 deficiencies in the text patch format.
4032 4041
4033 4042 Use --bypass to apply and commit patches directly to the
4034 4043 repository, not touching the working directory. Without --exact,
4035 4044 patches will be applied on top of the working directory parent
4036 4045 revision.
4037 4046
4038 4047 With -s/--similarity, hg will attempt to discover renames and
4039 4048 copies in the patch in the same way as :hg:`addremove`.
4040 4049
4041 4050 Use --partial to ensure a changeset will be created from the patch
4042 4051 even if some hunks fail to apply. Hunks that fail to apply will be
4043 4052 written to a <target-file>.rej file. Conflicts can then be resolved
4044 4053 by hand before :hg:`commit --amend` is run to update the created
4045 4054 changeset. This flag exists to let people import patches that
4046 4055 partially apply without losing the associated metadata (author,
4047 4056 date, description, ...). Note that when none of the hunk applies
4048 4057 cleanly, :hg:`import --partial` will create an empty changeset,
4049 4058 importing only the patch metadata.
4050 4059
4051 4060 To read a patch from standard input, use "-" as the patch name. If
4052 4061 a URL is specified, the patch will be downloaded from it.
4053 4062 See :hg:`help dates` for a list of formats valid for -d/--date.
4054 4063
4055 4064 .. container:: verbose
4056 4065
4057 4066 Examples:
4058 4067
4059 4068 - import a traditional patch from a website and detect renames::
4060 4069
4061 4070 hg import -s 80 http://example.com/bugfix.patch
4062 4071
4063 4072 - import a changeset from an hgweb server::
4064 4073
4065 4074 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4066 4075
4067 4076 - import all the patches in an Unix-style mbox::
4068 4077
4069 4078 hg import incoming-patches.mbox
4070 4079
4071 4080 - attempt to exactly restore an exported changeset (not always
4072 4081 possible)::
4073 4082
4074 4083 hg import --exact proposed-fix.patch
4075 4084
4076 4085 Returns 0 on success, 1 on partial success (see --partial).
4077 4086 """
4078 4087
4079 4088 if not patch1:
4080 4089 raise util.Abort(_('need at least one patch to import'))
4081 4090
4082 4091 patches = (patch1,) + patches
4083 4092
4084 4093 date = opts.get('date')
4085 4094 if date:
4086 4095 opts['date'] = util.parsedate(date)
4087 4096
4088 4097 update = not opts.get('bypass')
4089 4098 if not update and opts.get('no_commit'):
4090 4099 raise util.Abort(_('cannot use --no-commit with --bypass'))
4091 4100 try:
4092 4101 sim = float(opts.get('similarity') or 0)
4093 4102 except ValueError:
4094 4103 raise util.Abort(_('similarity must be a number'))
4095 4104 if sim < 0 or sim > 100:
4096 4105 raise util.Abort(_('similarity must be between 0 and 100'))
4097 4106 if sim and not update:
4098 4107 raise util.Abort(_('cannot use --similarity with --bypass'))
4099 4108 if opts.get('exact') and opts.get('edit'):
4100 4109 raise util.Abort(_('cannot use --exact with --edit'))
4101 4110
4102 4111 if update:
4103 4112 cmdutil.checkunfinished(repo)
4104 4113 if (opts.get('exact') or not opts.get('force')) and update:
4105 4114 cmdutil.bailifchanged(repo)
4106 4115
4107 4116 base = opts["base"]
4108 4117 wlock = lock = tr = None
4109 4118 msgs = []
4110 4119 ret = 0
4111 4120
4112 4121
4113 4122 try:
4114 4123 try:
4115 4124 wlock = repo.wlock()
4116 4125 repo.dirstate.beginparentchange()
4117 4126 if not opts.get('no_commit'):
4118 4127 lock = repo.lock()
4119 4128 tr = repo.transaction('import')
4120 4129 parents = repo.parents()
4121 4130 for patchurl in patches:
4122 4131 if patchurl == '-':
4123 4132 ui.status(_('applying patch from stdin\n'))
4124 4133 patchfile = ui.fin
4125 4134 patchurl = 'stdin' # for error message
4126 4135 else:
4127 4136 patchurl = os.path.join(base, patchurl)
4128 4137 ui.status(_('applying %s\n') % patchurl)
4129 4138 patchfile = hg.openpath(ui, patchurl)
4130 4139
4131 4140 haspatch = False
4132 4141 for hunk in patch.split(patchfile):
4133 4142 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4134 4143 parents, opts,
4135 4144 msgs, hg.clean)
4136 4145 if msg:
4137 4146 haspatch = True
4138 4147 ui.note(msg + '\n')
4139 4148 if update or opts.get('exact'):
4140 4149 parents = repo.parents()
4141 4150 else:
4142 4151 parents = [repo[node]]
4143 4152 if rej:
4144 4153 ui.write_err(_("patch applied partially\n"))
4145 4154 ui.write_err(_("(fix the .rej files and run "
4146 4155 "`hg commit --amend`)\n"))
4147 4156 ret = 1
4148 4157 break
4149 4158
4150 4159 if not haspatch:
4151 4160 raise util.Abort(_('%s: no diffs found') % patchurl)
4152 4161
4153 4162 if tr:
4154 4163 tr.close()
4155 4164 if msgs:
4156 4165 repo.savecommitmessage('\n* * *\n'.join(msgs))
4157 4166 repo.dirstate.endparentchange()
4158 4167 return ret
4159 4168 except: # re-raises
4160 4169 # wlock.release() indirectly calls dirstate.write(): since
4161 4170 # we're crashing, we do not want to change the working dir
4162 4171 # parent after all, so make sure it writes nothing
4163 4172 repo.dirstate.invalidate()
4164 4173 raise
4165 4174 finally:
4166 4175 if tr:
4167 4176 tr.release()
4168 4177 release(lock, wlock)
4169 4178
4170 4179 @command('incoming|in',
4171 4180 [('f', 'force', None,
4172 4181 _('run even if remote repository is unrelated')),
4173 4182 ('n', 'newest-first', None, _('show newest record first')),
4174 4183 ('', 'bundle', '',
4175 4184 _('file to store the bundles into'), _('FILE')),
4176 4185 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4177 4186 ('B', 'bookmarks', False, _("compare bookmarks")),
4178 4187 ('b', 'branch', [],
4179 4188 _('a specific branch you would like to pull'), _('BRANCH')),
4180 4189 ] + logopts + remoteopts + subrepoopts,
4181 4190 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4182 4191 def incoming(ui, repo, source="default", **opts):
4183 4192 """show new changesets found in source
4184 4193
4185 4194 Show new changesets found in the specified path/URL or the default
4186 4195 pull location. These are the changesets that would have been pulled
4187 4196 if a pull at the time you issued this command.
4188 4197
4189 4198 For remote repository, using --bundle avoids downloading the
4190 4199 changesets twice if the incoming is followed by a pull.
4191 4200
4192 4201 See pull for valid source format details.
4193 4202
4194 4203 .. container:: verbose
4195 4204
4196 4205 Examples:
4197 4206
4198 4207 - show incoming changes with patches and full description::
4199 4208
4200 4209 hg incoming -vp
4201 4210
4202 4211 - show incoming changes excluding merges, store a bundle::
4203 4212
4204 4213 hg in -vpM --bundle incoming.hg
4205 4214 hg pull incoming.hg
4206 4215
4207 4216 - briefly list changes inside a bundle::
4208 4217
4209 4218 hg in changes.hg -T "{desc|firstline}\\n"
4210 4219
4211 4220 Returns 0 if there are incoming changes, 1 otherwise.
4212 4221 """
4213 4222 if opts.get('graph'):
4214 4223 cmdutil.checkunsupportedgraphflags([], opts)
4215 4224 def display(other, chlist, displayer):
4216 4225 revdag = cmdutil.graphrevs(other, chlist, opts)
4217 4226 showparents = [ctx.node() for ctx in repo[None].parents()]
4218 4227 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4219 4228 graphmod.asciiedges)
4220 4229
4221 4230 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4222 4231 return 0
4223 4232
4224 4233 if opts.get('bundle') and opts.get('subrepos'):
4225 4234 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4226 4235
4227 4236 if opts.get('bookmarks'):
4228 4237 source, branches = hg.parseurl(ui.expandpath(source),
4229 4238 opts.get('branch'))
4230 4239 other = hg.peer(repo, opts, source)
4231 4240 if 'bookmarks' not in other.listkeys('namespaces'):
4232 4241 ui.warn(_("remote doesn't support bookmarks\n"))
4233 4242 return 0
4234 4243 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4235 4244 return bookmarks.diff(ui, repo, other)
4236 4245
4237 4246 repo._subtoppath = ui.expandpath(source)
4238 4247 try:
4239 4248 return hg.incoming(ui, repo, source, opts)
4240 4249 finally:
4241 4250 del repo._subtoppath
4242 4251
4243 4252
4244 4253 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4245 4254 norepo=True)
4246 4255 def init(ui, dest=".", **opts):
4247 4256 """create a new repository in the given directory
4248 4257
4249 4258 Initialize a new repository in the given directory. If the given
4250 4259 directory does not exist, it will be created.
4251 4260
4252 4261 If no directory is given, the current directory is used.
4253 4262
4254 4263 It is possible to specify an ``ssh://`` URL as the destination.
4255 4264 See :hg:`help urls` for more information.
4256 4265
4257 4266 Returns 0 on success.
4258 4267 """
4259 4268 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4260 4269
4261 4270 @command('locate',
4262 4271 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4263 4272 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4264 4273 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4265 4274 ] + walkopts,
4266 4275 _('[OPTION]... [PATTERN]...'))
4267 4276 def locate(ui, repo, *pats, **opts):
4268 4277 """locate files matching specific patterns (DEPRECATED)
4269 4278
4270 4279 Print files under Mercurial control in the working directory whose
4271 4280 names match the given patterns.
4272 4281
4273 4282 By default, this command searches all directories in the working
4274 4283 directory. To search just the current directory and its
4275 4284 subdirectories, use "--include .".
4276 4285
4277 4286 If no patterns are given to match, this command prints the names
4278 4287 of all files under Mercurial control in the working directory.
4279 4288
4280 4289 If you want to feed the output of this command into the "xargs"
4281 4290 command, use the -0 option to both this command and "xargs". This
4282 4291 will avoid the problem of "xargs" treating single filenames that
4283 4292 contain whitespace as multiple filenames.
4284 4293
4285 4294 See :hg:`help files` for a more versatile command.
4286 4295
4287 4296 Returns 0 if a match is found, 1 otherwise.
4288 4297 """
4289 4298 end = opts.get('print0') and '\0' or '\n'
4290 4299 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4291 4300
4292 4301 ret = 1
4293 4302 ctx = repo[rev]
4294 4303 m = scmutil.match(ctx, pats, opts, default='relglob')
4295 4304 m.bad = lambda x, y: False
4296 4305
4297 4306 for abs in ctx.matches(m):
4298 4307 if opts.get('fullpath'):
4299 4308 ui.write(repo.wjoin(abs), end)
4300 4309 else:
4301 4310 ui.write(((pats and m.rel(abs)) or abs), end)
4302 4311 ret = 0
4303 4312
4304 4313 return ret
4305 4314
4306 4315 @command('^log|history',
4307 4316 [('f', 'follow', None,
4308 4317 _('follow changeset history, or file history across copies and renames')),
4309 4318 ('', 'follow-first', None,
4310 4319 _('only follow the first parent of merge changesets (DEPRECATED)')),
4311 4320 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4312 4321 ('C', 'copies', None, _('show copied files')),
4313 4322 ('k', 'keyword', [],
4314 4323 _('do case-insensitive search for a given text'), _('TEXT')),
4315 4324 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4316 4325 ('', 'removed', None, _('include revisions where files were removed')),
4317 4326 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4318 4327 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4319 4328 ('', 'only-branch', [],
4320 4329 _('show only changesets within the given named branch (DEPRECATED)'),
4321 4330 _('BRANCH')),
4322 4331 ('b', 'branch', [],
4323 4332 _('show changesets within the given named branch'), _('BRANCH')),
4324 4333 ('P', 'prune', [],
4325 4334 _('do not display revision or any of its ancestors'), _('REV')),
4326 4335 ] + logopts + walkopts,
4327 4336 _('[OPTION]... [FILE]'),
4328 4337 inferrepo=True)
4329 4338 def log(ui, repo, *pats, **opts):
4330 4339 """show revision history of entire repository or files
4331 4340
4332 4341 Print the revision history of the specified files or the entire
4333 4342 project.
4334 4343
4335 4344 If no revision range is specified, the default is ``tip:0`` unless
4336 4345 --follow is set, in which case the working directory parent is
4337 4346 used as the starting revision.
4338 4347
4339 4348 File history is shown without following rename or copy history of
4340 4349 files. Use -f/--follow with a filename to follow history across
4341 4350 renames and copies. --follow without a filename will only show
4342 4351 ancestors or descendants of the starting revision.
4343 4352
4344 4353 By default this command prints revision number and changeset id,
4345 4354 tags, non-trivial parents, user, date and time, and a summary for
4346 4355 each commit. When the -v/--verbose switch is used, the list of
4347 4356 changed files and full commit message are shown.
4348 4357
4349 4358 With --graph the revisions are shown as an ASCII art DAG with the most
4350 4359 recent changeset at the top.
4351 4360 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4352 4361 and '+' represents a fork where the changeset from the lines below is a
4353 4362 parent of the 'o' merge on the same line.
4354 4363
4355 4364 .. note::
4356 4365
4357 4366 log -p/--patch may generate unexpected diff output for merge
4358 4367 changesets, as it will only compare the merge changeset against
4359 4368 its first parent. Also, only files different from BOTH parents
4360 4369 will appear in files:.
4361 4370
4362 4371 .. note::
4363 4372
4364 4373 for performance reasons, log FILE may omit duplicate changes
4365 4374 made on branches and will not show removals or mode changes. To
4366 4375 see all such changes, use the --removed switch.
4367 4376
4368 4377 .. container:: verbose
4369 4378
4370 4379 Some examples:
4371 4380
4372 4381 - changesets with full descriptions and file lists::
4373 4382
4374 4383 hg log -v
4375 4384
4376 4385 - changesets ancestral to the working directory::
4377 4386
4378 4387 hg log -f
4379 4388
4380 4389 - last 10 commits on the current branch::
4381 4390
4382 4391 hg log -l 10 -b .
4383 4392
4384 4393 - changesets showing all modifications of a file, including removals::
4385 4394
4386 4395 hg log --removed file.c
4387 4396
4388 4397 - all changesets that touch a directory, with diffs, excluding merges::
4389 4398
4390 4399 hg log -Mp lib/
4391 4400
4392 4401 - all revision numbers that match a keyword::
4393 4402
4394 4403 hg log -k bug --template "{rev}\\n"
4395 4404
4396 4405 - list available log templates::
4397 4406
4398 4407 hg log -T list
4399 4408
4400 4409 - check if a given changeset is included in a tagged release::
4401 4410
4402 4411 hg log -r "a21ccf and ancestor(1.9)"
4403 4412
4404 4413 - find all changesets by some user in a date range::
4405 4414
4406 4415 hg log -k alice -d "may 2008 to jul 2008"
4407 4416
4408 4417 - summary of all changesets after the last tag::
4409 4418
4410 4419 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4411 4420
4412 4421 See :hg:`help dates` for a list of formats valid for -d/--date.
4413 4422
4414 4423 See :hg:`help revisions` and :hg:`help revsets` for more about
4415 4424 specifying revisions.
4416 4425
4417 4426 See :hg:`help templates` for more about pre-packaged styles and
4418 4427 specifying custom templates.
4419 4428
4420 4429 Returns 0 on success.
4421 4430
4422 4431 """
4423 4432 if opts.get('graph'):
4424 4433 return cmdutil.graphlog(ui, repo, *pats, **opts)
4425 4434
4426 4435 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4427 4436 limit = cmdutil.loglimit(opts)
4428 4437 count = 0
4429 4438
4430 4439 getrenamed = None
4431 4440 if opts.get('copies'):
4432 4441 endrev = None
4433 4442 if opts.get('rev'):
4434 4443 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4435 4444 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4436 4445
4437 4446 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4438 4447 for rev in revs:
4439 4448 if count == limit:
4440 4449 break
4441 4450 ctx = repo[rev]
4442 4451 copies = None
4443 4452 if getrenamed is not None and rev:
4444 4453 copies = []
4445 4454 for fn in ctx.files():
4446 4455 rename = getrenamed(fn, rev)
4447 4456 if rename:
4448 4457 copies.append((fn, rename[0]))
4449 4458 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4450 4459 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4451 4460 if displayer.flush(rev):
4452 4461 count += 1
4453 4462
4454 4463 displayer.close()
4455 4464
4456 4465 @command('manifest',
4457 4466 [('r', 'rev', '', _('revision to display'), _('REV')),
4458 4467 ('', 'all', False, _("list files from all revisions"))]
4459 4468 + formatteropts,
4460 4469 _('[-r REV]'))
4461 4470 def manifest(ui, repo, node=None, rev=None, **opts):
4462 4471 """output the current or given revision of the project manifest
4463 4472
4464 4473 Print a list of version controlled files for the given revision.
4465 4474 If no revision is given, the first parent of the working directory
4466 4475 is used, or the null revision if no revision is checked out.
4467 4476
4468 4477 With -v, print file permissions, symlink and executable bits.
4469 4478 With --debug, print file revision hashes.
4470 4479
4471 4480 If option --all is specified, the list of all files from all revisions
4472 4481 is printed. This includes deleted and renamed files.
4473 4482
4474 4483 Returns 0 on success.
4475 4484 """
4476 4485
4477 4486 fm = ui.formatter('manifest', opts)
4478 4487
4479 4488 if opts.get('all'):
4480 4489 if rev or node:
4481 4490 raise util.Abort(_("can't specify a revision with --all"))
4482 4491
4483 4492 res = []
4484 4493 prefix = "data/"
4485 4494 suffix = ".i"
4486 4495 plen = len(prefix)
4487 4496 slen = len(suffix)
4488 4497 lock = repo.lock()
4489 4498 try:
4490 4499 for fn, b, size in repo.store.datafiles():
4491 4500 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4492 4501 res.append(fn[plen:-slen])
4493 4502 finally:
4494 4503 lock.release()
4495 4504 for f in res:
4496 4505 fm.startitem()
4497 4506 fm.write("path", '%s\n', f)
4498 4507 fm.end()
4499 4508 return
4500 4509
4501 4510 if rev and node:
4502 4511 raise util.Abort(_("please specify just one revision"))
4503 4512
4504 4513 if not node:
4505 4514 node = rev
4506 4515
4507 4516 char = {'l': '@', 'x': '*', '': ''}
4508 4517 mode = {'l': '644', 'x': '755', '': '644'}
4509 4518 ctx = scmutil.revsingle(repo, node)
4510 4519 mf = ctx.manifest()
4511 4520 for f in ctx:
4512 4521 fm.startitem()
4513 4522 fl = ctx[f].flags()
4514 4523 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4515 4524 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4516 4525 fm.write('path', '%s\n', f)
4517 4526 fm.end()
4518 4527
4519 4528 @command('^merge',
4520 4529 [('f', 'force', None,
4521 4530 _('force a merge including outstanding changes (DEPRECATED)')),
4522 4531 ('r', 'rev', '', _('revision to merge'), _('REV')),
4523 4532 ('P', 'preview', None,
4524 4533 _('review revisions to merge (no merge is performed)'))
4525 4534 ] + mergetoolopts,
4526 4535 _('[-P] [-f] [[-r] REV]'))
4527 4536 def merge(ui, repo, node=None, **opts):
4528 4537 """merge working directory with another revision
4529 4538
4530 4539 The current working directory is updated with all changes made in
4531 4540 the requested revision since the last common predecessor revision.
4532 4541
4533 4542 Files that changed between either parent are marked as changed for
4534 4543 the next commit and a commit must be performed before any further
4535 4544 updates to the repository are allowed. The next commit will have
4536 4545 two parents.
4537 4546
4538 4547 ``--tool`` can be used to specify the merge tool used for file
4539 4548 merges. It overrides the HGMERGE environment variable and your
4540 4549 configuration files. See :hg:`help merge-tools` for options.
4541 4550
4542 4551 If no revision is specified, the working directory's parent is a
4543 4552 head revision, and the current branch contains exactly one other
4544 4553 head, the other head is merged with by default. Otherwise, an
4545 4554 explicit revision with which to merge with must be provided.
4546 4555
4547 4556 :hg:`resolve` must be used to resolve unresolved files.
4548 4557
4549 4558 To undo an uncommitted merge, use :hg:`update --clean .` which
4550 4559 will check out a clean copy of the original merge parent, losing
4551 4560 all changes.
4552 4561
4553 4562 Returns 0 on success, 1 if there are unresolved files.
4554 4563 """
4555 4564
4556 4565 if opts.get('rev') and node:
4557 4566 raise util.Abort(_("please specify just one revision"))
4558 4567 if not node:
4559 4568 node = opts.get('rev')
4560 4569
4561 4570 if node:
4562 4571 node = scmutil.revsingle(repo, node).node()
4563 4572
4564 4573 if not node and repo._bookmarkcurrent:
4565 4574 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4566 4575 curhead = repo[repo._bookmarkcurrent].node()
4567 4576 if len(bmheads) == 2:
4568 4577 if curhead == bmheads[0]:
4569 4578 node = bmheads[1]
4570 4579 else:
4571 4580 node = bmheads[0]
4572 4581 elif len(bmheads) > 2:
4573 4582 raise util.Abort(_("multiple matching bookmarks to merge - "
4574 4583 "please merge with an explicit rev or bookmark"),
4575 4584 hint=_("run 'hg heads' to see all heads"))
4576 4585 elif len(bmheads) <= 1:
4577 4586 raise util.Abort(_("no matching bookmark to merge - "
4578 4587 "please merge with an explicit rev or bookmark"),
4579 4588 hint=_("run 'hg heads' to see all heads"))
4580 4589
4581 4590 if not node and not repo._bookmarkcurrent:
4582 4591 branch = repo[None].branch()
4583 4592 bheads = repo.branchheads(branch)
4584 4593 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4585 4594
4586 4595 if len(nbhs) > 2:
4587 4596 raise util.Abort(_("branch '%s' has %d heads - "
4588 4597 "please merge with an explicit rev")
4589 4598 % (branch, len(bheads)),
4590 4599 hint=_("run 'hg heads .' to see heads"))
4591 4600
4592 4601 parent = repo.dirstate.p1()
4593 4602 if len(nbhs) <= 1:
4594 4603 if len(bheads) > 1:
4595 4604 raise util.Abort(_("heads are bookmarked - "
4596 4605 "please merge with an explicit rev"),
4597 4606 hint=_("run 'hg heads' to see all heads"))
4598 4607 if len(repo.heads()) > 1:
4599 4608 raise util.Abort(_("branch '%s' has one head - "
4600 4609 "please merge with an explicit rev")
4601 4610 % branch,
4602 4611 hint=_("run 'hg heads' to see all heads"))
4603 4612 msg, hint = _('nothing to merge'), None
4604 4613 if parent != repo.lookup(branch):
4605 4614 hint = _("use 'hg update' instead")
4606 4615 raise util.Abort(msg, hint=hint)
4607 4616
4608 4617 if parent not in bheads:
4609 4618 raise util.Abort(_('working directory not at a head revision'),
4610 4619 hint=_("use 'hg update' or merge with an "
4611 4620 "explicit revision"))
4612 4621 if parent == nbhs[0]:
4613 4622 node = nbhs[-1]
4614 4623 else:
4615 4624 node = nbhs[0]
4616 4625
4617 4626 if opts.get('preview'):
4618 4627 # find nodes that are ancestors of p2 but not of p1
4619 4628 p1 = repo.lookup('.')
4620 4629 p2 = repo.lookup(node)
4621 4630 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4622 4631
4623 4632 displayer = cmdutil.show_changeset(ui, repo, opts)
4624 4633 for node in nodes:
4625 4634 displayer.show(repo[node])
4626 4635 displayer.close()
4627 4636 return 0
4628 4637
4629 4638 try:
4630 4639 # ui.forcemerge is an internal variable, do not document
4631 4640 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4632 4641 return hg.merge(repo, node, force=opts.get('force'))
4633 4642 finally:
4634 4643 ui.setconfig('ui', 'forcemerge', '', 'merge')
4635 4644
4636 4645 @command('outgoing|out',
4637 4646 [('f', 'force', None, _('run even when the destination is unrelated')),
4638 4647 ('r', 'rev', [],
4639 4648 _('a changeset intended to be included in the destination'), _('REV')),
4640 4649 ('n', 'newest-first', None, _('show newest record first')),
4641 4650 ('B', 'bookmarks', False, _('compare bookmarks')),
4642 4651 ('b', 'branch', [], _('a specific branch you would like to push'),
4643 4652 _('BRANCH')),
4644 4653 ] + logopts + remoteopts + subrepoopts,
4645 4654 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4646 4655 def outgoing(ui, repo, dest=None, **opts):
4647 4656 """show changesets not found in the destination
4648 4657
4649 4658 Show changesets not found in the specified destination repository
4650 4659 or the default push location. These are the changesets that would
4651 4660 be pushed if a push was requested.
4652 4661
4653 4662 See pull for details of valid destination formats.
4654 4663
4655 4664 Returns 0 if there are outgoing changes, 1 otherwise.
4656 4665 """
4657 4666 if opts.get('graph'):
4658 4667 cmdutil.checkunsupportedgraphflags([], opts)
4659 4668 o, other = hg._outgoing(ui, repo, dest, opts)
4660 4669 if not o:
4661 4670 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4662 4671 return
4663 4672
4664 4673 revdag = cmdutil.graphrevs(repo, o, opts)
4665 4674 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4666 4675 showparents = [ctx.node() for ctx in repo[None].parents()]
4667 4676 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4668 4677 graphmod.asciiedges)
4669 4678 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4670 4679 return 0
4671 4680
4672 4681 if opts.get('bookmarks'):
4673 4682 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4674 4683 dest, branches = hg.parseurl(dest, opts.get('branch'))
4675 4684 other = hg.peer(repo, opts, dest)
4676 4685 if 'bookmarks' not in other.listkeys('namespaces'):
4677 4686 ui.warn(_("remote doesn't support bookmarks\n"))
4678 4687 return 0
4679 4688 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4680 4689 return bookmarks.diff(ui, other, repo)
4681 4690
4682 4691 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4683 4692 try:
4684 4693 return hg.outgoing(ui, repo, dest, opts)
4685 4694 finally:
4686 4695 del repo._subtoppath
4687 4696
4688 4697 @command('parents',
4689 4698 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4690 4699 ] + templateopts,
4691 4700 _('[-r REV] [FILE]'),
4692 4701 inferrepo=True)
4693 4702 def parents(ui, repo, file_=None, **opts):
4694 4703 """show the parents of the working directory or revision (DEPRECATED)
4695 4704
4696 4705 Print the working directory's parent revisions. If a revision is
4697 4706 given via -r/--rev, the parent of that revision will be printed.
4698 4707 If a file argument is given, the revision in which the file was
4699 4708 last changed (before the working directory revision or the
4700 4709 argument to --rev if given) is printed.
4701 4710
4702 4711 See :hg:`summary` and :hg:`help revsets` for related information.
4703 4712
4704 4713 Returns 0 on success.
4705 4714 """
4706 4715
4707 4716 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4708 4717
4709 4718 if file_:
4710 4719 m = scmutil.match(ctx, (file_,), opts)
4711 4720 if m.anypats() or len(m.files()) != 1:
4712 4721 raise util.Abort(_('can only specify an explicit filename'))
4713 4722 file_ = m.files()[0]
4714 4723 filenodes = []
4715 4724 for cp in ctx.parents():
4716 4725 if not cp:
4717 4726 continue
4718 4727 try:
4719 4728 filenodes.append(cp.filenode(file_))
4720 4729 except error.LookupError:
4721 4730 pass
4722 4731 if not filenodes:
4723 4732 raise util.Abort(_("'%s' not found in manifest!") % file_)
4724 4733 p = []
4725 4734 for fn in filenodes:
4726 4735 fctx = repo.filectx(file_, fileid=fn)
4727 4736 p.append(fctx.node())
4728 4737 else:
4729 4738 p = [cp.node() for cp in ctx.parents()]
4730 4739
4731 4740 displayer = cmdutil.show_changeset(ui, repo, opts)
4732 4741 for n in p:
4733 4742 if n != nullid:
4734 4743 displayer.show(repo[n])
4735 4744 displayer.close()
4736 4745
4737 4746 @command('paths', [], _('[NAME]'), optionalrepo=True)
4738 4747 def paths(ui, repo, search=None):
4739 4748 """show aliases for remote repositories
4740 4749
4741 4750 Show definition of symbolic path name NAME. If no name is given,
4742 4751 show definition of all available names.
4743 4752
4744 4753 Option -q/--quiet suppresses all output when searching for NAME
4745 4754 and shows only the path names when listing all definitions.
4746 4755
4747 4756 Path names are defined in the [paths] section of your
4748 4757 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4749 4758 repository, ``.hg/hgrc`` is used, too.
4750 4759
4751 4760 The path names ``default`` and ``default-push`` have a special
4752 4761 meaning. When performing a push or pull operation, they are used
4753 4762 as fallbacks if no location is specified on the command-line.
4754 4763 When ``default-push`` is set, it will be used for push and
4755 4764 ``default`` will be used for pull; otherwise ``default`` is used
4756 4765 as the fallback for both. When cloning a repository, the clone
4757 4766 source is written as ``default`` in ``.hg/hgrc``. Note that
4758 4767 ``default`` and ``default-push`` apply to all inbound (e.g.
4759 4768 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4760 4769 :hg:`bundle`) operations.
4761 4770
4762 4771 See :hg:`help urls` for more information.
4763 4772
4764 4773 Returns 0 on success.
4765 4774 """
4766 4775 if search:
4767 4776 for name, path in ui.configitems("paths"):
4768 4777 if name == search:
4769 4778 ui.status("%s\n" % util.hidepassword(path))
4770 4779 return
4771 4780 if not ui.quiet:
4772 4781 ui.warn(_("not found!\n"))
4773 4782 return 1
4774 4783 else:
4775 4784 for name, path in ui.configitems("paths"):
4776 4785 if ui.quiet:
4777 4786 ui.write("%s\n" % name)
4778 4787 else:
4779 4788 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4780 4789
4781 4790 @command('phase',
4782 4791 [('p', 'public', False, _('set changeset phase to public')),
4783 4792 ('d', 'draft', False, _('set changeset phase to draft')),
4784 4793 ('s', 'secret', False, _('set changeset phase to secret')),
4785 4794 ('f', 'force', False, _('allow to move boundary backward')),
4786 4795 ('r', 'rev', [], _('target revision'), _('REV')),
4787 4796 ],
4788 4797 _('[-p|-d|-s] [-f] [-r] REV...'))
4789 4798 def phase(ui, repo, *revs, **opts):
4790 4799 """set or show the current phase name
4791 4800
4792 4801 With no argument, show the phase name of specified revisions.
4793 4802
4794 4803 With one of -p/--public, -d/--draft or -s/--secret, change the
4795 4804 phase value of the specified revisions.
4796 4805
4797 4806 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4798 4807 lower phase to an higher phase. Phases are ordered as follows::
4799 4808
4800 4809 public < draft < secret
4801 4810
4802 4811 Returns 0 on success, 1 if no phases were changed or some could not
4803 4812 be changed.
4804 4813 """
4805 4814 # search for a unique phase argument
4806 4815 targetphase = None
4807 4816 for idx, name in enumerate(phases.phasenames):
4808 4817 if opts[name]:
4809 4818 if targetphase is not None:
4810 4819 raise util.Abort(_('only one phase can be specified'))
4811 4820 targetphase = idx
4812 4821
4813 4822 # look for specified revision
4814 4823 revs = list(revs)
4815 4824 revs.extend(opts['rev'])
4816 4825 if not revs:
4817 4826 raise util.Abort(_('no revisions specified'))
4818 4827
4819 4828 revs = scmutil.revrange(repo, revs)
4820 4829
4821 4830 lock = None
4822 4831 ret = 0
4823 4832 if targetphase is None:
4824 4833 # display
4825 4834 for r in revs:
4826 4835 ctx = repo[r]
4827 4836 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4828 4837 else:
4829 4838 tr = None
4830 4839 lock = repo.lock()
4831 4840 try:
4832 4841 tr = repo.transaction("phase")
4833 4842 # set phase
4834 4843 if not revs:
4835 4844 raise util.Abort(_('empty revision set'))
4836 4845 nodes = [repo[r].node() for r in revs]
4837 4846 olddata = repo._phasecache.getphaserevs(repo)[:]
4838 4847 phases.advanceboundary(repo, tr, targetphase, nodes)
4839 4848 if opts['force']:
4840 4849 phases.retractboundary(repo, tr, targetphase, nodes)
4841 4850 tr.close()
4842 4851 finally:
4843 4852 if tr is not None:
4844 4853 tr.release()
4845 4854 lock.release()
4846 4855 # moving revision from public to draft may hide them
4847 4856 # We have to check result on an unfiltered repository
4848 4857 unfi = repo.unfiltered()
4849 4858 newdata = repo._phasecache.getphaserevs(unfi)
4850 4859 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4851 4860 cl = unfi.changelog
4852 4861 rejected = [n for n in nodes
4853 4862 if newdata[cl.rev(n)] < targetphase]
4854 4863 if rejected:
4855 4864 ui.warn(_('cannot move %i changesets to a higher '
4856 4865 'phase, use --force\n') % len(rejected))
4857 4866 ret = 1
4858 4867 if changes:
4859 4868 msg = _('phase changed for %i changesets\n') % changes
4860 4869 if ret:
4861 4870 ui.status(msg)
4862 4871 else:
4863 4872 ui.note(msg)
4864 4873 else:
4865 4874 ui.warn(_('no phases changed\n'))
4866 4875 ret = 1
4867 4876 return ret
4868 4877
4869 4878 def postincoming(ui, repo, modheads, optupdate, checkout):
4870 4879 if modheads == 0:
4871 4880 return
4872 4881 if optupdate:
4873 4882 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4874 4883 try:
4875 4884 ret = hg.update(repo, checkout)
4876 4885 except util.Abort, inst:
4877 4886 ui.warn(_("not updating: %s\n") % str(inst))
4878 4887 if inst.hint:
4879 4888 ui.warn(_("(%s)\n") % inst.hint)
4880 4889 return 0
4881 4890 if not ret and not checkout:
4882 4891 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4883 4892 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4884 4893 return ret
4885 4894 if modheads > 1:
4886 4895 currentbranchheads = len(repo.branchheads())
4887 4896 if currentbranchheads == modheads:
4888 4897 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4889 4898 elif currentbranchheads > 1:
4890 4899 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4891 4900 "merge)\n"))
4892 4901 else:
4893 4902 ui.status(_("(run 'hg heads' to see heads)\n"))
4894 4903 else:
4895 4904 ui.status(_("(run 'hg update' to get a working copy)\n"))
4896 4905
4897 4906 @command('^pull',
4898 4907 [('u', 'update', None,
4899 4908 _('update to new branch head if changesets were pulled')),
4900 4909 ('f', 'force', None, _('run even when remote repository is unrelated')),
4901 4910 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4902 4911 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4903 4912 ('b', 'branch', [], _('a specific branch you would like to pull'),
4904 4913 _('BRANCH')),
4905 4914 ] + remoteopts,
4906 4915 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4907 4916 def pull(ui, repo, source="default", **opts):
4908 4917 """pull changes from the specified source
4909 4918
4910 4919 Pull changes from a remote repository to a local one.
4911 4920
4912 4921 This finds all changes from the repository at the specified path
4913 4922 or URL and adds them to a local repository (the current one unless
4914 4923 -R is specified). By default, this does not update the copy of the
4915 4924 project in the working directory.
4916 4925
4917 4926 Use :hg:`incoming` if you want to see what would have been added
4918 4927 by a pull at the time you issued this command. If you then decide
4919 4928 to add those changes to the repository, you should use :hg:`pull
4920 4929 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4921 4930
4922 4931 If SOURCE is omitted, the 'default' path will be used.
4923 4932 See :hg:`help urls` for more information.
4924 4933
4925 4934 Returns 0 on success, 1 if an update had unresolved files.
4926 4935 """
4927 4936 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4928 4937 other = hg.peer(repo, opts, source)
4929 4938 try:
4930 4939 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4931 4940 revs, checkout = hg.addbranchrevs(repo, other, branches,
4932 4941 opts.get('rev'))
4933 4942
4934 4943 remotebookmarks = other.listkeys('bookmarks')
4935 4944
4936 4945 if opts.get('bookmark'):
4937 4946 if not revs:
4938 4947 revs = []
4939 4948 for b in opts['bookmark']:
4940 4949 if b not in remotebookmarks:
4941 4950 raise util.Abort(_('remote bookmark %s not found!') % b)
4942 4951 revs.append(remotebookmarks[b])
4943 4952
4944 4953 if revs:
4945 4954 try:
4946 4955 revs = [other.lookup(rev) for rev in revs]
4947 4956 except error.CapabilityError:
4948 4957 err = _("other repository doesn't support revision lookup, "
4949 4958 "so a rev cannot be specified.")
4950 4959 raise util.Abort(err)
4951 4960
4952 4961 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4953 4962 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4954 4963 if checkout:
4955 4964 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4956 4965 repo._subtoppath = source
4957 4966 try:
4958 4967 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4959 4968
4960 4969 finally:
4961 4970 del repo._subtoppath
4962 4971
4963 4972 # update specified bookmarks
4964 4973 if opts.get('bookmark'):
4965 4974 marks = repo._bookmarks
4966 4975 for b in opts['bookmark']:
4967 4976 # explicit pull overrides local bookmark if any
4968 4977 ui.status(_("importing bookmark %s\n") % b)
4969 4978 marks[b] = repo[remotebookmarks[b]].node()
4970 4979 marks.write()
4971 4980 finally:
4972 4981 other.close()
4973 4982 return ret
4974 4983
4975 4984 @command('^push',
4976 4985 [('f', 'force', None, _('force push')),
4977 4986 ('r', 'rev', [],
4978 4987 _('a changeset intended to be included in the destination'),
4979 4988 _('REV')),
4980 4989 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4981 4990 ('b', 'branch', [],
4982 4991 _('a specific branch you would like to push'), _('BRANCH')),
4983 4992 ('', 'new-branch', False, _('allow pushing a new branch')),
4984 4993 ] + remoteopts,
4985 4994 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4986 4995 def push(ui, repo, dest=None, **opts):
4987 4996 """push changes to the specified destination
4988 4997
4989 4998 Push changesets from the local repository to the specified
4990 4999 destination.
4991 5000
4992 5001 This operation is symmetrical to pull: it is identical to a pull
4993 5002 in the destination repository from the current one.
4994 5003
4995 5004 By default, push will not allow creation of new heads at the
4996 5005 destination, since multiple heads would make it unclear which head
4997 5006 to use. In this situation, it is recommended to pull and merge
4998 5007 before pushing.
4999 5008
5000 5009 Use --new-branch if you want to allow push to create a new named
5001 5010 branch that is not present at the destination. This allows you to
5002 5011 only create a new branch without forcing other changes.
5003 5012
5004 5013 .. note::
5005 5014
5006 5015 Extra care should be taken with the -f/--force option,
5007 5016 which will push all new heads on all branches, an action which will
5008 5017 almost always cause confusion for collaborators.
5009 5018
5010 5019 If -r/--rev is used, the specified revision and all its ancestors
5011 5020 will be pushed to the remote repository.
5012 5021
5013 5022 If -B/--bookmark is used, the specified bookmarked revision, its
5014 5023 ancestors, and the bookmark will be pushed to the remote
5015 5024 repository.
5016 5025
5017 5026 Please see :hg:`help urls` for important details about ``ssh://``
5018 5027 URLs. If DESTINATION is omitted, a default path will be used.
5019 5028
5020 5029 Returns 0 if push was successful, 1 if nothing to push.
5021 5030 """
5022 5031
5023 5032 if opts.get('bookmark'):
5024 5033 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5025 5034 for b in opts['bookmark']:
5026 5035 # translate -B options to -r so changesets get pushed
5027 5036 if b in repo._bookmarks:
5028 5037 opts.setdefault('rev', []).append(b)
5029 5038 else:
5030 5039 # if we try to push a deleted bookmark, translate it to null
5031 5040 # this lets simultaneous -r, -b options continue working
5032 5041 opts.setdefault('rev', []).append("null")
5033 5042
5034 5043 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5035 5044 dest, branches = hg.parseurl(dest, opts.get('branch'))
5036 5045 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5037 5046 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5038 5047 try:
5039 5048 other = hg.peer(repo, opts, dest)
5040 5049 except error.RepoError:
5041 5050 if dest == "default-push":
5042 5051 raise util.Abort(_("default repository not configured!"),
5043 5052 hint=_('see the "path" section in "hg help config"'))
5044 5053 else:
5045 5054 raise
5046 5055
5047 5056 if revs:
5048 5057 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5049 5058
5050 5059 repo._subtoppath = dest
5051 5060 try:
5052 5061 # push subrepos depth-first for coherent ordering
5053 5062 c = repo['']
5054 5063 subs = c.substate # only repos that are committed
5055 5064 for s in sorted(subs):
5056 5065 result = c.sub(s).push(opts)
5057 5066 if result == 0:
5058 5067 return not result
5059 5068 finally:
5060 5069 del repo._subtoppath
5061 5070 result = repo.push(other, opts.get('force'), revs=revs,
5062 5071 newbranch=opts.get('new_branch'))
5063 5072
5064 5073 result = not result
5065 5074
5066 5075 if opts.get('bookmark'):
5067 5076 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
5068 5077 if bresult == 2:
5069 5078 return 2
5070 5079 if not result and bresult:
5071 5080 result = 2
5072 5081
5073 5082 return result
5074 5083
5075 5084 @command('recover', [])
5076 5085 def recover(ui, repo):
5077 5086 """roll back an interrupted transaction
5078 5087
5079 5088 Recover from an interrupted commit or pull.
5080 5089
5081 5090 This command tries to fix the repository status after an
5082 5091 interrupted operation. It should only be necessary when Mercurial
5083 5092 suggests it.
5084 5093
5085 5094 Returns 0 if successful, 1 if nothing to recover or verify fails.
5086 5095 """
5087 5096 if repo.recover():
5088 5097 return hg.verify(repo)
5089 5098 return 1
5090 5099
5091 5100 @command('^remove|rm',
5092 5101 [('A', 'after', None, _('record delete for missing files')),
5093 5102 ('f', 'force', None,
5094 5103 _('remove (and delete) file even if added or modified')),
5095 5104 ] + walkopts,
5096 5105 _('[OPTION]... FILE...'),
5097 5106 inferrepo=True)
5098 5107 def remove(ui, repo, *pats, **opts):
5099 5108 """remove the specified files on the next commit
5100 5109
5101 5110 Schedule the indicated files for removal from the current branch.
5102 5111
5103 5112 This command schedules the files to be removed at the next commit.
5104 5113 To undo a remove before that, see :hg:`revert`. To undo added
5105 5114 files, see :hg:`forget`.
5106 5115
5107 5116 .. container:: verbose
5108 5117
5109 5118 -A/--after can be used to remove only files that have already
5110 5119 been deleted, -f/--force can be used to force deletion, and -Af
5111 5120 can be used to remove files from the next revision without
5112 5121 deleting them from the working directory.
5113 5122
5114 5123 The following table details the behavior of remove for different
5115 5124 file states (columns) and option combinations (rows). The file
5116 5125 states are Added [A], Clean [C], Modified [M] and Missing [!]
5117 5126 (as reported by :hg:`status`). The actions are Warn, Remove
5118 5127 (from branch) and Delete (from disk):
5119 5128
5120 5129 ========= == == == ==
5121 5130 opt/state A C M !
5122 5131 ========= == == == ==
5123 5132 none W RD W R
5124 5133 -f R RD RD R
5125 5134 -A W W W R
5126 5135 -Af R R R R
5127 5136 ========= == == == ==
5128 5137
5129 5138 Note that remove never deletes files in Added [A] state from the
5130 5139 working directory, not even if option --force is specified.
5131 5140
5132 5141 Returns 0 on success, 1 if any warnings encountered.
5133 5142 """
5134 5143
5135 5144 ret = 0
5136 5145 after, force = opts.get('after'), opts.get('force')
5137 5146 if not pats and not after:
5138 5147 raise util.Abort(_('no files specified'))
5139 5148
5140 5149 m = scmutil.match(repo[None], pats, opts)
5141 5150 s = repo.status(match=m, clean=True)
5142 5151 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5143 5152
5144 5153 # warn about failure to delete explicit files/dirs
5145 5154 wctx = repo[None]
5146 5155 for f in m.files():
5147 5156 if f in repo.dirstate or f in wctx.dirs():
5148 5157 continue
5149 5158 if os.path.exists(m.rel(f)):
5150 5159 if os.path.isdir(m.rel(f)):
5151 5160 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5152 5161 else:
5153 5162 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5154 5163 # missing files will generate a warning elsewhere
5155 5164 ret = 1
5156 5165
5157 5166 if force:
5158 5167 list = modified + deleted + clean + added
5159 5168 elif after:
5160 5169 list = deleted
5161 5170 for f in modified + added + clean:
5162 5171 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5163 5172 ret = 1
5164 5173 else:
5165 5174 list = deleted + clean
5166 5175 for f in modified:
5167 5176 ui.warn(_('not removing %s: file is modified (use -f'
5168 5177 ' to force removal)\n') % m.rel(f))
5169 5178 ret = 1
5170 5179 for f in added:
5171 5180 ui.warn(_('not removing %s: file has been marked for add'
5172 5181 ' (use forget to undo)\n') % m.rel(f))
5173 5182 ret = 1
5174 5183
5175 5184 for f in sorted(list):
5176 5185 if ui.verbose or not m.exact(f):
5177 5186 ui.status(_('removing %s\n') % m.rel(f))
5178 5187
5179 5188 wlock = repo.wlock()
5180 5189 try:
5181 5190 if not after:
5182 5191 for f in list:
5183 5192 if f in added:
5184 5193 continue # we never unlink added files on remove
5185 5194 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5186 5195 repo[None].forget(list)
5187 5196 finally:
5188 5197 wlock.release()
5189 5198
5190 5199 return ret
5191 5200
5192 5201 @command('rename|move|mv',
5193 5202 [('A', 'after', None, _('record a rename that has already occurred')),
5194 5203 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5195 5204 ] + walkopts + dryrunopts,
5196 5205 _('[OPTION]... SOURCE... DEST'))
5197 5206 def rename(ui, repo, *pats, **opts):
5198 5207 """rename files; equivalent of copy + remove
5199 5208
5200 5209 Mark dest as copies of sources; mark sources for deletion. If dest
5201 5210 is a directory, copies are put in that directory. If dest is a
5202 5211 file, there can only be one source.
5203 5212
5204 5213 By default, this command copies the contents of files as they
5205 5214 exist in the working directory. If invoked with -A/--after, the
5206 5215 operation is recorded, but no copying is performed.
5207 5216
5208 5217 This command takes effect at the next commit. To undo a rename
5209 5218 before that, see :hg:`revert`.
5210 5219
5211 5220 Returns 0 on success, 1 if errors are encountered.
5212 5221 """
5213 5222 wlock = repo.wlock(False)
5214 5223 try:
5215 5224 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5216 5225 finally:
5217 5226 wlock.release()
5218 5227
5219 5228 @command('resolve',
5220 5229 [('a', 'all', None, _('select all unresolved files')),
5221 5230 ('l', 'list', None, _('list state of files needing merge')),
5222 5231 ('m', 'mark', None, _('mark files as resolved')),
5223 5232 ('u', 'unmark', None, _('mark files as unresolved')),
5224 5233 ('n', 'no-status', None, _('hide status prefix'))]
5225 5234 + mergetoolopts + walkopts,
5226 5235 _('[OPTION]... [FILE]...'),
5227 5236 inferrepo=True)
5228 5237 def resolve(ui, repo, *pats, **opts):
5229 5238 """redo merges or set/view the merge status of files
5230 5239
5231 5240 Merges with unresolved conflicts are often the result of
5232 5241 non-interactive merging using the ``internal:merge`` configuration
5233 5242 setting, or a command-line merge tool like ``diff3``. The resolve
5234 5243 command is used to manage the files involved in a merge, after
5235 5244 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5236 5245 working directory must have two parents). See :hg:`help
5237 5246 merge-tools` for information on configuring merge tools.
5238 5247
5239 5248 The resolve command can be used in the following ways:
5240 5249
5241 5250 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5242 5251 files, discarding any previous merge attempts. Re-merging is not
5243 5252 performed for files already marked as resolved. Use ``--all/-a``
5244 5253 to select all unresolved files. ``--tool`` can be used to specify
5245 5254 the merge tool used for the given files. It overrides the HGMERGE
5246 5255 environment variable and your configuration files. Previous file
5247 5256 contents are saved with a ``.orig`` suffix.
5248 5257
5249 5258 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5250 5259 (e.g. after having manually fixed-up the files). The default is
5251 5260 to mark all unresolved files.
5252 5261
5253 5262 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5254 5263 default is to mark all resolved files.
5255 5264
5256 5265 - :hg:`resolve -l`: list files which had or still have conflicts.
5257 5266 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5258 5267
5259 5268 Note that Mercurial will not let you commit files with unresolved
5260 5269 merge conflicts. You must use :hg:`resolve -m ...` before you can
5261 5270 commit after a conflicting merge.
5262 5271
5263 5272 Returns 0 on success, 1 if any files fail a resolve attempt.
5264 5273 """
5265 5274
5266 5275 all, mark, unmark, show, nostatus = \
5267 5276 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5268 5277
5269 5278 if (show and (mark or unmark)) or (mark and unmark):
5270 5279 raise util.Abort(_("too many options specified"))
5271 5280 if pats and all:
5272 5281 raise util.Abort(_("can't specify --all and patterns"))
5273 5282 if not (all or pats or show or mark or unmark):
5274 5283 raise util.Abort(_('no files or directories specified'),
5275 5284 hint=('use --all to remerge all files'))
5276 5285
5277 5286 wlock = repo.wlock()
5278 5287 try:
5279 5288 ms = mergemod.mergestate(repo)
5280 5289
5281 5290 if not ms.active() and not show:
5282 5291 raise util.Abort(
5283 5292 _('resolve command not applicable when not merging'))
5284 5293
5285 5294 m = scmutil.match(repo[None], pats, opts)
5286 5295 ret = 0
5287 5296 didwork = False
5288 5297
5289 5298 for f in ms:
5290 5299 if not m(f):
5291 5300 continue
5292 5301
5293 5302 didwork = True
5294 5303
5295 5304 if show:
5296 5305 if nostatus:
5297 5306 ui.write("%s\n" % f)
5298 5307 else:
5299 5308 ui.write("%s %s\n" % (ms[f].upper(), f),
5300 5309 label='resolve.' +
5301 5310 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5302 5311 elif mark:
5303 5312 ms.mark(f, "r")
5304 5313 elif unmark:
5305 5314 ms.mark(f, "u")
5306 5315 else:
5307 5316 wctx = repo[None]
5308 5317
5309 5318 # backup pre-resolve (merge uses .orig for its own purposes)
5310 5319 a = repo.wjoin(f)
5311 5320 util.copyfile(a, a + ".resolve")
5312 5321
5313 5322 try:
5314 5323 # resolve file
5315 5324 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5316 5325 'resolve')
5317 5326 if ms.resolve(f, wctx):
5318 5327 ret = 1
5319 5328 finally:
5320 5329 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5321 5330 ms.commit()
5322 5331
5323 5332 # replace filemerge's .orig file with our resolve file
5324 5333 util.rename(a + ".resolve", a + ".orig")
5325 5334
5326 5335 ms.commit()
5327 5336
5328 5337 if not didwork and pats:
5329 5338 ui.warn(_("arguments do not match paths that need resolving\n"))
5330 5339
5331 5340 finally:
5332 5341 wlock.release()
5333 5342
5334 5343 # Nudge users into finishing an unfinished operation. We don't print
5335 5344 # this with the list/show operation because we want list/show to remain
5336 5345 # machine readable.
5337 5346 if not list(ms.unresolved()) and not show:
5338 5347 ui.status(_('(no more unresolved files)\n'))
5339 5348
5340 5349 return ret
5341 5350
5342 5351 @command('revert',
5343 5352 [('a', 'all', None, _('revert all changes when no arguments given')),
5344 5353 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5345 5354 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5346 5355 ('C', 'no-backup', None, _('do not save backup copies of files')),
5347 5356 ] + walkopts + dryrunopts,
5348 5357 _('[OPTION]... [-r REV] [NAME]...'))
5349 5358 def revert(ui, repo, *pats, **opts):
5350 5359 """restore files to their checkout state
5351 5360
5352 5361 .. note::
5353 5362
5354 5363 To check out earlier revisions, you should use :hg:`update REV`.
5355 5364 To cancel an uncommitted merge (and lose your changes),
5356 5365 use :hg:`update --clean .`.
5357 5366
5358 5367 With no revision specified, revert the specified files or directories
5359 5368 to the contents they had in the parent of the working directory.
5360 5369 This restores the contents of files to an unmodified
5361 5370 state and unschedules adds, removes, copies, and renames. If the
5362 5371 working directory has two parents, you must explicitly specify a
5363 5372 revision.
5364 5373
5365 5374 Using the -r/--rev or -d/--date options, revert the given files or
5366 5375 directories to their states as of a specific revision. Because
5367 5376 revert does not change the working directory parents, this will
5368 5377 cause these files to appear modified. This can be helpful to "back
5369 5378 out" some or all of an earlier change. See :hg:`backout` for a
5370 5379 related method.
5371 5380
5372 5381 Modified files are saved with a .orig suffix before reverting.
5373 5382 To disable these backups, use --no-backup.
5374 5383
5375 5384 See :hg:`help dates` for a list of formats valid for -d/--date.
5376 5385
5377 5386 Returns 0 on success.
5378 5387 """
5379 5388
5380 5389 if opts.get("date"):
5381 5390 if opts.get("rev"):
5382 5391 raise util.Abort(_("you can't specify a revision and a date"))
5383 5392 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5384 5393
5385 5394 parent, p2 = repo.dirstate.parents()
5386 5395 if not opts.get('rev') and p2 != nullid:
5387 5396 # revert after merge is a trap for new users (issue2915)
5388 5397 raise util.Abort(_('uncommitted merge with no revision specified'),
5389 5398 hint=_('use "hg update" or see "hg help revert"'))
5390 5399
5391 5400 ctx = scmutil.revsingle(repo, opts.get('rev'))
5392 5401
5393 5402 if not pats and not opts.get('all'):
5394 5403 msg = _("no files or directories specified")
5395 5404 if p2 != nullid:
5396 5405 hint = _("uncommitted merge, use --all to discard all changes,"
5397 5406 " or 'hg update -C .' to abort the merge")
5398 5407 raise util.Abort(msg, hint=hint)
5399 5408 dirty = util.any(repo.status())
5400 5409 node = ctx.node()
5401 5410 if node != parent:
5402 5411 if dirty:
5403 5412 hint = _("uncommitted changes, use --all to discard all"
5404 5413 " changes, or 'hg update %s' to update") % ctx.rev()
5405 5414 else:
5406 5415 hint = _("use --all to revert all files,"
5407 5416 " or 'hg update %s' to update") % ctx.rev()
5408 5417 elif dirty:
5409 5418 hint = _("uncommitted changes, use --all to discard all changes")
5410 5419 else:
5411 5420 hint = _("use --all to revert all files")
5412 5421 raise util.Abort(msg, hint=hint)
5413 5422
5414 5423 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5415 5424
5416 5425 @command('rollback', dryrunopts +
5417 5426 [('f', 'force', False, _('ignore safety measures'))])
5418 5427 def rollback(ui, repo, **opts):
5419 5428 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5420 5429
5421 5430 Please use :hg:`commit --amend` instead of rollback to correct
5422 5431 mistakes in the last commit.
5423 5432
5424 5433 This command should be used with care. There is only one level of
5425 5434 rollback, and there is no way to undo a rollback. It will also
5426 5435 restore the dirstate at the time of the last transaction, losing
5427 5436 any dirstate changes since that time. This command does not alter
5428 5437 the working directory.
5429 5438
5430 5439 Transactions are used to encapsulate the effects of all commands
5431 5440 that create new changesets or propagate existing changesets into a
5432 5441 repository.
5433 5442
5434 5443 .. container:: verbose
5435 5444
5436 5445 For example, the following commands are transactional, and their
5437 5446 effects can be rolled back:
5438 5447
5439 5448 - commit
5440 5449 - import
5441 5450 - pull
5442 5451 - push (with this repository as the destination)
5443 5452 - unbundle
5444 5453
5445 5454 To avoid permanent data loss, rollback will refuse to rollback a
5446 5455 commit transaction if it isn't checked out. Use --force to
5447 5456 override this protection.
5448 5457
5449 5458 This command is not intended for use on public repositories. Once
5450 5459 changes are visible for pull by other users, rolling a transaction
5451 5460 back locally is ineffective (someone else may already have pulled
5452 5461 the changes). Furthermore, a race is possible with readers of the
5453 5462 repository; for example an in-progress pull from the repository
5454 5463 may fail if a rollback is performed.
5455 5464
5456 5465 Returns 0 on success, 1 if no rollback data is available.
5457 5466 """
5458 5467 return repo.rollback(dryrun=opts.get('dry_run'),
5459 5468 force=opts.get('force'))
5460 5469
5461 5470 @command('root', [])
5462 5471 def root(ui, repo):
5463 5472 """print the root (top) of the current working directory
5464 5473
5465 5474 Print the root directory of the current repository.
5466 5475
5467 5476 Returns 0 on success.
5468 5477 """
5469 5478 ui.write(repo.root + "\n")
5470 5479
5471 5480 @command('^serve',
5472 5481 [('A', 'accesslog', '', _('name of access log file to write to'),
5473 5482 _('FILE')),
5474 5483 ('d', 'daemon', None, _('run server in background')),
5475 5484 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5476 5485 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5477 5486 # use string type, then we can check if something was passed
5478 5487 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5479 5488 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5480 5489 _('ADDR')),
5481 5490 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5482 5491 _('PREFIX')),
5483 5492 ('n', 'name', '',
5484 5493 _('name to show in web pages (default: working directory)'), _('NAME')),
5485 5494 ('', 'web-conf', '',
5486 5495 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5487 5496 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5488 5497 _('FILE')),
5489 5498 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5490 5499 ('', 'stdio', None, _('for remote clients')),
5491 5500 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5492 5501 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5493 5502 ('', 'style', '', _('template style to use'), _('STYLE')),
5494 5503 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5495 5504 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5496 5505 _('[OPTION]...'),
5497 5506 optionalrepo=True)
5498 5507 def serve(ui, repo, **opts):
5499 5508 """start stand-alone webserver
5500 5509
5501 5510 Start a local HTTP repository browser and pull server. You can use
5502 5511 this for ad-hoc sharing and browsing of repositories. It is
5503 5512 recommended to use a real web server to serve a repository for
5504 5513 longer periods of time.
5505 5514
5506 5515 Please note that the server does not implement access control.
5507 5516 This means that, by default, anybody can read from the server and
5508 5517 nobody can write to it by default. Set the ``web.allow_push``
5509 5518 option to ``*`` to allow everybody to push to the server. You
5510 5519 should use a real web server if you need to authenticate users.
5511 5520
5512 5521 By default, the server logs accesses to stdout and errors to
5513 5522 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5514 5523 files.
5515 5524
5516 5525 To have the server choose a free port number to listen on, specify
5517 5526 a port number of 0; in this case, the server will print the port
5518 5527 number it uses.
5519 5528
5520 5529 Returns 0 on success.
5521 5530 """
5522 5531
5523 5532 if opts["stdio"] and opts["cmdserver"]:
5524 5533 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5525 5534
5526 5535 if opts["stdio"]:
5527 5536 if repo is None:
5528 5537 raise error.RepoError(_("there is no Mercurial repository here"
5529 5538 " (.hg not found)"))
5530 5539 s = sshserver.sshserver(ui, repo)
5531 5540 s.serve_forever()
5532 5541
5533 5542 if opts["cmdserver"]:
5534 5543 s = commandserver.server(ui, repo, opts["cmdserver"])
5535 5544 return s.serve()
5536 5545
5537 5546 # this way we can check if something was given in the command-line
5538 5547 if opts.get('port'):
5539 5548 opts['port'] = util.getport(opts.get('port'))
5540 5549
5541 5550 baseui = repo and repo.baseui or ui
5542 5551 optlist = ("name templates style address port prefix ipv6"
5543 5552 " accesslog errorlog certificate encoding")
5544 5553 for o in optlist.split():
5545 5554 val = opts.get(o, '')
5546 5555 if val in (None, ''): # should check against default options instead
5547 5556 continue
5548 5557 baseui.setconfig("web", o, val, 'serve')
5549 5558 if repo and repo.ui != baseui:
5550 5559 repo.ui.setconfig("web", o, val, 'serve')
5551 5560
5552 5561 o = opts.get('web_conf') or opts.get('webdir_conf')
5553 5562 if not o:
5554 5563 if not repo:
5555 5564 raise error.RepoError(_("there is no Mercurial repository"
5556 5565 " here (.hg not found)"))
5557 5566 o = repo
5558 5567
5559 5568 app = hgweb.hgweb(o, baseui=baseui)
5560 5569 service = httpservice(ui, app, opts)
5561 5570 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5562 5571
5563 5572 class httpservice(object):
5564 5573 def __init__(self, ui, app, opts):
5565 5574 self.ui = ui
5566 5575 self.app = app
5567 5576 self.opts = opts
5568 5577
5569 5578 def init(self):
5570 5579 util.setsignalhandler()
5571 5580 self.httpd = hgweb_server.create_server(self.ui, self.app)
5572 5581
5573 5582 if self.opts['port'] and not self.ui.verbose:
5574 5583 return
5575 5584
5576 5585 if self.httpd.prefix:
5577 5586 prefix = self.httpd.prefix.strip('/') + '/'
5578 5587 else:
5579 5588 prefix = ''
5580 5589
5581 5590 port = ':%d' % self.httpd.port
5582 5591 if port == ':80':
5583 5592 port = ''
5584 5593
5585 5594 bindaddr = self.httpd.addr
5586 5595 if bindaddr == '0.0.0.0':
5587 5596 bindaddr = '*'
5588 5597 elif ':' in bindaddr: # IPv6
5589 5598 bindaddr = '[%s]' % bindaddr
5590 5599
5591 5600 fqaddr = self.httpd.fqaddr
5592 5601 if ':' in fqaddr:
5593 5602 fqaddr = '[%s]' % fqaddr
5594 5603 if self.opts['port']:
5595 5604 write = self.ui.status
5596 5605 else:
5597 5606 write = self.ui.write
5598 5607 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5599 5608 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5600 5609 self.ui.flush() # avoid buffering of status message
5601 5610
5602 5611 def run(self):
5603 5612 self.httpd.serve_forever()
5604 5613
5605 5614
5606 5615 @command('^status|st',
5607 5616 [('A', 'all', None, _('show status of all files')),
5608 5617 ('m', 'modified', None, _('show only modified files')),
5609 5618 ('a', 'added', None, _('show only added files')),
5610 5619 ('r', 'removed', None, _('show only removed files')),
5611 5620 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5612 5621 ('c', 'clean', None, _('show only files without changes')),
5613 5622 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5614 5623 ('i', 'ignored', None, _('show only ignored files')),
5615 5624 ('n', 'no-status', None, _('hide status prefix')),
5616 5625 ('C', 'copies', None, _('show source of copied files')),
5617 5626 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5618 5627 ('', 'rev', [], _('show difference from revision'), _('REV')),
5619 5628 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5620 5629 ] + walkopts + subrepoopts + formatteropts,
5621 5630 _('[OPTION]... [FILE]...'),
5622 5631 inferrepo=True)
5623 5632 def status(ui, repo, *pats, **opts):
5624 5633 """show changed files in the working directory
5625 5634
5626 5635 Show status of files in the repository. If names are given, only
5627 5636 files that match are shown. Files that are clean or ignored or
5628 5637 the source of a copy/move operation, are not listed unless
5629 5638 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5630 5639 Unless options described with "show only ..." are given, the
5631 5640 options -mardu are used.
5632 5641
5633 5642 Option -q/--quiet hides untracked (unknown and ignored) files
5634 5643 unless explicitly requested with -u/--unknown or -i/--ignored.
5635 5644
5636 5645 .. note::
5637 5646
5638 5647 status may appear to disagree with diff if permissions have
5639 5648 changed or a merge has occurred. The standard diff format does
5640 5649 not report permission changes and diff only reports changes
5641 5650 relative to one merge parent.
5642 5651
5643 5652 If one revision is given, it is used as the base revision.
5644 5653 If two revisions are given, the differences between them are
5645 5654 shown. The --change option can also be used as a shortcut to list
5646 5655 the changed files of a revision from its first parent.
5647 5656
5648 5657 The codes used to show the status of files are::
5649 5658
5650 5659 M = modified
5651 5660 A = added
5652 5661 R = removed
5653 5662 C = clean
5654 5663 ! = missing (deleted by non-hg command, but still tracked)
5655 5664 ? = not tracked
5656 5665 I = ignored
5657 5666 = origin of the previous file (with --copies)
5658 5667
5659 5668 .. container:: verbose
5660 5669
5661 5670 Examples:
5662 5671
5663 5672 - show changes in the working directory relative to a
5664 5673 changeset::
5665 5674
5666 5675 hg status --rev 9353
5667 5676
5668 5677 - show all changes including copies in an existing changeset::
5669 5678
5670 5679 hg status --copies --change 9353
5671 5680
5672 5681 - get a NUL separated list of added files, suitable for xargs::
5673 5682
5674 5683 hg status -an0
5675 5684
5676 5685 Returns 0 on success.
5677 5686 """
5678 5687
5679 5688 revs = opts.get('rev')
5680 5689 change = opts.get('change')
5681 5690
5682 5691 if revs and change:
5683 5692 msg = _('cannot specify --rev and --change at the same time')
5684 5693 raise util.Abort(msg)
5685 5694 elif change:
5686 5695 node2 = scmutil.revsingle(repo, change, None).node()
5687 5696 node1 = repo[node2].p1().node()
5688 5697 else:
5689 5698 node1, node2 = scmutil.revpair(repo, revs)
5690 5699
5691 5700 cwd = (pats and repo.getcwd()) or ''
5692 5701 end = opts.get('print0') and '\0' or '\n'
5693 5702 copy = {}
5694 5703 states = 'modified added removed deleted unknown ignored clean'.split()
5695 5704 show = [k for k in states if opts.get(k)]
5696 5705 if opts.get('all'):
5697 5706 show += ui.quiet and (states[:4] + ['clean']) or states
5698 5707 if not show:
5699 5708 show = ui.quiet and states[:4] or states[:5]
5700 5709
5701 5710 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5702 5711 'ignored' in show, 'clean' in show, 'unknown' in show,
5703 5712 opts.get('subrepos'))
5704 5713 changestates = zip(states, 'MAR!?IC', stat)
5705 5714
5706 5715 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5707 5716 copy = copies.pathcopies(repo[node1], repo[node2])
5708 5717
5709 5718 fm = ui.formatter('status', opts)
5710 5719 fmt = '%s' + end
5711 5720 showchar = not opts.get('no_status')
5712 5721
5713 5722 for state, char, files in changestates:
5714 5723 if state in show:
5715 5724 label = 'status.' + state
5716 5725 for f in files:
5717 5726 fm.startitem()
5718 5727 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5719 5728 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5720 5729 if f in copy:
5721 5730 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5722 5731 label='status.copied')
5723 5732 fm.end()
5724 5733
5725 5734 @command('^summary|sum',
5726 5735 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5727 5736 def summary(ui, repo, **opts):
5728 5737 """summarize working directory state
5729 5738
5730 5739 This generates a brief summary of the working directory state,
5731 5740 including parents, branch, commit status, and available updates.
5732 5741
5733 5742 With the --remote option, this will check the default paths for
5734 5743 incoming and outgoing changes. This can be time-consuming.
5735 5744
5736 5745 Returns 0 on success.
5737 5746 """
5738 5747
5739 5748 ctx = repo[None]
5740 5749 parents = ctx.parents()
5741 5750 pnode = parents[0].node()
5742 5751 marks = []
5743 5752
5744 5753 for p in parents:
5745 5754 # label with log.changeset (instead of log.parent) since this
5746 5755 # shows a working directory parent *changeset*:
5747 5756 # i18n: column positioning for "hg summary"
5748 5757 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5749 5758 label='log.changeset changeset.%s' % p.phasestr())
5750 5759 ui.write(' '.join(p.tags()), label='log.tag')
5751 5760 if p.bookmarks():
5752 5761 marks.extend(p.bookmarks())
5753 5762 if p.rev() == -1:
5754 5763 if not len(repo):
5755 5764 ui.write(_(' (empty repository)'))
5756 5765 else:
5757 5766 ui.write(_(' (no revision checked out)'))
5758 5767 ui.write('\n')
5759 5768 if p.description():
5760 5769 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5761 5770 label='log.summary')
5762 5771
5763 5772 branch = ctx.branch()
5764 5773 bheads = repo.branchheads(branch)
5765 5774 # i18n: column positioning for "hg summary"
5766 5775 m = _('branch: %s\n') % branch
5767 5776 if branch != 'default':
5768 5777 ui.write(m, label='log.branch')
5769 5778 else:
5770 5779 ui.status(m, label='log.branch')
5771 5780
5772 5781 if marks:
5773 5782 current = repo._bookmarkcurrent
5774 5783 # i18n: column positioning for "hg summary"
5775 5784 ui.write(_('bookmarks:'), label='log.bookmark')
5776 5785 if current is not None:
5777 5786 if current in marks:
5778 5787 ui.write(' *' + current, label='bookmarks.current')
5779 5788 marks.remove(current)
5780 5789 else:
5781 5790 ui.write(' [%s]' % current, label='bookmarks.current')
5782 5791 for m in marks:
5783 5792 ui.write(' ' + m, label='log.bookmark')
5784 5793 ui.write('\n', label='log.bookmark')
5785 5794
5786 5795 st = list(repo.status(unknown=True))[:6]
5787 5796
5788 5797 c = repo.dirstate.copies()
5789 5798 copied, renamed = [], []
5790 5799 for d, s in c.iteritems():
5791 5800 if s in st[2]:
5792 5801 st[2].remove(s)
5793 5802 renamed.append(d)
5794 5803 else:
5795 5804 copied.append(d)
5796 5805 if d in st[1]:
5797 5806 st[1].remove(d)
5798 5807 st.insert(3, renamed)
5799 5808 st.insert(4, copied)
5800 5809
5801 5810 ms = mergemod.mergestate(repo)
5802 5811 st.append([f for f in ms if ms[f] == 'u'])
5803 5812
5804 5813 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5805 5814 st.append(subs)
5806 5815
5807 5816 labels = [ui.label(_('%d modified'), 'status.modified'),
5808 5817 ui.label(_('%d added'), 'status.added'),
5809 5818 ui.label(_('%d removed'), 'status.removed'),
5810 5819 ui.label(_('%d renamed'), 'status.copied'),
5811 5820 ui.label(_('%d copied'), 'status.copied'),
5812 5821 ui.label(_('%d deleted'), 'status.deleted'),
5813 5822 ui.label(_('%d unknown'), 'status.unknown'),
5814 5823 ui.label(_('%d ignored'), 'status.ignored'),
5815 5824 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5816 5825 ui.label(_('%d subrepos'), 'status.modified')]
5817 5826 t = []
5818 5827 for s, l in zip(st, labels):
5819 5828 if s:
5820 5829 t.append(l % len(s))
5821 5830
5822 5831 t = ', '.join(t)
5823 5832 cleanworkdir = False
5824 5833
5825 5834 if repo.vfs.exists('updatestate'):
5826 5835 t += _(' (interrupted update)')
5827 5836 elif len(parents) > 1:
5828 5837 t += _(' (merge)')
5829 5838 elif branch != parents[0].branch():
5830 5839 t += _(' (new branch)')
5831 5840 elif (parents[0].closesbranch() and
5832 5841 pnode in repo.branchheads(branch, closed=True)):
5833 5842 t += _(' (head closed)')
5834 5843 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5835 5844 t += _(' (clean)')
5836 5845 cleanworkdir = True
5837 5846 elif pnode not in bheads:
5838 5847 t += _(' (new branch head)')
5839 5848
5840 5849 if cleanworkdir:
5841 5850 # i18n: column positioning for "hg summary"
5842 5851 ui.status(_('commit: %s\n') % t.strip())
5843 5852 else:
5844 5853 # i18n: column positioning for "hg summary"
5845 5854 ui.write(_('commit: %s\n') % t.strip())
5846 5855
5847 5856 # all ancestors of branch heads - all ancestors of parent = new csets
5848 5857 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5849 5858 bheads))
5850 5859
5851 5860 if new == 0:
5852 5861 # i18n: column positioning for "hg summary"
5853 5862 ui.status(_('update: (current)\n'))
5854 5863 elif pnode not in bheads:
5855 5864 # i18n: column positioning for "hg summary"
5856 5865 ui.write(_('update: %d new changesets (update)\n') % new)
5857 5866 else:
5858 5867 # i18n: column positioning for "hg summary"
5859 5868 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5860 5869 (new, len(bheads)))
5861 5870
5862 5871 cmdutil.summaryhooks(ui, repo)
5863 5872
5864 5873 if opts.get('remote'):
5865 5874 needsincoming, needsoutgoing = True, True
5866 5875 else:
5867 5876 needsincoming, needsoutgoing = False, False
5868 5877 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5869 5878 if i:
5870 5879 needsincoming = True
5871 5880 if o:
5872 5881 needsoutgoing = True
5873 5882 if not needsincoming and not needsoutgoing:
5874 5883 return
5875 5884
5876 5885 def getincoming():
5877 5886 source, branches = hg.parseurl(ui.expandpath('default'))
5878 5887 sbranch = branches[0]
5879 5888 try:
5880 5889 other = hg.peer(repo, {}, source)
5881 5890 except error.RepoError:
5882 5891 if opts.get('remote'):
5883 5892 raise
5884 5893 return source, sbranch, None, None, None
5885 5894 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5886 5895 if revs:
5887 5896 revs = [other.lookup(rev) for rev in revs]
5888 5897 ui.debug('comparing with %s\n' % util.hidepassword(source))
5889 5898 repo.ui.pushbuffer()
5890 5899 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5891 5900 repo.ui.popbuffer()
5892 5901 return source, sbranch, other, commoninc, commoninc[1]
5893 5902
5894 5903 if needsincoming:
5895 5904 source, sbranch, sother, commoninc, incoming = getincoming()
5896 5905 else:
5897 5906 source = sbranch = sother = commoninc = incoming = None
5898 5907
5899 5908 def getoutgoing():
5900 5909 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5901 5910 dbranch = branches[0]
5902 5911 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5903 5912 if source != dest:
5904 5913 try:
5905 5914 dother = hg.peer(repo, {}, dest)
5906 5915 except error.RepoError:
5907 5916 if opts.get('remote'):
5908 5917 raise
5909 5918 return dest, dbranch, None, None
5910 5919 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5911 5920 elif sother is None:
5912 5921 # there is no explicit destination peer, but source one is invalid
5913 5922 return dest, dbranch, None, None
5914 5923 else:
5915 5924 dother = sother
5916 5925 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5917 5926 common = None
5918 5927 else:
5919 5928 common = commoninc
5920 5929 if revs:
5921 5930 revs = [repo.lookup(rev) for rev in revs]
5922 5931 repo.ui.pushbuffer()
5923 5932 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5924 5933 commoninc=common)
5925 5934 repo.ui.popbuffer()
5926 5935 return dest, dbranch, dother, outgoing
5927 5936
5928 5937 if needsoutgoing:
5929 5938 dest, dbranch, dother, outgoing = getoutgoing()
5930 5939 else:
5931 5940 dest = dbranch = dother = outgoing = None
5932 5941
5933 5942 if opts.get('remote'):
5934 5943 t = []
5935 5944 if incoming:
5936 5945 t.append(_('1 or more incoming'))
5937 5946 o = outgoing.missing
5938 5947 if o:
5939 5948 t.append(_('%d outgoing') % len(o))
5940 5949 other = dother or sother
5941 5950 if 'bookmarks' in other.listkeys('namespaces'):
5942 5951 lmarks = repo.listkeys('bookmarks')
5943 5952 rmarks = other.listkeys('bookmarks')
5944 5953 diff = set(rmarks) - set(lmarks)
5945 5954 if len(diff) > 0:
5946 5955 t.append(_('%d incoming bookmarks') % len(diff))
5947 5956 diff = set(lmarks) - set(rmarks)
5948 5957 if len(diff) > 0:
5949 5958 t.append(_('%d outgoing bookmarks') % len(diff))
5950 5959
5951 5960 if t:
5952 5961 # i18n: column positioning for "hg summary"
5953 5962 ui.write(_('remote: %s\n') % (', '.join(t)))
5954 5963 else:
5955 5964 # i18n: column positioning for "hg summary"
5956 5965 ui.status(_('remote: (synced)\n'))
5957 5966
5958 5967 cmdutil.summaryremotehooks(ui, repo, opts,
5959 5968 ((source, sbranch, sother, commoninc),
5960 5969 (dest, dbranch, dother, outgoing)))
5961 5970
5962 5971 @command('tag',
5963 5972 [('f', 'force', None, _('force tag')),
5964 5973 ('l', 'local', None, _('make the tag local')),
5965 5974 ('r', 'rev', '', _('revision to tag'), _('REV')),
5966 5975 ('', 'remove', None, _('remove a tag')),
5967 5976 # -l/--local is already there, commitopts cannot be used
5968 5977 ('e', 'edit', None, _('invoke editor on commit messages')),
5969 5978 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5970 5979 ] + commitopts2,
5971 5980 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5972 5981 def tag(ui, repo, name1, *names, **opts):
5973 5982 """add one or more tags for the current or given revision
5974 5983
5975 5984 Name a particular revision using <name>.
5976 5985
5977 5986 Tags are used to name particular revisions of the repository and are
5978 5987 very useful to compare different revisions, to go back to significant
5979 5988 earlier versions or to mark branch points as releases, etc. Changing
5980 5989 an existing tag is normally disallowed; use -f/--force to override.
5981 5990
5982 5991 If no revision is given, the parent of the working directory is
5983 5992 used.
5984 5993
5985 5994 To facilitate version control, distribution, and merging of tags,
5986 5995 they are stored as a file named ".hgtags" which is managed similarly
5987 5996 to other project files and can be hand-edited if necessary. This
5988 5997 also means that tagging creates a new commit. The file
5989 5998 ".hg/localtags" is used for local tags (not shared among
5990 5999 repositories).
5991 6000
5992 6001 Tag commits are usually made at the head of a branch. If the parent
5993 6002 of the working directory is not a branch head, :hg:`tag` aborts; use
5994 6003 -f/--force to force the tag commit to be based on a non-head
5995 6004 changeset.
5996 6005
5997 6006 See :hg:`help dates` for a list of formats valid for -d/--date.
5998 6007
5999 6008 Since tag names have priority over branch names during revision
6000 6009 lookup, using an existing branch name as a tag name is discouraged.
6001 6010
6002 6011 Returns 0 on success.
6003 6012 """
6004 6013 wlock = lock = None
6005 6014 try:
6006 6015 wlock = repo.wlock()
6007 6016 lock = repo.lock()
6008 6017 rev_ = "."
6009 6018 names = [t.strip() for t in (name1,) + names]
6010 6019 if len(names) != len(set(names)):
6011 6020 raise util.Abort(_('tag names must be unique'))
6012 6021 for n in names:
6013 6022 scmutil.checknewlabel(repo, n, 'tag')
6014 6023 if not n:
6015 6024 raise util.Abort(_('tag names cannot consist entirely of '
6016 6025 'whitespace'))
6017 6026 if opts.get('rev') and opts.get('remove'):
6018 6027 raise util.Abort(_("--rev and --remove are incompatible"))
6019 6028 if opts.get('rev'):
6020 6029 rev_ = opts['rev']
6021 6030 message = opts.get('message')
6022 6031 if opts.get('remove'):
6023 6032 expectedtype = opts.get('local') and 'local' or 'global'
6024 6033 for n in names:
6025 6034 if not repo.tagtype(n):
6026 6035 raise util.Abort(_("tag '%s' does not exist") % n)
6027 6036 if repo.tagtype(n) != expectedtype:
6028 6037 if expectedtype == 'global':
6029 6038 raise util.Abort(_("tag '%s' is not a global tag") % n)
6030 6039 else:
6031 6040 raise util.Abort(_("tag '%s' is not a local tag") % n)
6032 6041 rev_ = nullid
6033 6042 if not message:
6034 6043 # we don't translate commit messages
6035 6044 message = 'Removed tag %s' % ', '.join(names)
6036 6045 elif not opts.get('force'):
6037 6046 for n in names:
6038 6047 if n in repo.tags():
6039 6048 raise util.Abort(_("tag '%s' already exists "
6040 6049 "(use -f to force)") % n)
6041 6050 if not opts.get('local'):
6042 6051 p1, p2 = repo.dirstate.parents()
6043 6052 if p2 != nullid:
6044 6053 raise util.Abort(_('uncommitted merge'))
6045 6054 bheads = repo.branchheads()
6046 6055 if not opts.get('force') and bheads and p1 not in bheads:
6047 6056 raise util.Abort(_('not at a branch head (use -f to force)'))
6048 6057 r = scmutil.revsingle(repo, rev_).node()
6049 6058
6050 6059 if not message:
6051 6060 # we don't translate commit messages
6052 6061 message = ('Added tag %s for changeset %s' %
6053 6062 (', '.join(names), short(r)))
6054 6063
6055 6064 date = opts.get('date')
6056 6065 if date:
6057 6066 date = util.parsedate(date)
6058 6067
6059 6068 if opts.get('remove'):
6060 6069 editform = 'tag.remove'
6061 6070 else:
6062 6071 editform = 'tag.add'
6063 6072 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6064 6073
6065 6074 # don't allow tagging the null rev
6066 6075 if (not opts.get('remove') and
6067 6076 scmutil.revsingle(repo, rev_).rev() == nullrev):
6068 6077 raise util.Abort(_("cannot tag null revision"))
6069 6078
6070 6079 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6071 6080 editor=editor)
6072 6081 finally:
6073 6082 release(lock, wlock)
6074 6083
6075 6084 @command('tags', formatteropts, '')
6076 6085 def tags(ui, repo, **opts):
6077 6086 """list repository tags
6078 6087
6079 6088 This lists both regular and local tags. When the -v/--verbose
6080 6089 switch is used, a third column "local" is printed for local tags.
6081 6090
6082 6091 Returns 0 on success.
6083 6092 """
6084 6093
6085 6094 fm = ui.formatter('tags', opts)
6086 6095 if fm or ui.debugflag:
6087 6096 hexfunc = hex
6088 6097 else:
6089 6098 hexfunc = short
6090 6099 tagtype = ""
6091 6100
6092 6101 for t, n in reversed(repo.tagslist()):
6093 6102 hn = hexfunc(n)
6094 6103 label = 'tags.normal'
6095 6104 tagtype = ''
6096 6105 if repo.tagtype(t) == 'local':
6097 6106 label = 'tags.local'
6098 6107 tagtype = 'local'
6099 6108
6100 6109 fm.startitem()
6101 6110 fm.write('tag', '%s', t, label=label)
6102 6111 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6103 6112 fm.condwrite(not ui.quiet, 'rev node', fmt,
6104 6113 repo.changelog.rev(n), hn, label=label)
6105 6114 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6106 6115 tagtype, label=label)
6107 6116 fm.plain('\n')
6108 6117 fm.end()
6109 6118
6110 6119 @command('tip',
6111 6120 [('p', 'patch', None, _('show patch')),
6112 6121 ('g', 'git', None, _('use git extended diff format')),
6113 6122 ] + templateopts,
6114 6123 _('[-p] [-g]'))
6115 6124 def tip(ui, repo, **opts):
6116 6125 """show the tip revision (DEPRECATED)
6117 6126
6118 6127 The tip revision (usually just called the tip) is the changeset
6119 6128 most recently added to the repository (and therefore the most
6120 6129 recently changed head).
6121 6130
6122 6131 If you have just made a commit, that commit will be the tip. If
6123 6132 you have just pulled changes from another repository, the tip of
6124 6133 that repository becomes the current tip. The "tip" tag is special
6125 6134 and cannot be renamed or assigned to a different changeset.
6126 6135
6127 6136 This command is deprecated, please use :hg:`heads` instead.
6128 6137
6129 6138 Returns 0 on success.
6130 6139 """
6131 6140 displayer = cmdutil.show_changeset(ui, repo, opts)
6132 6141 displayer.show(repo['tip'])
6133 6142 displayer.close()
6134 6143
6135 6144 @command('unbundle',
6136 6145 [('u', 'update', None,
6137 6146 _('update to new branch head if changesets were unbundled'))],
6138 6147 _('[-u] FILE...'))
6139 6148 def unbundle(ui, repo, fname1, *fnames, **opts):
6140 6149 """apply one or more changegroup files
6141 6150
6142 6151 Apply one or more compressed changegroup files generated by the
6143 6152 bundle command.
6144 6153
6145 6154 Returns 0 on success, 1 if an update has unresolved files.
6146 6155 """
6147 6156 fnames = (fname1,) + fnames
6148 6157
6149 6158 lock = repo.lock()
6150 6159 try:
6151 6160 for fname in fnames:
6152 6161 f = hg.openpath(ui, fname)
6153 6162 gen = exchange.readbundle(ui, f, fname)
6154 6163 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6155 6164 'bundle:' + fname)
6156 6165 finally:
6157 6166 lock.release()
6158 6167
6159 6168 return postincoming(ui, repo, modheads, opts.get('update'), None)
6160 6169
6161 6170 @command('^update|up|checkout|co',
6162 6171 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6163 6172 ('c', 'check', None,
6164 6173 _('update across branches if no uncommitted changes')),
6165 6174 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6166 6175 ('r', 'rev', '', _('revision'), _('REV'))
6167 6176 ] + mergetoolopts,
6168 6177 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6169 6178 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6170 6179 tool=None):
6171 6180 """update working directory (or switch revisions)
6172 6181
6173 6182 Update the repository's working directory to the specified
6174 6183 changeset. If no changeset is specified, update to the tip of the
6175 6184 current named branch and move the current bookmark (see :hg:`help
6176 6185 bookmarks`).
6177 6186
6178 6187 Update sets the working directory's parent revision to the specified
6179 6188 changeset (see :hg:`help parents`).
6180 6189
6181 6190 If the changeset is not a descendant or ancestor of the working
6182 6191 directory's parent, the update is aborted. With the -c/--check
6183 6192 option, the working directory is checked for uncommitted changes; if
6184 6193 none are found, the working directory is updated to the specified
6185 6194 changeset.
6186 6195
6187 6196 .. container:: verbose
6188 6197
6189 6198 The following rules apply when the working directory contains
6190 6199 uncommitted changes:
6191 6200
6192 6201 1. If neither -c/--check nor -C/--clean is specified, and if
6193 6202 the requested changeset is an ancestor or descendant of
6194 6203 the working directory's parent, the uncommitted changes
6195 6204 are merged into the requested changeset and the merged
6196 6205 result is left uncommitted. If the requested changeset is
6197 6206 not an ancestor or descendant (that is, it is on another
6198 6207 branch), the update is aborted and the uncommitted changes
6199 6208 are preserved.
6200 6209
6201 6210 2. With the -c/--check option, the update is aborted and the
6202 6211 uncommitted changes are preserved.
6203 6212
6204 6213 3. With the -C/--clean option, uncommitted changes are discarded and
6205 6214 the working directory is updated to the requested changeset.
6206 6215
6207 6216 To cancel an uncommitted merge (and lose your changes), use
6208 6217 :hg:`update --clean .`.
6209 6218
6210 6219 Use null as the changeset to remove the working directory (like
6211 6220 :hg:`clone -U`).
6212 6221
6213 6222 If you want to revert just one file to an older revision, use
6214 6223 :hg:`revert [-r REV] NAME`.
6215 6224
6216 6225 See :hg:`help dates` for a list of formats valid for -d/--date.
6217 6226
6218 6227 Returns 0 on success, 1 if there are unresolved files.
6219 6228 """
6220 6229 if rev and node:
6221 6230 raise util.Abort(_("please specify just one revision"))
6222 6231
6223 6232 if rev is None or rev == '':
6224 6233 rev = node
6225 6234
6226 6235 cmdutil.clearunfinished(repo)
6227 6236
6228 6237 # with no argument, we also move the current bookmark, if any
6229 6238 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6230 6239
6231 6240 # if we defined a bookmark, we have to remember the original bookmark name
6232 6241 brev = rev
6233 6242 rev = scmutil.revsingle(repo, rev, rev).rev()
6234 6243
6235 6244 if check and clean:
6236 6245 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6237 6246
6238 6247 if date:
6239 6248 if rev is not None:
6240 6249 raise util.Abort(_("you can't specify a revision and a date"))
6241 6250 rev = cmdutil.finddate(ui, repo, date)
6242 6251
6243 6252 if check:
6244 6253 c = repo[None]
6245 6254 if c.dirty(merge=False, branch=False, missing=True):
6246 6255 raise util.Abort(_("uncommitted changes"))
6247 6256 if rev is None:
6248 6257 rev = repo[repo[None].branch()].rev()
6249 6258 mergemod._checkunknown(repo, repo[None], repo[rev])
6250 6259
6251 6260 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6252 6261
6253 6262 if clean:
6254 6263 ret = hg.clean(repo, rev)
6255 6264 else:
6256 6265 ret = hg.update(repo, rev)
6257 6266
6258 6267 if not ret and movemarkfrom:
6259 6268 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6260 6269 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6261 6270 elif brev in repo._bookmarks:
6262 6271 bookmarks.setcurrent(repo, brev)
6263 6272 ui.status(_("(activating bookmark %s)\n") % brev)
6264 6273 elif brev:
6265 6274 if repo._bookmarkcurrent:
6266 6275 ui.status(_("(leaving bookmark %s)\n") %
6267 6276 repo._bookmarkcurrent)
6268 6277 bookmarks.unsetcurrent(repo)
6269 6278
6270 6279 return ret
6271 6280
6272 6281 @command('verify', [])
6273 6282 def verify(ui, repo):
6274 6283 """verify the integrity of the repository
6275 6284
6276 6285 Verify the integrity of the current repository.
6277 6286
6278 6287 This will perform an extensive check of the repository's
6279 6288 integrity, validating the hashes and checksums of each entry in
6280 6289 the changelog, manifest, and tracked files, as well as the
6281 6290 integrity of their crosslinks and indices.
6282 6291
6283 6292 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6284 6293 for more information about recovery from corruption of the
6285 6294 repository.
6286 6295
6287 6296 Returns 0 on success, 1 if errors are encountered.
6288 6297 """
6289 6298 return hg.verify(repo)
6290 6299
6291 6300 @command('version', [], norepo=True)
6292 6301 def version_(ui):
6293 6302 """output version and copyright information"""
6294 6303 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6295 6304 % util.version())
6296 6305 ui.status(_(
6297 6306 "(see http://mercurial.selenic.com for more information)\n"
6298 6307 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6299 6308 "This is free software; see the source for copying conditions. "
6300 6309 "There is NO\nwarranty; "
6301 6310 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6302 6311 ))
6303 6312
6304 6313 ui.note(_("\nEnabled extensions:\n\n"))
6305 6314 if ui.verbose:
6306 6315 # format names and versions into columns
6307 6316 names = []
6308 6317 vers = []
6309 6318 for name, module in extensions.extensions():
6310 6319 names.append(name)
6311 6320 vers.append(extensions.moduleversion(module))
6312 6321 if names:
6313 6322 maxnamelen = max(len(n) for n in names)
6314 6323 for i, name in enumerate(names):
6315 6324 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,713 +1,734 b''
1 1 # minirst.py - minimal reStructuredText parser
2 2 #
3 3 # Copyright 2009, 2010 Matt Mackall <mpm@selenic.com> and others
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 """simplified reStructuredText parser.
9 9
10 10 This parser knows just enough about reStructuredText to parse the
11 11 Mercurial docstrings.
12 12
13 13 It cheats in a major way: nested blocks are not really nested. They
14 14 are just indented blocks that look like they are nested. This relies
15 15 on the user to keep the right indentation for the blocks.
16 16
17 17 Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
18 18 when adding support for new constructs.
19 19 """
20 20
21 21 import re
22 22 import util, encoding
23 23 from i18n import _
24 24
25 25 import cgi
26 26
27 27 def section(s):
28 28 return "%s\n%s\n\n" % (s, "\"" * encoding.colwidth(s))
29 29
30 30 def subsection(s):
31 31 return "%s\n%s\n\n" % (s, '=' * encoding.colwidth(s))
32 32
33 33 def subsubsection(s):
34 34 return "%s\n%s\n\n" % (s, "-" * encoding.colwidth(s))
35 35
36 36 def subsubsubsection(s):
37 37 return "%s\n%s\n\n" % (s, "." * encoding.colwidth(s))
38 38
39 39 def replace(text, substs):
40 40 '''
41 41 Apply a list of (find, replace) pairs to a text.
42 42
43 43 >>> replace("foo bar", [('f', 'F'), ('b', 'B')])
44 44 'Foo Bar'
45 45 >>> encoding.encoding = 'latin1'
46 46 >>> replace('\\x81\\\\', [('\\\\', '/')])
47 47 '\\x81/'
48 48 >>> encoding.encoding = 'shiftjis'
49 49 >>> replace('\\x81\\\\', [('\\\\', '/')])
50 50 '\\x81\\\\'
51 51 '''
52 52
53 53 # some character encodings (cp932 for Japanese, at least) use
54 54 # ASCII characters other than control/alphabet/digit as a part of
55 55 # multi-bytes characters, so direct replacing with such characters
56 56 # on strings in local encoding causes invalid byte sequences.
57 57 utext = text.decode(encoding.encoding)
58 58 for f, t in substs:
59 59 utext = utext.replace(f.decode("ascii"), t.decode("ascii"))
60 60 return utext.encode(encoding.encoding)
61 61
62 62 _blockre = re.compile(r"\n(?:\s*\n)+")
63 63
64 64 def findblocks(text):
65 65 """Find continuous blocks of lines in text.
66 66
67 67 Returns a list of dictionaries representing the blocks. Each block
68 68 has an 'indent' field and a 'lines' field.
69 69 """
70 70 blocks = []
71 71 for b in _blockre.split(text.lstrip('\n').rstrip()):
72 72 lines = b.splitlines()
73 73 if lines:
74 74 indent = min((len(l) - len(l.lstrip())) for l in lines)
75 75 lines = [l[indent:] for l in lines]
76 76 blocks.append({'indent': indent, 'lines': lines})
77 77 return blocks
78 78
79 79 def findliteralblocks(blocks):
80 80 """Finds literal blocks and adds a 'type' field to the blocks.
81 81
82 82 Literal blocks are given the type 'literal', all other blocks are
83 83 given type the 'paragraph'.
84 84 """
85 85 i = 0
86 86 while i < len(blocks):
87 87 # Searching for a block that looks like this:
88 88 #
89 89 # +------------------------------+
90 90 # | paragraph |
91 91 # | (ends with "::") |
92 92 # +------------------------------+
93 93 # +---------------------------+
94 94 # | indented literal block |
95 95 # +---------------------------+
96 96 blocks[i]['type'] = 'paragraph'
97 97 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
98 98 indent = blocks[i]['indent']
99 99 adjustment = blocks[i + 1]['indent'] - indent
100 100
101 101 if blocks[i]['lines'] == ['::']:
102 102 # Expanded form: remove block
103 103 del blocks[i]
104 104 i -= 1
105 105 elif blocks[i]['lines'][-1].endswith(' ::'):
106 106 # Partially minimized form: remove space and both
107 107 # colons.
108 108 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
109 109 elif len(blocks[i]['lines']) == 1 and \
110 110 blocks[i]['lines'][0].lstrip(' ').startswith('.. ') and \
111 111 blocks[i]['lines'][0].find(' ', 3) == -1:
112 112 # directive on its own line, not a literal block
113 113 i += 1
114 114 continue
115 115 else:
116 116 # Fully minimized form: remove just one colon.
117 117 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
118 118
119 119 # List items are formatted with a hanging indent. We must
120 120 # correct for this here while we still have the original
121 121 # information on the indentation of the subsequent literal
122 122 # blocks available.
123 123 m = _bulletre.match(blocks[i]['lines'][0])
124 124 if m:
125 125 indent += m.end()
126 126 adjustment -= m.end()
127 127
128 128 # Mark the following indented blocks.
129 129 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
130 130 blocks[i + 1]['type'] = 'literal'
131 131 blocks[i + 1]['indent'] -= adjustment
132 132 i += 1
133 133 i += 1
134 134 return blocks
135 135
136 136 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
137 137 _optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
138 138 r'((.*) +)(.*)$')
139 139 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
140 140 _definitionre = re.compile(r'[^ ]')
141 141 _tablere = re.compile(r'(=+\s+)*=+')
142 142
143 143 def splitparagraphs(blocks):
144 144 """Split paragraphs into lists."""
145 145 # Tuples with (list type, item regexp, single line items?). Order
146 146 # matters: definition lists has the least specific regexp and must
147 147 # come last.
148 148 listtypes = [('bullet', _bulletre, True),
149 149 ('option', _optionre, True),
150 150 ('field', _fieldre, True),
151 151 ('definition', _definitionre, False)]
152 152
153 153 def match(lines, i, itemre, singleline):
154 154 """Does itemre match an item at line i?
155 155
156 156 A list item can be followed by an indented line or another list
157 157 item (but only if singleline is True).
158 158 """
159 159 line1 = lines[i]
160 160 line2 = i + 1 < len(lines) and lines[i + 1] or ''
161 161 if not itemre.match(line1):
162 162 return False
163 163 if singleline:
164 164 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
165 165 else:
166 166 return line2.startswith(' ')
167 167
168 168 i = 0
169 169 while i < len(blocks):
170 170 if blocks[i]['type'] == 'paragraph':
171 171 lines = blocks[i]['lines']
172 172 for type, itemre, singleline in listtypes:
173 173 if match(lines, 0, itemre, singleline):
174 174 items = []
175 175 for j, line in enumerate(lines):
176 176 if match(lines, j, itemre, singleline):
177 177 items.append({'type': type, 'lines': [],
178 178 'indent': blocks[i]['indent']})
179 179 items[-1]['lines'].append(line)
180 180 blocks[i:i + 1] = items
181 181 break
182 182 i += 1
183 183 return blocks
184 184
185 185 _fieldwidth = 14
186 186
187 187 def updatefieldlists(blocks):
188 188 """Find key for field lists."""
189 189 i = 0
190 190 while i < len(blocks):
191 191 if blocks[i]['type'] != 'field':
192 192 i += 1
193 193 continue
194 194
195 195 j = i
196 196 while j < len(blocks) and blocks[j]['type'] == 'field':
197 197 m = _fieldre.match(blocks[j]['lines'][0])
198 198 key, rest = m.groups()
199 199 blocks[j]['lines'][0] = rest
200 200 blocks[j]['key'] = key
201 201 j += 1
202 202
203 203 i = j + 1
204 204
205 205 return blocks
206 206
207 207 def updateoptionlists(blocks):
208 208 i = 0
209 209 while i < len(blocks):
210 210 if blocks[i]['type'] != 'option':
211 211 i += 1
212 212 continue
213 213
214 214 optstrwidth = 0
215 215 j = i
216 216 while j < len(blocks) and blocks[j]['type'] == 'option':
217 217 m = _optionre.match(blocks[j]['lines'][0])
218 218
219 219 shortoption = m.group(2)
220 220 group3 = m.group(3)
221 221 longoption = group3[2:].strip()
222 222 desc = m.group(6).strip()
223 223 longoptionarg = m.group(5).strip()
224 224 blocks[j]['lines'][0] = desc
225 225
226 226 noshortop = ''
227 227 if not shortoption:
228 228 noshortop = ' '
229 229
230 230 opt = "%s%s" % (shortoption and "-%s " % shortoption or '',
231 231 ("%s--%s %s") % (noshortop, longoption,
232 232 longoptionarg))
233 233 opt = opt.rstrip()
234 234 blocks[j]['optstr'] = opt
235 235 optstrwidth = max(optstrwidth, encoding.colwidth(opt))
236 236 j += 1
237 237
238 238 for block in blocks[i:j]:
239 239 block['optstrwidth'] = optstrwidth
240 240 i = j + 1
241 241 return blocks
242 242
243 243 def prunecontainers(blocks, keep):
244 244 """Prune unwanted containers.
245 245
246 246 The blocks must have a 'type' field, i.e., they should have been
247 247 run through findliteralblocks first.
248 248 """
249 249 pruned = []
250 250 i = 0
251 251 while i + 1 < len(blocks):
252 252 # Searching for a block that looks like this:
253 253 #
254 254 # +-------+---------------------------+
255 255 # | ".. container ::" type |
256 256 # +---+ |
257 257 # | blocks |
258 258 # +-------------------------------+
259 259 if (blocks[i]['type'] == 'paragraph' and
260 260 blocks[i]['lines'][0].startswith('.. container::')):
261 261 indent = blocks[i]['indent']
262 262 adjustment = blocks[i + 1]['indent'] - indent
263 263 containertype = blocks[i]['lines'][0][15:]
264 264 prune = True
265 265 for c in keep:
266 266 if c in containertype.split('.'):
267 267 prune = False
268 268 if prune:
269 269 pruned.append(containertype)
270 270
271 271 # Always delete "..container:: type" block
272 272 del blocks[i]
273 273 j = i
274 274 i -= 1
275 275 while j < len(blocks) and blocks[j]['indent'] > indent:
276 276 if prune:
277 277 del blocks[j]
278 278 else:
279 279 blocks[j]['indent'] -= adjustment
280 280 j += 1
281 281 i += 1
282 282 return blocks, pruned
283 283
284 284 _sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
285 285
286 286 def findtables(blocks):
287 287 '''Find simple tables
288 288
289 289 Only simple one-line table elements are supported
290 290 '''
291 291
292 292 for block in blocks:
293 293 # Searching for a block that looks like this:
294 294 #
295 295 # === ==== ===
296 296 # A B C
297 297 # === ==== === <- optional
298 298 # 1 2 3
299 299 # x y z
300 300 # === ==== ===
301 301 if (block['type'] == 'paragraph' and
302 302 len(block['lines']) > 2 and
303 303 _tablere.match(block['lines'][0]) and
304 304 block['lines'][0] == block['lines'][-1]):
305 305 block['type'] = 'table'
306 306 block['header'] = False
307 307 div = block['lines'][0]
308 308
309 309 # column markers are ASCII so we can calculate column
310 310 # position in bytes
311 311 columns = [x for x in xrange(len(div))
312 312 if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
313 313 rows = []
314 314 for l in block['lines'][1:-1]:
315 315 if l == div:
316 316 block['header'] = True
317 317 continue
318 318 row = []
319 319 # we measure columns not in bytes or characters but in
320 320 # colwidth which makes things tricky
321 321 pos = columns[0] # leading whitespace is bytes
322 322 for n, start in enumerate(columns):
323 323 if n + 1 < len(columns):
324 324 width = columns[n + 1] - start
325 325 v = encoding.getcols(l, pos, width) # gather columns
326 326 pos += len(v) # calculate byte position of end
327 327 row.append(v.strip())
328 328 else:
329 329 row.append(l[pos:].strip())
330 330 rows.append(row)
331 331
332 332 block['table'] = rows
333 333
334 334 return blocks
335 335
336 336 def findsections(blocks):
337 337 """Finds sections.
338 338
339 339 The blocks must have a 'type' field, i.e., they should have been
340 340 run through findliteralblocks first.
341 341 """
342 342 for block in blocks:
343 343 # Searching for a block that looks like this:
344 344 #
345 345 # +------------------------------+
346 346 # | Section title |
347 347 # | ------------- |
348 348 # +------------------------------+
349 349 if (block['type'] == 'paragraph' and
350 350 len(block['lines']) == 2 and
351 351 encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
352 352 _sectionre.match(block['lines'][1])):
353 353 block['underline'] = block['lines'][1][0]
354 354 block['type'] = 'section'
355 355 del block['lines'][1]
356 356 return blocks
357 357
358 358 def inlineliterals(blocks):
359 359 substs = [('``', '"')]
360 360 for b in blocks:
361 361 if b['type'] in ('paragraph', 'section'):
362 362 b['lines'] = [replace(l, substs) for l in b['lines']]
363 363 return blocks
364 364
365 365 def hgrole(blocks):
366 366 substs = [(':hg:`', '"hg '), ('`', '"')]
367 367 for b in blocks:
368 368 if b['type'] in ('paragraph', 'section'):
369 369 # Turn :hg:`command` into "hg command". This also works
370 370 # when there is a line break in the command and relies on
371 371 # the fact that we have no stray back-quotes in the input
372 372 # (run the blocks through inlineliterals first).
373 373 b['lines'] = [replace(l, substs) for l in b['lines']]
374 374 return blocks
375 375
376 376 def addmargins(blocks):
377 377 """Adds empty blocks for vertical spacing.
378 378
379 379 This groups bullets, options, and definitions together with no vertical
380 380 space between them, and adds an empty block between all other blocks.
381 381 """
382 382 i = 1
383 383 while i < len(blocks):
384 384 if (blocks[i]['type'] == blocks[i - 1]['type'] and
385 385 blocks[i]['type'] in ('bullet', 'option', 'field')):
386 386 i += 1
387 387 elif not blocks[i - 1]['lines']:
388 388 # no lines in previous block, do not separate
389 389 i += 1
390 390 else:
391 391 blocks.insert(i, {'lines': [''], 'indent': 0, 'type': 'margin'})
392 392 i += 2
393 393 return blocks
394 394
395 395 def prunecomments(blocks):
396 396 """Remove comments."""
397 397 i = 0
398 398 while i < len(blocks):
399 399 b = blocks[i]
400 400 if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
401 401 b['lines'] == ['..']):
402 402 del blocks[i]
403 403 if i < len(blocks) and blocks[i]['type'] == 'margin':
404 404 del blocks[i]
405 405 else:
406 406 i += 1
407 407 return blocks
408 408
409 409 _admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
410 410 r"error|hint|important|note|tip|warning)::",
411 411 flags=re.IGNORECASE)
412 412
413 413 def findadmonitions(blocks):
414 414 """
415 415 Makes the type of the block an admonition block if
416 416 the first line is an admonition directive
417 417 """
418 418 i = 0
419 419 while i < len(blocks):
420 420 m = _admonitionre.match(blocks[i]['lines'][0])
421 421 if m:
422 422 blocks[i]['type'] = 'admonition'
423 423 admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
424 424
425 425 firstline = blocks[i]['lines'][0][m.end() + 1:]
426 426 if firstline:
427 427 blocks[i]['lines'].insert(1, ' ' + firstline)
428 428
429 429 blocks[i]['admonitiontitle'] = admonitiontitle
430 430 del blocks[i]['lines'][0]
431 431 i = i + 1
432 432 return blocks
433 433
434 434 _admonitiontitles = {'attention': _('Attention:'),
435 435 'caution': _('Caution:'),
436 436 'danger': _('!Danger!') ,
437 437 'error': _('Error:'),
438 438 'hint': _('Hint:'),
439 439 'important': _('Important:'),
440 440 'note': _('Note:'),
441 441 'tip': _('Tip:'),
442 442 'warning': _('Warning!')}
443 443
444 444 def formatoption(block, width):
445 445 desc = ' '.join(map(str.strip, block['lines']))
446 446 colwidth = encoding.colwidth(block['optstr'])
447 447 usablewidth = width - 1
448 448 hanging = block['optstrwidth']
449 449 initindent = '%s%s ' % (block['optstr'], ' ' * ((hanging - colwidth)))
450 450 hangindent = ' ' * (encoding.colwidth(initindent) + 1)
451 451 return ' %s\n' % (util.wrap(desc, usablewidth,
452 452 initindent=initindent,
453 453 hangindent=hangindent))
454 454
455 455 def formatblock(block, width):
456 456 """Format a block according to width."""
457 457 if width <= 0:
458 458 width = 78
459 459 indent = ' ' * block['indent']
460 460 if block['type'] == 'admonition':
461 461 admonition = _admonitiontitles[block['admonitiontitle']]
462 462 if not block['lines']:
463 463 return indent + admonition + '\n'
464 464 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
465 465
466 466 defindent = indent + hang * ' '
467 467 text = ' '.join(map(str.strip, block['lines']))
468 468 return '%s\n%s\n' % (indent + admonition,
469 469 util.wrap(text, width=width,
470 470 initindent=defindent,
471 471 hangindent=defindent))
472 472 if block['type'] == 'margin':
473 473 return '\n'
474 474 if block['type'] == 'literal':
475 475 indent += ' '
476 476 return indent + ('\n' + indent).join(block['lines']) + '\n'
477 477 if block['type'] == 'section':
478 478 underline = encoding.colwidth(block['lines'][0]) * block['underline']
479 479 return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
480 480 if block['type'] == 'table':
481 481 table = block['table']
482 482 # compute column widths
483 483 widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
484 484 text = ''
485 485 span = sum(widths) + len(widths) - 1
486 486 indent = ' ' * block['indent']
487 487 hang = ' ' * (len(indent) + span - widths[-1])
488 488
489 489 for row in table:
490 490 l = []
491 491 for w, v in zip(widths, row):
492 492 pad = ' ' * (w - encoding.colwidth(v))
493 493 l.append(v + pad)
494 494 l = ' '.join(l)
495 495 l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
496 496 if not text and block['header']:
497 497 text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
498 498 else:
499 499 text += l + "\n"
500 500 return text
501 501 if block['type'] == 'definition':
502 502 term = indent + block['lines'][0]
503 503 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
504 504 defindent = indent + hang * ' '
505 505 text = ' '.join(map(str.strip, block['lines'][1:]))
506 506 return '%s\n%s\n' % (term, util.wrap(text, width=width,
507 507 initindent=defindent,
508 508 hangindent=defindent))
509 509 subindent = indent
510 510 if block['type'] == 'bullet':
511 511 if block['lines'][0].startswith('| '):
512 512 # Remove bullet for line blocks and add no extra
513 513 # indention.
514 514 block['lines'][0] = block['lines'][0][2:]
515 515 else:
516 516 m = _bulletre.match(block['lines'][0])
517 517 subindent = indent + m.end() * ' '
518 518 elif block['type'] == 'field':
519 519 key = block['key']
520 520 subindent = indent + _fieldwidth * ' '
521 521 if len(key) + 2 > _fieldwidth:
522 522 # key too large, use full line width
523 523 key = key.ljust(width)
524 524 else:
525 525 # key fits within field width
526 526 key = key.ljust(_fieldwidth)
527 527 block['lines'][0] = key + block['lines'][0]
528 528 elif block['type'] == 'option':
529 529 return formatoption(block, width)
530 530
531 531 text = ' '.join(map(str.strip, block['lines']))
532 532 return util.wrap(text, width=width,
533 533 initindent=indent,
534 534 hangindent=subindent) + '\n'
535 535
536 536 def formathtml(blocks):
537 537 """Format RST blocks as HTML"""
538 538
539 539 out = []
540 540 headernest = ''
541 541 listnest = []
542 542
543 543 def escape(s):
544 544 return cgi.escape(s, True)
545 545
546 546 def openlist(start, level):
547 547 if not listnest or listnest[-1][0] != start:
548 548 listnest.append((start, level))
549 549 out.append('<%s>\n' % start)
550 550
551 551 blocks = [b for b in blocks if b['type'] != 'margin']
552 552
553 553 for pos, b in enumerate(blocks):
554 554 btype = b['type']
555 555 level = b['indent']
556 556 lines = b['lines']
557 557
558 558 if btype == 'admonition':
559 559 admonition = escape(_admonitiontitles[b['admonitiontitle']])
560 560 text = escape(' '.join(map(str.strip, lines)))
561 561 out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
562 562 elif btype == 'paragraph':
563 563 out.append('<p>\n%s\n</p>\n' % escape('\n'.join(lines)))
564 564 elif btype == 'margin':
565 565 pass
566 566 elif btype == 'literal':
567 567 out.append('<pre>\n%s\n</pre>\n' % escape('\n'.join(lines)))
568 568 elif btype == 'section':
569 569 i = b['underline']
570 570 if i not in headernest:
571 571 headernest += i
572 572 level = headernest.index(i) + 1
573 573 out.append('<h%d>%s</h%d>\n' % (level, escape(lines[0]), level))
574 574 elif btype == 'table':
575 575 table = b['table']
576 576 out.append('<table>\n')
577 577 for row in table:
578 578 out.append('<tr>')
579 579 for v in row:
580 580 out.append('<td>')
581 581 out.append(escape(v))
582 582 out.append('</td>')
583 583 out.append('\n')
584 584 out.pop()
585 585 out.append('</tr>\n')
586 586 out.append('</table>\n')
587 587 elif btype == 'definition':
588 588 openlist('dl', level)
589 589 term = escape(lines[0])
590 590 text = escape(' '.join(map(str.strip, lines[1:])))
591 591 out.append(' <dt>%s\n <dd>%s\n' % (term, text))
592 592 elif btype == 'bullet':
593 593 bullet, head = lines[0].split(' ', 1)
594 594 if bullet == '-':
595 595 openlist('ul', level)
596 596 else:
597 597 openlist('ol', level)
598 598 out.append(' <li> %s\n' % escape(' '.join([head] + lines[1:])))
599 599 elif btype == 'field':
600 600 openlist('dl', level)
601 601 key = escape(b['key'])
602 602 text = escape(' '.join(map(str.strip, lines)))
603 603 out.append(' <dt>%s\n <dd>%s\n' % (key, text))
604 604 elif btype == 'option':
605 605 openlist('dl', level)
606 606 opt = escape(b['optstr'])
607 607 desc = escape(' '.join(map(str.strip, lines)))
608 608 out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
609 609
610 610 # close lists if indent level of next block is lower
611 611 if listnest:
612 612 start, level = listnest[-1]
613 613 if pos == len(blocks) - 1:
614 614 out.append('</%s>\n' % start)
615 615 listnest.pop()
616 616 else:
617 617 nb = blocks[pos + 1]
618 618 ni = nb['indent']
619 619 if (ni < level or
620 620 (ni == level and
621 621 nb['type'] not in 'definition bullet field option')):
622 622 out.append('</%s>\n' % start)
623 623 listnest.pop()
624 624
625 625 return ''.join(out)
626 626
627 627 def parse(text, indent=0, keep=None):
628 628 """Parse text into a list of blocks"""
629 629 pruned = []
630 630 blocks = findblocks(text)
631 631 for b in blocks:
632 632 b['indent'] += indent
633 633 blocks = findliteralblocks(blocks)
634 634 blocks = findtables(blocks)
635 635 blocks, pruned = prunecontainers(blocks, keep or [])
636 636 blocks = findsections(blocks)
637 637 blocks = inlineliterals(blocks)
638 638 blocks = hgrole(blocks)
639 639 blocks = splitparagraphs(blocks)
640 640 blocks = updatefieldlists(blocks)
641 641 blocks = updateoptionlists(blocks)
642 642 blocks = findadmonitions(blocks)
643 643 blocks = addmargins(blocks)
644 644 blocks = prunecomments(blocks)
645 645 return blocks, pruned
646 646
647 647 def formatblocks(blocks, width):
648 648 text = ''.join(formatblock(b, width) for b in blocks)
649 649 return text
650 650
651 def format(text, width=80, indent=0, keep=None, style='plain'):
651 def format(text, width=80, indent=0, keep=None, style='plain', section=None):
652 652 """Parse and format the text according to width."""
653 653 blocks, pruned = parse(text, indent, keep or [])
654 if section:
655 sections = getsections(blocks)
656 blocks = []
657 for name, nest, b in sections:
658 if name == section:
659 blocks = b
654 660 if style == 'html':
655 661 text = formathtml(blocks)
656 662 else:
657 663 text = ''.join(formatblock(b, width) for b in blocks)
658 664 if keep is None:
659 665 return text
660 666 else:
661 667 return text, pruned
662 668
663 669 def getsections(blocks):
664 670 '''return a list of (section name, nesting level, blocks) tuples'''
665 671 nest = ""
666 672 level = 0
667 673 secs = []
674
675 def getname(b):
676 x = b['lines'][0]
677 x = x.lower().strip('"')
678 if '(' in x:
679 x = x.split('(')[0]
680 return x
681
668 682 for b in blocks:
669 683 if b['type'] == 'section':
670 684 i = b['underline']
671 685 if i not in nest:
672 686 nest += i
673 687 level = nest.index(i) + 1
674 688 nest = nest[:level]
675 secs.append((b['lines'][0], level, [b]))
689 secs.append((getname(b), level, [b]))
690 if b['type'] == 'definition':
691 i = ' '
692 if i not in nest:
693 nest += i
694 level = nest.index(i) + 1
695 nest = nest[:level]
696 secs.append((getname(b), level, [b]))
676 697 else:
677 698 if not secs:
678 699 # add an initial empty section
679 700 secs = [('', 0, [])]
680 701 secs[-1][2].append(b)
681 702 return secs
682 703
683 704 def decorateblocks(blocks, width):
684 705 '''generate a list of (section name, line text) pairs for search'''
685 706 lines = []
686 707 for s in getsections(blocks):
687 708 section = s[0]
688 709 text = formatblocks(s[2], width)
689 710 lines.append([(section, l) for l in text.splitlines(True)])
690 711 return lines
691 712
692 713 def maketable(data, indent=0, header=False):
693 714 '''Generate an RST table for the given table data as a list of lines'''
694 715
695 716 widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
696 717 indent = ' ' * indent
697 718 div = indent + ' '.join('=' * w for w in widths) + '\n'
698 719
699 720 out = [div]
700 721 for row in data:
701 722 l = []
702 723 for w, v in zip(widths, row):
703 724 if '\n' in v:
704 725 # only remove line breaks and indentation, long lines are
705 726 # handled by the next tool
706 727 v = ' '.join(e.lstrip() for e in v.split('\n'))
707 728 pad = ' ' * (w - encoding.colwidth(v))
708 729 l.append(v + pad)
709 730 out.append(indent + ' '.join(l) + "\n")
710 731 if header and len(data) > 1:
711 732 out.insert(2, div)
712 733 out.append(div)
713 734 return out
@@ -1,2063 +1,2082 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 working directory with another revision
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 working directory with another revision
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 copy 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 working directory with another revision
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 diffs Diff Formats
108 108 environment Environment Variables
109 109 extensions Using Additional Features
110 110 filesets Specifying File Sets
111 111 glossary Glossary
112 112 hgignore Syntax for Mercurial Ignore Files
113 113 hgweb Configuring hgweb
114 114 merge-tools Merge Tools
115 115 multirevs Specifying Multiple Revisions
116 116 patterns File Name Patterns
117 117 phases Working with Phases
118 118 revisions Specifying Single Revisions
119 119 revsets Specifying Revision Sets
120 120 subrepos Subrepositories
121 121 templating Template Usage
122 122 urls URL Paths
123 123
124 124 (use "hg help -v" to show built-in aliases and global options)
125 125
126 126 $ hg -q help
127 127 add add the specified files on the next commit
128 128 addremove add all new files, delete all missing files
129 129 annotate show changeset information by line for each file
130 130 archive create an unversioned archive of a repository revision
131 131 backout reverse effect of earlier changeset
132 132 bisect subdivision search of changesets
133 133 bookmarks create a new bookmark or list existing bookmarks
134 134 branch set or show the current branch name
135 135 branches list repository named branches
136 136 bundle create a changegroup file
137 137 cat output the current or given revision of files
138 138 clone make a copy of an existing repository
139 139 commit commit the specified files or all outstanding changes
140 140 config show combined config settings from all hgrc files
141 141 copy mark files as copied for the next commit
142 142 diff diff repository (or selected files)
143 143 export dump the header and diffs for one or more changesets
144 144 files list tracked files
145 145 forget forget the specified files on the next commit
146 146 graft copy changes from other branches onto the current branch
147 147 grep search for a pattern in specified files and revisions
148 148 heads show branch heads
149 149 help show help for a given topic or a help overview
150 150 identify identify the working copy or specified revision
151 151 import import an ordered set of patches
152 152 incoming show new changesets found in source
153 153 init create a new repository in the given directory
154 154 log show revision history of entire repository or files
155 155 manifest output the current or given revision of the project manifest
156 156 merge merge working directory with another revision
157 157 outgoing show changesets not found in the destination
158 158 paths show aliases for remote repositories
159 159 phase set or show the current phase name
160 160 pull pull changes from the specified source
161 161 push push changes to the specified destination
162 162 recover roll back an interrupted transaction
163 163 remove remove the specified files on the next commit
164 164 rename rename files; equivalent of copy + remove
165 165 resolve redo merges or set/view the merge status of files
166 166 revert restore files to their checkout state
167 167 root print the root (top) of the current working directory
168 168 serve start stand-alone webserver
169 169 status show changed files in the working directory
170 170 summary summarize working directory state
171 171 tag add one or more tags for the current or given revision
172 172 tags list repository tags
173 173 unbundle apply one or more changegroup files
174 174 update update working directory (or switch revisions)
175 175 verify verify the integrity of the repository
176 176 version output version and copyright information
177 177
178 178 additional help topics:
179 179
180 180 config Configuration Files
181 181 dates Date Formats
182 182 diffs Diff Formats
183 183 environment Environment Variables
184 184 extensions Using Additional Features
185 185 filesets Specifying File Sets
186 186 glossary Glossary
187 187 hgignore Syntax for Mercurial Ignore Files
188 188 hgweb Configuring hgweb
189 189 merge-tools Merge Tools
190 190 multirevs Specifying Multiple Revisions
191 191 patterns File Name Patterns
192 192 phases Working with Phases
193 193 revisions Specifying Single Revisions
194 194 revsets Specifying Revision Sets
195 195 subrepos Subrepositories
196 196 templating Template Usage
197 197 urls URL Paths
198 198
199 199 Test extension help:
200 200 $ hg help extensions --config extensions.rebase= --config extensions.children=
201 201 Using Additional Features
202 202 """""""""""""""""""""""""
203 203
204 204 Mercurial has the ability to add new features through the use of
205 205 extensions. Extensions may add new commands, add options to existing
206 206 commands, change the default behavior of commands, or implement hooks.
207 207
208 208 To enable the "foo" extension, either shipped with Mercurial or in the
209 209 Python search path, create an entry for it in your configuration file,
210 210 like this:
211 211
212 212 [extensions]
213 213 foo =
214 214
215 215 You may also specify the full path to an extension:
216 216
217 217 [extensions]
218 218 myfeature = ~/.hgext/myfeature.py
219 219
220 220 See "hg help config" for more information on configuration files.
221 221
222 222 Extensions are not loaded by default for a variety of reasons: they can
223 223 increase startup overhead; they may be meant for advanced usage only; they
224 224 may provide potentially dangerous abilities (such as letting you destroy
225 225 or modify history); they might not be ready for prime time; or they may
226 226 alter some usual behaviors of stock Mercurial. It is thus up to the user
227 227 to activate extensions as needed.
228 228
229 229 To explicitly disable an extension enabled in a configuration file of
230 230 broader scope, prepend its path with !:
231 231
232 232 [extensions]
233 233 # disabling extension bar residing in /path/to/extension/bar.py
234 234 bar = !/path/to/extension/bar.py
235 235 # ditto, but no path was supplied for extension baz
236 236 baz = !
237 237
238 238 enabled extensions:
239 239
240 240 children command to display child changesets (DEPRECATED)
241 241 rebase command to move sets of revisions to a different ancestor
242 242
243 243 disabled extensions:
244 244
245 245 acl hooks for controlling repository access
246 246 blackbox log repository events to a blackbox for debugging
247 247 bugzilla hooks for integrating with the Bugzilla bug tracker
248 248 churn command to display statistics about repository history
249 249 color colorize output from some commands
250 250 convert import revisions from foreign VCS repositories into
251 251 Mercurial
252 252 eol automatically manage newlines in repository files
253 253 extdiff command to allow external programs to compare revisions
254 254 factotum http authentication with factotum
255 255 gpg commands to sign and verify changesets
256 256 hgcia hooks for integrating with the CIA.vc notification service
257 257 hgk browse the repository in a graphical way
258 258 highlight syntax highlighting for hgweb (requires Pygments)
259 259 histedit interactive history editing
260 260 keyword expand keywords in tracked files
261 261 largefiles track large binary files
262 262 mq manage a stack of patches
263 263 notify hooks for sending email push notifications
264 264 pager browse command output with an external pager
265 265 patchbomb command to send changesets as (a series of) patch emails
266 266 progress show progress bars for some actions
267 267 purge command to delete untracked files from the working
268 268 directory
269 269 record commands to interactively select changes for
270 270 commit/qrefresh
271 271 relink recreates hardlinks between repository clones
272 272 schemes extend schemes with shortcuts to repository swarms
273 273 share share a common history between several working directories
274 274 shelve save and restore changes to the working directory
275 275 strip strip changesets and their descendents from history
276 276 transplant command to transplant changesets from another branch
277 277 win32mbcs allow the use of MBCS paths with problematic encodings
278 278 zeroconf discover and advertise repositories on the local network
279 279 Test short command list with verbose option
280 280
281 281 $ hg -v help shortlist
282 282 Mercurial Distributed SCM
283 283
284 284 basic commands:
285 285
286 286 add add the specified files on the next commit
287 287 annotate, blame
288 288 show changeset information by line for each file
289 289 clone make a copy of an existing repository
290 290 commit, ci commit the specified files or all outstanding changes
291 291 diff diff repository (or selected files)
292 292 export dump the header and diffs for one or more changesets
293 293 forget forget the specified files on the next commit
294 294 init create a new repository in the given directory
295 295 log, history show revision history of entire repository or files
296 296 merge merge working directory with another revision
297 297 pull pull changes from the specified source
298 298 push push changes to the specified destination
299 299 remove, rm remove the specified files on the next commit
300 300 serve start stand-alone webserver
301 301 status, st show changed files in the working directory
302 302 summary, sum summarize working directory state
303 303 update, up, checkout, co
304 304 update working directory (or switch revisions)
305 305
306 306 global options ([+] can be repeated):
307 307
308 308 -R --repository REPO repository root directory or name of overlay bundle
309 309 file
310 310 --cwd DIR change working directory
311 311 -y --noninteractive do not prompt, automatically pick the first choice for
312 312 all prompts
313 313 -q --quiet suppress output
314 314 -v --verbose enable additional output
315 315 --config CONFIG [+] set/override config option (use 'section.name=value')
316 316 --debug enable debugging output
317 317 --debugger start debugger
318 318 --encoding ENCODE set the charset encoding (default: ascii)
319 319 --encodingmode MODE set the charset encoding mode (default: strict)
320 320 --traceback always print a traceback on exception
321 321 --time time how long the command takes
322 322 --profile print command execution profile
323 323 --version output version information and exit
324 324 -h --help display help and exit
325 325 --hidden consider hidden changesets
326 326
327 327 (use "hg help" for the full list of commands)
328 328
329 329 $ hg add -h
330 330 hg add [OPTION]... [FILE]...
331 331
332 332 add the specified files on the next commit
333 333
334 334 Schedule files to be version controlled and added to the repository.
335 335
336 336 The files will be added to the repository at the next commit. To undo an
337 337 add before that, see "hg forget".
338 338
339 339 If no names are given, add all files to the repository.
340 340
341 341 Returns 0 if all files are successfully added.
342 342
343 343 options ([+] can be repeated):
344 344
345 345 -I --include PATTERN [+] include names matching the given patterns
346 346 -X --exclude PATTERN [+] exclude names matching the given patterns
347 347 -S --subrepos recurse into subrepositories
348 348 -n --dry-run do not perform actions, just print output
349 349
350 350 (some details hidden, use --verbose to show complete help)
351 351
352 352 Verbose help for add
353 353
354 354 $ hg add -hv
355 355 hg add [OPTION]... [FILE]...
356 356
357 357 add the specified files on the next commit
358 358
359 359 Schedule files to be version controlled and added to the repository.
360 360
361 361 The files will be added to the repository at the next commit. To undo an
362 362 add before that, see "hg forget".
363 363
364 364 If no names are given, add all files to the repository.
365 365
366 366 An example showing how new (unknown) files are added automatically by "hg
367 367 add":
368 368
369 369 $ ls
370 370 foo.c
371 371 $ hg status
372 372 ? foo.c
373 373 $ hg add
374 374 adding foo.c
375 375 $ hg status
376 376 A foo.c
377 377
378 378 Returns 0 if all files are successfully added.
379 379
380 380 options ([+] can be repeated):
381 381
382 382 -I --include PATTERN [+] include names matching the given patterns
383 383 -X --exclude PATTERN [+] exclude names matching the given patterns
384 384 -S --subrepos recurse into subrepositories
385 385 -n --dry-run do not perform actions, just print output
386 386
387 387 global options ([+] can be repeated):
388 388
389 389 -R --repository REPO repository root directory or name of overlay bundle
390 390 file
391 391 --cwd DIR change working directory
392 392 -y --noninteractive do not prompt, automatically pick the first choice for
393 393 all prompts
394 394 -q --quiet suppress output
395 395 -v --verbose enable additional output
396 396 --config CONFIG [+] set/override config option (use 'section.name=value')
397 397 --debug enable debugging output
398 398 --debugger start debugger
399 399 --encoding ENCODE set the charset encoding (default: ascii)
400 400 --encodingmode MODE set the charset encoding mode (default: strict)
401 401 --traceback always print a traceback on exception
402 402 --time time how long the command takes
403 403 --profile print command execution profile
404 404 --version output version information and exit
405 405 -h --help display help and exit
406 406 --hidden consider hidden changesets
407 407
408 408 Test help option with version option
409 409
410 410 $ hg add -h --version
411 411 Mercurial Distributed SCM (version *) (glob)
412 412 (see http://mercurial.selenic.com for more information)
413 413
414 414 Copyright (C) 2005-2014 Matt Mackall and others
415 415 This is free software; see the source for copying conditions. There is NO
416 416 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
417 417
418 418 $ hg add --skjdfks
419 419 hg add: option --skjdfks not recognized
420 420 hg add [OPTION]... [FILE]...
421 421
422 422 add the specified files on the next commit
423 423
424 424 options ([+] can be repeated):
425 425
426 426 -I --include PATTERN [+] include names matching the given patterns
427 427 -X --exclude PATTERN [+] exclude names matching the given patterns
428 428 -S --subrepos recurse into subrepositories
429 429 -n --dry-run do not perform actions, just print output
430 430
431 431 (use "hg add -h" to show more help)
432 432 [255]
433 433
434 434 Test ambiguous command help
435 435
436 436 $ hg help ad
437 437 list of commands:
438 438
439 439 add add the specified files on the next commit
440 440 addremove add all new files, delete all missing files
441 441
442 442 (use "hg help -v ad" to show built-in aliases and global options)
443 443
444 444 Test command without options
445 445
446 446 $ hg help verify
447 447 hg verify
448 448
449 449 verify the integrity of the repository
450 450
451 451 Verify the integrity of the current repository.
452 452
453 453 This will perform an extensive check of the repository's integrity,
454 454 validating the hashes and checksums of each entry in the changelog,
455 455 manifest, and tracked files, as well as the integrity of their crosslinks
456 456 and indices.
457 457
458 458 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption for more
459 459 information about recovery from corruption of the repository.
460 460
461 461 Returns 0 on success, 1 if errors are encountered.
462 462
463 463 (some details hidden, use --verbose to show complete help)
464 464
465 465 $ hg help diff
466 466 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
467 467
468 468 diff repository (or selected files)
469 469
470 470 Show differences between revisions for the specified files.
471 471
472 472 Differences between files are shown using the unified diff format.
473 473
474 474 Note:
475 475 diff may generate unexpected results for merges, as it will default to
476 476 comparing against the working directory's first parent changeset if no
477 477 revisions are specified.
478 478
479 479 When two revision arguments are given, then changes are shown between
480 480 those revisions. If only one revision is specified then that revision is
481 481 compared to the working directory, and, when no revisions are specified,
482 482 the working directory files are compared to its parent.
483 483
484 484 Alternatively you can specify -c/--change with a revision to see the
485 485 changes in that changeset relative to its first parent.
486 486
487 487 Without the -a/--text option, diff will avoid generating diffs of files it
488 488 detects as binary. With -a, diff will generate a diff anyway, probably
489 489 with undesirable results.
490 490
491 491 Use the -g/--git option to generate diffs in the git extended diff format.
492 492 For more information, read "hg help diffs".
493 493
494 494 Returns 0 on success.
495 495
496 496 options ([+] can be repeated):
497 497
498 498 -r --rev REV [+] revision
499 499 -c --change REV change made by revision
500 500 -a --text treat all files as text
501 501 -g --git use git extended diff format
502 502 --nodates omit dates from diff headers
503 503 -p --show-function show which function each change is in
504 504 --reverse produce a diff that undoes the changes
505 505 -w --ignore-all-space ignore white space when comparing lines
506 506 -b --ignore-space-change ignore changes in the amount of white space
507 507 -B --ignore-blank-lines ignore changes whose lines are all blank
508 508 -U --unified NUM number of lines of context to show
509 509 --stat output diffstat-style summary of changes
510 510 -I --include PATTERN [+] include names matching the given patterns
511 511 -X --exclude PATTERN [+] exclude names matching the given patterns
512 512 -S --subrepos recurse into subrepositories
513 513
514 514 (some details hidden, use --verbose to show complete help)
515 515
516 516 $ hg help status
517 517 hg status [OPTION]... [FILE]...
518 518
519 519 aliases: st
520 520
521 521 show changed files in the working directory
522 522
523 523 Show status of files in the repository. If names are given, only files
524 524 that match are shown. Files that are clean or ignored or the source of a
525 525 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
526 526 -C/--copies or -A/--all are given. Unless options described with "show
527 527 only ..." are given, the options -mardu are used.
528 528
529 529 Option -q/--quiet hides untracked (unknown and ignored) files unless
530 530 explicitly requested with -u/--unknown or -i/--ignored.
531 531
532 532 Note:
533 533 status may appear to disagree with diff if permissions have changed or
534 534 a merge has occurred. The standard diff format does not report
535 535 permission changes and diff only reports changes relative to one merge
536 536 parent.
537 537
538 538 If one revision is given, it is used as the base revision. If two
539 539 revisions are given, the differences between them are shown. The --change
540 540 option can also be used as a shortcut to list the changed files of a
541 541 revision from its first parent.
542 542
543 543 The codes used to show the status of files are:
544 544
545 545 M = modified
546 546 A = added
547 547 R = removed
548 548 C = clean
549 549 ! = missing (deleted by non-hg command, but still tracked)
550 550 ? = not tracked
551 551 I = ignored
552 552 = origin of the previous file (with --copies)
553 553
554 554 Returns 0 on success.
555 555
556 556 options ([+] can be repeated):
557 557
558 558 -A --all show status of all files
559 559 -m --modified show only modified files
560 560 -a --added show only added files
561 561 -r --removed show only removed files
562 562 -d --deleted show only deleted (but tracked) files
563 563 -c --clean show only files without changes
564 564 -u --unknown show only unknown (not tracked) files
565 565 -i --ignored show only ignored files
566 566 -n --no-status hide status prefix
567 567 -C --copies show source of copied files
568 568 -0 --print0 end filenames with NUL, for use with xargs
569 569 --rev REV [+] show difference from revision
570 570 --change REV list the changed files of a revision
571 571 -I --include PATTERN [+] include names matching the given patterns
572 572 -X --exclude PATTERN [+] exclude names matching the given patterns
573 573 -S --subrepos recurse into subrepositories
574 574
575 575 (some details hidden, use --verbose to show complete help)
576 576
577 577 $ hg -q help status
578 578 hg status [OPTION]... [FILE]...
579 579
580 580 show changed files in the working directory
581 581
582 582 $ hg help foo
583 583 abort: no such help topic: foo
584 584 (try "hg help --keyword foo")
585 585 [255]
586 586
587 587 $ hg skjdfks
588 588 hg: unknown command 'skjdfks'
589 589 Mercurial Distributed SCM
590 590
591 591 basic commands:
592 592
593 593 add add the specified files on the next commit
594 594 annotate show changeset information by line for each file
595 595 clone make a copy of an existing repository
596 596 commit commit the specified files or all outstanding changes
597 597 diff diff repository (or selected files)
598 598 export dump the header and diffs for one or more changesets
599 599 forget forget the specified files on the next commit
600 600 init create a new repository in the given directory
601 601 log show revision history of entire repository or files
602 602 merge merge working directory with another revision
603 603 pull pull changes from the specified source
604 604 push push changes to the specified destination
605 605 remove remove the specified files on the next commit
606 606 serve start stand-alone webserver
607 607 status show changed files in the working directory
608 608 summary summarize working directory state
609 609 update update working directory (or switch revisions)
610 610
611 611 (use "hg help" for the full list of commands or "hg -v" for details)
612 612 [255]
613 613
614 614
615 615 $ cat > helpext.py <<EOF
616 616 > import os
617 617 > from mercurial import cmdutil, commands
618 618 >
619 619 > cmdtable = {}
620 620 > command = cmdutil.command(cmdtable)
621 621 >
622 622 > @command('nohelp',
623 623 > [('', 'longdesc', 3, 'x'*90),
624 624 > ('n', '', None, 'normal desc'),
625 625 > ('', 'newline', '', 'line1\nline2')],
626 626 > 'hg nohelp',
627 627 > norepo=True)
628 628 > @command('debugoptDEP', [('', 'dopt', None, 'option is DEPRECATED')])
629 629 > def nohelp(ui, *args, **kwargs):
630 630 > pass
631 631 >
632 632 > EOF
633 633 $ echo '[extensions]' >> $HGRCPATH
634 634 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
635 635
636 636 Test command with no help text
637 637
638 638 $ hg help nohelp
639 639 hg nohelp
640 640
641 641 (no help text available)
642 642
643 643 options:
644 644
645 645 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
646 646 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
647 647 -n -- normal desc
648 648 --newline VALUE line1 line2
649 649
650 650 (some details hidden, use --verbose to show complete help)
651 651
652 652 $ hg help -k nohelp
653 653 Commands:
654 654
655 655 nohelp hg nohelp
656 656
657 657 Extension Commands:
658 658
659 659 nohelp (no help text available)
660 660
661 661 Test that default list of commands omits extension commands
662 662
663 663 $ hg help
664 664 Mercurial Distributed SCM
665 665
666 666 list of commands:
667 667
668 668 add add the specified files on the next commit
669 669 addremove add all new files, delete all missing files
670 670 annotate show changeset information by line for each file
671 671 archive create an unversioned archive of a repository revision
672 672 backout reverse effect of earlier changeset
673 673 bisect subdivision search of changesets
674 674 bookmarks create a new bookmark or list existing bookmarks
675 675 branch set or show the current branch name
676 676 branches list repository named branches
677 677 bundle create a changegroup file
678 678 cat output the current or given revision of files
679 679 clone make a copy of an existing repository
680 680 commit commit the specified files or all outstanding changes
681 681 config show combined config settings from all hgrc files
682 682 copy mark files as copied for the next commit
683 683 diff diff repository (or selected files)
684 684 export dump the header and diffs for one or more changesets
685 685 files list tracked files
686 686 forget forget the specified files on the next commit
687 687 graft copy changes from other branches onto the current branch
688 688 grep search for a pattern in specified files and revisions
689 689 heads show branch heads
690 690 help show help for a given topic or a help overview
691 691 identify identify the working copy or specified revision
692 692 import import an ordered set of patches
693 693 incoming show new changesets found in source
694 694 init create a new repository in the given directory
695 695 log show revision history of entire repository or files
696 696 manifest output the current or given revision of the project manifest
697 697 merge merge working directory with another revision
698 698 outgoing show changesets not found in the destination
699 699 paths show aliases for remote repositories
700 700 phase set or show the current phase name
701 701 pull pull changes from the specified source
702 702 push push changes to the specified destination
703 703 recover roll back an interrupted transaction
704 704 remove remove the specified files on the next commit
705 705 rename rename files; equivalent of copy + remove
706 706 resolve redo merges or set/view the merge status of files
707 707 revert restore files to their checkout state
708 708 root print the root (top) of the current working directory
709 709 serve start stand-alone webserver
710 710 status show changed files in the working directory
711 711 summary summarize working directory state
712 712 tag add one or more tags for the current or given revision
713 713 tags list repository tags
714 714 unbundle apply one or more changegroup files
715 715 update update working directory (or switch revisions)
716 716 verify verify the integrity of the repository
717 717 version output version and copyright information
718 718
719 719 enabled extensions:
720 720
721 721 helpext (no help text available)
722 722
723 723 additional help topics:
724 724
725 725 config Configuration Files
726 726 dates Date Formats
727 727 diffs Diff Formats
728 728 environment Environment Variables
729 729 extensions Using Additional Features
730 730 filesets Specifying File Sets
731 731 glossary Glossary
732 732 hgignore Syntax for Mercurial Ignore Files
733 733 hgweb Configuring hgweb
734 734 merge-tools Merge Tools
735 735 multirevs Specifying Multiple Revisions
736 736 patterns File Name Patterns
737 737 phases Working with Phases
738 738 revisions Specifying Single Revisions
739 739 revsets Specifying Revision Sets
740 740 subrepos Subrepositories
741 741 templating Template Usage
742 742 urls URL Paths
743 743
744 744 (use "hg help -v" to show built-in aliases and global options)
745 745
746 746
747 747 Test list of internal help commands
748 748
749 749 $ hg help debug
750 750 debug commands (internal and unsupported):
751 751
752 752 debugancestor
753 753 find the ancestor revision of two revisions in a given index
754 754 debugbuilddag
755 755 builds a repo with a given DAG from scratch in the current
756 756 empty repo
757 757 debugbundle lists the contents of a bundle
758 758 debugcheckstate
759 759 validate the correctness of the current dirstate
760 760 debugcommands
761 761 list all available commands and options
762 762 debugcomplete
763 763 returns the completion list associated with the given command
764 764 debugdag format the changelog or an index DAG as a concise textual
765 765 description
766 766 debugdata dump the contents of a data file revision
767 767 debugdate parse and display a date
768 768 debugdirstate
769 769 show the contents of the current dirstate
770 770 debugdiscovery
771 771 runs the changeset discovery protocol in isolation
772 772 debugfileset parse and apply a fileset specification
773 773 debugfsinfo show information detected about current filesystem
774 774 debuggetbundle
775 775 retrieves a bundle from a repo
776 776 debugignore display the combined ignore pattern
777 777 debugindex dump the contents of an index file
778 778 debugindexdot
779 779 dump an index DAG as a graphviz dot file
780 780 debuginstall test Mercurial installation
781 781 debugknown test whether node ids are known to a repo
782 782 debuglabelcomplete
783 783 complete "labels" - tags, open branch names, bookmark names
784 784 debuglocks show or modify state of locks
785 785 debugobsolete
786 786 create arbitrary obsolete marker
787 787 debugoptDEP (no help text available)
788 788 debugpathcomplete
789 789 complete part or all of a tracked path
790 790 debugpushkey access the pushkey key/value protocol
791 791 debugpvec (no help text available)
792 792 debugrebuilddirstate
793 793 rebuild the dirstate as it would look like for the given
794 794 revision
795 795 debugrename dump rename information
796 796 debugrevlog show data and statistics about a revlog
797 797 debugrevspec parse and apply a revision specification
798 798 debugsetparents
799 799 manually set the parents of the current working directory
800 800 debugsub (no help text available)
801 801 debugsuccessorssets
802 802 show set of successors for revision
803 803 debugwalk show how files match on given patterns
804 804 debugwireargs
805 805 (no help text available)
806 806
807 807 (use "hg help -v debug" to show built-in aliases and global options)
808 808
809 809
810 810 Test list of commands with command with no help text
811 811
812 812 $ hg help helpext
813 813 helpext extension - no help text available
814 814
815 815 list of commands:
816 816
817 817 nohelp (no help text available)
818 818
819 819 (use "hg help -v helpext" to show built-in aliases and global options)
820 820
821 821
822 822 test deprecated option is hidden in command help
823 823 $ hg help debugoptDEP
824 824 hg debugoptDEP
825 825
826 826 (no help text available)
827 827
828 828 options:
829 829
830 830 (some details hidden, use --verbose to show complete help)
831 831
832 832 test deprecated option is shown with -v
833 833 $ hg help -v debugoptDEP | grep dopt
834 834 --dopt option is DEPRECATED
835 835
836 836 #if gettext
837 837 test deprecated option is hidden with translation with untranslated description
838 838 (use many globy for not failing on changed transaction)
839 839 $ LANGUAGE=sv hg help debugoptDEP
840 840 hg debugoptDEP
841 841
842 842 (*) (glob)
843 843
844 844 options:
845 845
846 846 (some details hidden, use --verbose to show complete help)
847 847 #endif
848 848
849 849 Test commands that collide with topics (issue4240)
850 850
851 851 $ hg config -hq
852 852 hg config [-u] [NAME]...
853 853
854 854 show combined config settings from all hgrc files
855 855 $ hg showconfig -hq
856 856 hg config [-u] [NAME]...
857 857
858 858 show combined config settings from all hgrc files
859 859
860 860 Test a help topic
861 861
862 862 $ hg help revs
863 863 Specifying Single Revisions
864 864 """""""""""""""""""""""""""
865 865
866 866 Mercurial supports several ways to specify individual revisions.
867 867
868 868 A plain integer is treated as a revision number. Negative integers are
869 869 treated as sequential offsets from the tip, with -1 denoting the tip, -2
870 870 denoting the revision prior to the tip, and so forth.
871 871
872 872 A 40-digit hexadecimal string is treated as a unique revision identifier.
873 873
874 874 A hexadecimal string less than 40 characters long is treated as a unique
875 875 revision identifier and is referred to as a short-form identifier. A
876 876 short-form identifier is only valid if it is the prefix of exactly one
877 877 full-length identifier.
878 878
879 879 Any other string is treated as a bookmark, tag, or branch name. A bookmark
880 880 is a movable pointer to a revision. A tag is a permanent name associated
881 881 with a revision. A branch name denotes the tipmost open branch head of
882 882 that branch - or if they are all closed, the tipmost closed head of the
883 883 branch. Bookmark, tag, and branch names must not contain the ":"
884 884 character.
885 885
886 886 The reserved name "tip" always identifies the most recent revision.
887 887
888 888 The reserved name "null" indicates the null revision. This is the revision
889 889 of an empty repository, and the parent of revision 0.
890 890
891 891 The reserved name "." indicates the working directory parent. If no
892 892 working directory is checked out, it is equivalent to null. If an
893 893 uncommitted merge is in progress, "." is the revision of the first parent.
894 894
895 895 Test templating help
896 896
897 897 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
898 898 desc String. The text of the changeset description.
899 899 diffstat String. Statistics of changes with the following format:
900 900 firstline Any text. Returns the first line of text.
901 901 nonempty Any text. Returns '(none)' if the string is empty.
902 902
903 903 Test help hooks
904 904
905 905 $ cat > helphook1.py <<EOF
906 906 > from mercurial import help
907 907 >
908 908 > def rewrite(topic, doc):
909 909 > return doc + '\nhelphook1\n'
910 910 >
911 911 > def extsetup(ui):
912 912 > help.addtopichook('revsets', rewrite)
913 913 > EOF
914 914 $ cat > helphook2.py <<EOF
915 915 > from mercurial import help
916 916 >
917 917 > def rewrite(topic, doc):
918 918 > return doc + '\nhelphook2\n'
919 919 >
920 920 > def extsetup(ui):
921 921 > help.addtopichook('revsets', rewrite)
922 922 > EOF
923 923 $ echo '[extensions]' >> $HGRCPATH
924 924 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
925 925 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
926 926 $ hg help revsets | grep helphook
927 927 helphook1
928 928 helphook2
929 929
930 930 Test keyword search help
931 931
932 932 $ cat > prefixedname.py <<EOF
933 933 > '''matched against word "clone"
934 934 > '''
935 935 > EOF
936 936 $ echo '[extensions]' >> $HGRCPATH
937 937 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
938 938 $ hg help -k clone
939 939 Topics:
940 940
941 941 config Configuration Files
942 942 extensions Using Additional Features
943 943 glossary Glossary
944 944 phases Working with Phases
945 945 subrepos Subrepositories
946 946 urls URL Paths
947 947
948 948 Commands:
949 949
950 950 bookmarks create a new bookmark or list existing bookmarks
951 951 clone make a copy of an existing repository
952 952 paths show aliases for remote repositories
953 953 update update working directory (or switch revisions)
954 954
955 955 Extensions:
956 956
957 957 prefixedname matched against word "clone"
958 958 relink recreates hardlinks between repository clones
959 959
960 960 Extension Commands:
961 961
962 962 qclone clone main and patch repository at same time
963 963
964 964 Test unfound topic
965 965
966 966 $ hg help nonexistingtopicthatwillneverexisteverever
967 967 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
968 968 (try "hg help --keyword nonexistingtopicthatwillneverexisteverever")
969 969 [255]
970 970
971 971 Test unfound keyword
972 972
973 973 $ hg help --keyword nonexistingwordthatwillneverexisteverever
974 974 abort: no matches
975 975 (try "hg help" for a list of topics)
976 976 [255]
977 977
978 978 Test omit indicating for help
979 979
980 980 $ cat > addverboseitems.py <<EOF
981 981 > '''extension to test omit indicating.
982 982 >
983 983 > This paragraph is never omitted (for extension)
984 984 >
985 985 > .. container:: verbose
986 986 >
987 987 > This paragraph is omitted,
988 988 > if :hg:\`help\` is invoked witout \`\`-v\`\` (for extension)
989 989 >
990 990 > This paragraph is never omitted, too (for extension)
991 991 > '''
992 992 >
993 993 > from mercurial import help, commands
994 994 > testtopic = """This paragraph is never omitted (for topic).
995 995 >
996 996 > .. container:: verbose
997 997 >
998 998 > This paragraph is omitted,
999 999 > if :hg:\`help\` is invoked witout \`\`-v\`\` (for topic)
1000 1000 >
1001 1001 > This paragraph is never omitted, too (for topic)
1002 1002 > """
1003 1003 > def extsetup(ui):
1004 1004 > help.helptable.append((["topic-containing-verbose"],
1005 1005 > "This is the topic to test omit indicating.",
1006 1006 > lambda : testtopic))
1007 1007 > EOF
1008 1008 $ echo '[extensions]' >> $HGRCPATH
1009 1009 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1010 1010 $ hg help addverboseitems
1011 1011 addverboseitems extension - extension to test omit indicating.
1012 1012
1013 1013 This paragraph is never omitted (for extension)
1014 1014
1015 1015 This paragraph is never omitted, too (for extension)
1016 1016
1017 1017 (some details hidden, use --verbose to show complete help)
1018 1018
1019 1019 no commands defined
1020 1020 $ hg help -v addverboseitems
1021 1021 addverboseitems extension - extension to test omit indicating.
1022 1022
1023 1023 This paragraph is never omitted (for extension)
1024 1024
1025 1025 This paragraph is omitted, if "hg help" is invoked witout "-v" (for extension)
1026 1026
1027 1027 This paragraph is never omitted, too (for extension)
1028 1028
1029 1029 no commands defined
1030 1030 $ hg help topic-containing-verbose
1031 1031 This is the topic to test omit indicating.
1032 1032 """"""""""""""""""""""""""""""""""""""""""
1033 1033
1034 1034 This paragraph is never omitted (for topic).
1035 1035
1036 1036 This paragraph is never omitted, too (for topic)
1037 1037
1038 1038 (some details hidden, use --verbose to show complete help)
1039 1039 $ hg help -v topic-containing-verbose
1040 1040 This is the topic to test omit indicating.
1041 1041 """"""""""""""""""""""""""""""""""""""""""
1042 1042
1043 1043 This paragraph is never omitted (for topic).
1044 1044
1045 1045 This paragraph is omitted, if "hg help" is invoked witout "-v" (for topic)
1046 1046
1047 1047 This paragraph is never omitted, too (for topic)
1048 1048
1049 Test section lookup
1050
1051 $ hg help revset.merge
1052 "merge()"
1053 Changeset is a merge changeset.
1054
1055 $ hg help glossary.dag
1056 DAG
1057 The repository of changesets of a distributed version control system
1058 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1059 of nodes and edges, where nodes correspond to changesets and edges
1060 imply a parent -> child relation. This graph can be visualized by
1061 graphical tools such as "hg log --graph". In Mercurial, the DAG is
1062 limited by the requirement for children to have at most two parents.
1063
1064 $ hg help glossary.mcguffin
1065 abort: help section not found
1066 [255]
1067
1049 1068 Test usage of section marks in help documents
1050 1069
1051 1070 $ cd "$TESTDIR"/../doc
1052 1071 $ python check-seclevel.py
1053 1072 $ cd $TESTTMP
1054 1073
1055 1074 #if serve
1056 1075
1057 1076 Test the help pages in hgweb.
1058 1077
1059 1078 Dish up an empty repo; serve it cold.
1060 1079
1061 1080 $ hg init "$TESTTMP/test"
1062 1081 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1063 1082 $ cat hg.pid >> $DAEMON_PIDS
1064 1083
1065 1084 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help"
1066 1085 200 Script output follows
1067 1086
1068 1087 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1069 1088 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1070 1089 <head>
1071 1090 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1072 1091 <meta name="robots" content="index, nofollow" />
1073 1092 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1074 1093 <script type="text/javascript" src="/static/mercurial.js"></script>
1075 1094
1076 1095 <title>Help: Index</title>
1077 1096 </head>
1078 1097 <body>
1079 1098
1080 1099 <div class="container">
1081 1100 <div class="menu">
1082 1101 <div class="logo">
1083 1102 <a href="http://mercurial.selenic.com/">
1084 1103 <img src="/static/hglogo.png" alt="mercurial" /></a>
1085 1104 </div>
1086 1105 <ul>
1087 1106 <li><a href="/shortlog">log</a></li>
1088 1107 <li><a href="/graph">graph</a></li>
1089 1108 <li><a href="/tags">tags</a></li>
1090 1109 <li><a href="/bookmarks">bookmarks</a></li>
1091 1110 <li><a href="/branches">branches</a></li>
1092 1111 </ul>
1093 1112 <ul>
1094 1113 <li class="active">help</li>
1095 1114 </ul>
1096 1115 </div>
1097 1116
1098 1117 <div class="main">
1099 1118 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1100 1119 <form class="search" action="/log">
1101 1120
1102 1121 <p><input name="rev" id="search1" type="text" size="30" /></p>
1103 1122 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1104 1123 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1105 1124 </form>
1106 1125 <table class="bigtable">
1107 1126 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
1108 1127
1109 1128 <tr><td>
1110 1129 <a href="/help/config">
1111 1130 config
1112 1131 </a>
1113 1132 </td><td>
1114 1133 Configuration Files
1115 1134 </td></tr>
1116 1135 <tr><td>
1117 1136 <a href="/help/dates">
1118 1137 dates
1119 1138 </a>
1120 1139 </td><td>
1121 1140 Date Formats
1122 1141 </td></tr>
1123 1142 <tr><td>
1124 1143 <a href="/help/diffs">
1125 1144 diffs
1126 1145 </a>
1127 1146 </td><td>
1128 1147 Diff Formats
1129 1148 </td></tr>
1130 1149 <tr><td>
1131 1150 <a href="/help/environment">
1132 1151 environment
1133 1152 </a>
1134 1153 </td><td>
1135 1154 Environment Variables
1136 1155 </td></tr>
1137 1156 <tr><td>
1138 1157 <a href="/help/extensions">
1139 1158 extensions
1140 1159 </a>
1141 1160 </td><td>
1142 1161 Using Additional Features
1143 1162 </td></tr>
1144 1163 <tr><td>
1145 1164 <a href="/help/filesets">
1146 1165 filesets
1147 1166 </a>
1148 1167 </td><td>
1149 1168 Specifying File Sets
1150 1169 </td></tr>
1151 1170 <tr><td>
1152 1171 <a href="/help/glossary">
1153 1172 glossary
1154 1173 </a>
1155 1174 </td><td>
1156 1175 Glossary
1157 1176 </td></tr>
1158 1177 <tr><td>
1159 1178 <a href="/help/hgignore">
1160 1179 hgignore
1161 1180 </a>
1162 1181 </td><td>
1163 1182 Syntax for Mercurial Ignore Files
1164 1183 </td></tr>
1165 1184 <tr><td>
1166 1185 <a href="/help/hgweb">
1167 1186 hgweb
1168 1187 </a>
1169 1188 </td><td>
1170 1189 Configuring hgweb
1171 1190 </td></tr>
1172 1191 <tr><td>
1173 1192 <a href="/help/merge-tools">
1174 1193 merge-tools
1175 1194 </a>
1176 1195 </td><td>
1177 1196 Merge Tools
1178 1197 </td></tr>
1179 1198 <tr><td>
1180 1199 <a href="/help/multirevs">
1181 1200 multirevs
1182 1201 </a>
1183 1202 </td><td>
1184 1203 Specifying Multiple Revisions
1185 1204 </td></tr>
1186 1205 <tr><td>
1187 1206 <a href="/help/patterns">
1188 1207 patterns
1189 1208 </a>
1190 1209 </td><td>
1191 1210 File Name Patterns
1192 1211 </td></tr>
1193 1212 <tr><td>
1194 1213 <a href="/help/phases">
1195 1214 phases
1196 1215 </a>
1197 1216 </td><td>
1198 1217 Working with Phases
1199 1218 </td></tr>
1200 1219 <tr><td>
1201 1220 <a href="/help/revisions">
1202 1221 revisions
1203 1222 </a>
1204 1223 </td><td>
1205 1224 Specifying Single Revisions
1206 1225 </td></tr>
1207 1226 <tr><td>
1208 1227 <a href="/help/revsets">
1209 1228 revsets
1210 1229 </a>
1211 1230 </td><td>
1212 1231 Specifying Revision Sets
1213 1232 </td></tr>
1214 1233 <tr><td>
1215 1234 <a href="/help/subrepos">
1216 1235 subrepos
1217 1236 </a>
1218 1237 </td><td>
1219 1238 Subrepositories
1220 1239 </td></tr>
1221 1240 <tr><td>
1222 1241 <a href="/help/templating">
1223 1242 templating
1224 1243 </a>
1225 1244 </td><td>
1226 1245 Template Usage
1227 1246 </td></tr>
1228 1247 <tr><td>
1229 1248 <a href="/help/urls">
1230 1249 urls
1231 1250 </a>
1232 1251 </td><td>
1233 1252 URL Paths
1234 1253 </td></tr>
1235 1254 <tr><td>
1236 1255 <a href="/help/topic-containing-verbose">
1237 1256 topic-containing-verbose
1238 1257 </a>
1239 1258 </td><td>
1240 1259 This is the topic to test omit indicating.
1241 1260 </td></tr>
1242 1261
1243 1262 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1244 1263
1245 1264 <tr><td>
1246 1265 <a href="/help/add">
1247 1266 add
1248 1267 </a>
1249 1268 </td><td>
1250 1269 add the specified files on the next commit
1251 1270 </td></tr>
1252 1271 <tr><td>
1253 1272 <a href="/help/annotate">
1254 1273 annotate
1255 1274 </a>
1256 1275 </td><td>
1257 1276 show changeset information by line for each file
1258 1277 </td></tr>
1259 1278 <tr><td>
1260 1279 <a href="/help/clone">
1261 1280 clone
1262 1281 </a>
1263 1282 </td><td>
1264 1283 make a copy of an existing repository
1265 1284 </td></tr>
1266 1285 <tr><td>
1267 1286 <a href="/help/commit">
1268 1287 commit
1269 1288 </a>
1270 1289 </td><td>
1271 1290 commit the specified files or all outstanding changes
1272 1291 </td></tr>
1273 1292 <tr><td>
1274 1293 <a href="/help/diff">
1275 1294 diff
1276 1295 </a>
1277 1296 </td><td>
1278 1297 diff repository (or selected files)
1279 1298 </td></tr>
1280 1299 <tr><td>
1281 1300 <a href="/help/export">
1282 1301 export
1283 1302 </a>
1284 1303 </td><td>
1285 1304 dump the header and diffs for one or more changesets
1286 1305 </td></tr>
1287 1306 <tr><td>
1288 1307 <a href="/help/forget">
1289 1308 forget
1290 1309 </a>
1291 1310 </td><td>
1292 1311 forget the specified files on the next commit
1293 1312 </td></tr>
1294 1313 <tr><td>
1295 1314 <a href="/help/init">
1296 1315 init
1297 1316 </a>
1298 1317 </td><td>
1299 1318 create a new repository in the given directory
1300 1319 </td></tr>
1301 1320 <tr><td>
1302 1321 <a href="/help/log">
1303 1322 log
1304 1323 </a>
1305 1324 </td><td>
1306 1325 show revision history of entire repository or files
1307 1326 </td></tr>
1308 1327 <tr><td>
1309 1328 <a href="/help/merge">
1310 1329 merge
1311 1330 </a>
1312 1331 </td><td>
1313 1332 merge working directory with another revision
1314 1333 </td></tr>
1315 1334 <tr><td>
1316 1335 <a href="/help/pull">
1317 1336 pull
1318 1337 </a>
1319 1338 </td><td>
1320 1339 pull changes from the specified source
1321 1340 </td></tr>
1322 1341 <tr><td>
1323 1342 <a href="/help/push">
1324 1343 push
1325 1344 </a>
1326 1345 </td><td>
1327 1346 push changes to the specified destination
1328 1347 </td></tr>
1329 1348 <tr><td>
1330 1349 <a href="/help/remove">
1331 1350 remove
1332 1351 </a>
1333 1352 </td><td>
1334 1353 remove the specified files on the next commit
1335 1354 </td></tr>
1336 1355 <tr><td>
1337 1356 <a href="/help/serve">
1338 1357 serve
1339 1358 </a>
1340 1359 </td><td>
1341 1360 start stand-alone webserver
1342 1361 </td></tr>
1343 1362 <tr><td>
1344 1363 <a href="/help/status">
1345 1364 status
1346 1365 </a>
1347 1366 </td><td>
1348 1367 show changed files in the working directory
1349 1368 </td></tr>
1350 1369 <tr><td>
1351 1370 <a href="/help/summary">
1352 1371 summary
1353 1372 </a>
1354 1373 </td><td>
1355 1374 summarize working directory state
1356 1375 </td></tr>
1357 1376 <tr><td>
1358 1377 <a href="/help/update">
1359 1378 update
1360 1379 </a>
1361 1380 </td><td>
1362 1381 update working directory (or switch revisions)
1363 1382 </td></tr>
1364 1383
1365 1384 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
1366 1385
1367 1386 <tr><td>
1368 1387 <a href="/help/addremove">
1369 1388 addremove
1370 1389 </a>
1371 1390 </td><td>
1372 1391 add all new files, delete all missing files
1373 1392 </td></tr>
1374 1393 <tr><td>
1375 1394 <a href="/help/archive">
1376 1395 archive
1377 1396 </a>
1378 1397 </td><td>
1379 1398 create an unversioned archive of a repository revision
1380 1399 </td></tr>
1381 1400 <tr><td>
1382 1401 <a href="/help/backout">
1383 1402 backout
1384 1403 </a>
1385 1404 </td><td>
1386 1405 reverse effect of earlier changeset
1387 1406 </td></tr>
1388 1407 <tr><td>
1389 1408 <a href="/help/bisect">
1390 1409 bisect
1391 1410 </a>
1392 1411 </td><td>
1393 1412 subdivision search of changesets
1394 1413 </td></tr>
1395 1414 <tr><td>
1396 1415 <a href="/help/bookmarks">
1397 1416 bookmarks
1398 1417 </a>
1399 1418 </td><td>
1400 1419 create a new bookmark or list existing bookmarks
1401 1420 </td></tr>
1402 1421 <tr><td>
1403 1422 <a href="/help/branch">
1404 1423 branch
1405 1424 </a>
1406 1425 </td><td>
1407 1426 set or show the current branch name
1408 1427 </td></tr>
1409 1428 <tr><td>
1410 1429 <a href="/help/branches">
1411 1430 branches
1412 1431 </a>
1413 1432 </td><td>
1414 1433 list repository named branches
1415 1434 </td></tr>
1416 1435 <tr><td>
1417 1436 <a href="/help/bundle">
1418 1437 bundle
1419 1438 </a>
1420 1439 </td><td>
1421 1440 create a changegroup file
1422 1441 </td></tr>
1423 1442 <tr><td>
1424 1443 <a href="/help/cat">
1425 1444 cat
1426 1445 </a>
1427 1446 </td><td>
1428 1447 output the current or given revision of files
1429 1448 </td></tr>
1430 1449 <tr><td>
1431 1450 <a href="/help/config">
1432 1451 config
1433 1452 </a>
1434 1453 </td><td>
1435 1454 show combined config settings from all hgrc files
1436 1455 </td></tr>
1437 1456 <tr><td>
1438 1457 <a href="/help/copy">
1439 1458 copy
1440 1459 </a>
1441 1460 </td><td>
1442 1461 mark files as copied for the next commit
1443 1462 </td></tr>
1444 1463 <tr><td>
1445 1464 <a href="/help/files">
1446 1465 files
1447 1466 </a>
1448 1467 </td><td>
1449 1468 list tracked files
1450 1469 </td></tr>
1451 1470 <tr><td>
1452 1471 <a href="/help/graft">
1453 1472 graft
1454 1473 </a>
1455 1474 </td><td>
1456 1475 copy changes from other branches onto the current branch
1457 1476 </td></tr>
1458 1477 <tr><td>
1459 1478 <a href="/help/grep">
1460 1479 grep
1461 1480 </a>
1462 1481 </td><td>
1463 1482 search for a pattern in specified files and revisions
1464 1483 </td></tr>
1465 1484 <tr><td>
1466 1485 <a href="/help/heads">
1467 1486 heads
1468 1487 </a>
1469 1488 </td><td>
1470 1489 show branch heads
1471 1490 </td></tr>
1472 1491 <tr><td>
1473 1492 <a href="/help/help">
1474 1493 help
1475 1494 </a>
1476 1495 </td><td>
1477 1496 show help for a given topic or a help overview
1478 1497 </td></tr>
1479 1498 <tr><td>
1480 1499 <a href="/help/identify">
1481 1500 identify
1482 1501 </a>
1483 1502 </td><td>
1484 1503 identify the working copy or specified revision
1485 1504 </td></tr>
1486 1505 <tr><td>
1487 1506 <a href="/help/import">
1488 1507 import
1489 1508 </a>
1490 1509 </td><td>
1491 1510 import an ordered set of patches
1492 1511 </td></tr>
1493 1512 <tr><td>
1494 1513 <a href="/help/incoming">
1495 1514 incoming
1496 1515 </a>
1497 1516 </td><td>
1498 1517 show new changesets found in source
1499 1518 </td></tr>
1500 1519 <tr><td>
1501 1520 <a href="/help/manifest">
1502 1521 manifest
1503 1522 </a>
1504 1523 </td><td>
1505 1524 output the current or given revision of the project manifest
1506 1525 </td></tr>
1507 1526 <tr><td>
1508 1527 <a href="/help/nohelp">
1509 1528 nohelp
1510 1529 </a>
1511 1530 </td><td>
1512 1531 (no help text available)
1513 1532 </td></tr>
1514 1533 <tr><td>
1515 1534 <a href="/help/outgoing">
1516 1535 outgoing
1517 1536 </a>
1518 1537 </td><td>
1519 1538 show changesets not found in the destination
1520 1539 </td></tr>
1521 1540 <tr><td>
1522 1541 <a href="/help/paths">
1523 1542 paths
1524 1543 </a>
1525 1544 </td><td>
1526 1545 show aliases for remote repositories
1527 1546 </td></tr>
1528 1547 <tr><td>
1529 1548 <a href="/help/phase">
1530 1549 phase
1531 1550 </a>
1532 1551 </td><td>
1533 1552 set or show the current phase name
1534 1553 </td></tr>
1535 1554 <tr><td>
1536 1555 <a href="/help/recover">
1537 1556 recover
1538 1557 </a>
1539 1558 </td><td>
1540 1559 roll back an interrupted transaction
1541 1560 </td></tr>
1542 1561 <tr><td>
1543 1562 <a href="/help/rename">
1544 1563 rename
1545 1564 </a>
1546 1565 </td><td>
1547 1566 rename files; equivalent of copy + remove
1548 1567 </td></tr>
1549 1568 <tr><td>
1550 1569 <a href="/help/resolve">
1551 1570 resolve
1552 1571 </a>
1553 1572 </td><td>
1554 1573 redo merges or set/view the merge status of files
1555 1574 </td></tr>
1556 1575 <tr><td>
1557 1576 <a href="/help/revert">
1558 1577 revert
1559 1578 </a>
1560 1579 </td><td>
1561 1580 restore files to their checkout state
1562 1581 </td></tr>
1563 1582 <tr><td>
1564 1583 <a href="/help/root">
1565 1584 root
1566 1585 </a>
1567 1586 </td><td>
1568 1587 print the root (top) of the current working directory
1569 1588 </td></tr>
1570 1589 <tr><td>
1571 1590 <a href="/help/tag">
1572 1591 tag
1573 1592 </a>
1574 1593 </td><td>
1575 1594 add one or more tags for the current or given revision
1576 1595 </td></tr>
1577 1596 <tr><td>
1578 1597 <a href="/help/tags">
1579 1598 tags
1580 1599 </a>
1581 1600 </td><td>
1582 1601 list repository tags
1583 1602 </td></tr>
1584 1603 <tr><td>
1585 1604 <a href="/help/unbundle">
1586 1605 unbundle
1587 1606 </a>
1588 1607 </td><td>
1589 1608 apply one or more changegroup files
1590 1609 </td></tr>
1591 1610 <tr><td>
1592 1611 <a href="/help/verify">
1593 1612 verify
1594 1613 </a>
1595 1614 </td><td>
1596 1615 verify the integrity of the repository
1597 1616 </td></tr>
1598 1617 <tr><td>
1599 1618 <a href="/help/version">
1600 1619 version
1601 1620 </a>
1602 1621 </td><td>
1603 1622 output version and copyright information
1604 1623 </td></tr>
1605 1624 </table>
1606 1625 </div>
1607 1626 </div>
1608 1627
1609 1628 <script type="text/javascript">process_dates()</script>
1610 1629
1611 1630
1612 1631 </body>
1613 1632 </html>
1614 1633
1615 1634
1616 1635 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/add"
1617 1636 200 Script output follows
1618 1637
1619 1638 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1620 1639 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1621 1640 <head>
1622 1641 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1623 1642 <meta name="robots" content="index, nofollow" />
1624 1643 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1625 1644 <script type="text/javascript" src="/static/mercurial.js"></script>
1626 1645
1627 1646 <title>Help: add</title>
1628 1647 </head>
1629 1648 <body>
1630 1649
1631 1650 <div class="container">
1632 1651 <div class="menu">
1633 1652 <div class="logo">
1634 1653 <a href="http://mercurial.selenic.com/">
1635 1654 <img src="/static/hglogo.png" alt="mercurial" /></a>
1636 1655 </div>
1637 1656 <ul>
1638 1657 <li><a href="/shortlog">log</a></li>
1639 1658 <li><a href="/graph">graph</a></li>
1640 1659 <li><a href="/tags">tags</a></li>
1641 1660 <li><a href="/bookmarks">bookmarks</a></li>
1642 1661 <li><a href="/branches">branches</a></li>
1643 1662 </ul>
1644 1663 <ul>
1645 1664 <li class="active"><a href="/help">help</a></li>
1646 1665 </ul>
1647 1666 </div>
1648 1667
1649 1668 <div class="main">
1650 1669 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1651 1670 <h3>Help: add</h3>
1652 1671
1653 1672 <form class="search" action="/log">
1654 1673
1655 1674 <p><input name="rev" id="search1" type="text" size="30" /></p>
1656 1675 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1657 1676 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1658 1677 </form>
1659 1678 <div id="doc">
1660 1679 <p>
1661 1680 hg add [OPTION]... [FILE]...
1662 1681 </p>
1663 1682 <p>
1664 1683 add the specified files on the next commit
1665 1684 </p>
1666 1685 <p>
1667 1686 Schedule files to be version controlled and added to the
1668 1687 repository.
1669 1688 </p>
1670 1689 <p>
1671 1690 The files will be added to the repository at the next commit. To
1672 1691 undo an add before that, see &quot;hg forget&quot;.
1673 1692 </p>
1674 1693 <p>
1675 1694 If no names are given, add all files to the repository.
1676 1695 </p>
1677 1696 <p>
1678 1697 An example showing how new (unknown) files are added
1679 1698 automatically by &quot;hg add&quot;:
1680 1699 </p>
1681 1700 <pre>
1682 1701 \$ ls (re)
1683 1702 foo.c
1684 1703 \$ hg status (re)
1685 1704 ? foo.c
1686 1705 \$ hg add (re)
1687 1706 adding foo.c
1688 1707 \$ hg status (re)
1689 1708 A foo.c
1690 1709 </pre>
1691 1710 <p>
1692 1711 Returns 0 if all files are successfully added.
1693 1712 </p>
1694 1713 <p>
1695 1714 options ([+] can be repeated):
1696 1715 </p>
1697 1716 <table>
1698 1717 <tr><td>-I</td>
1699 1718 <td>--include PATTERN [+]</td>
1700 1719 <td>include names matching the given patterns</td></tr>
1701 1720 <tr><td>-X</td>
1702 1721 <td>--exclude PATTERN [+]</td>
1703 1722 <td>exclude names matching the given patterns</td></tr>
1704 1723 <tr><td>-S</td>
1705 1724 <td>--subrepos</td>
1706 1725 <td>recurse into subrepositories</td></tr>
1707 1726 <tr><td>-n</td>
1708 1727 <td>--dry-run</td>
1709 1728 <td>do not perform actions, just print output</td></tr>
1710 1729 </table>
1711 1730 <p>
1712 1731 global options ([+] can be repeated):
1713 1732 </p>
1714 1733 <table>
1715 1734 <tr><td>-R</td>
1716 1735 <td>--repository REPO</td>
1717 1736 <td>repository root directory or name of overlay bundle file</td></tr>
1718 1737 <tr><td></td>
1719 1738 <td>--cwd DIR</td>
1720 1739 <td>change working directory</td></tr>
1721 1740 <tr><td>-y</td>
1722 1741 <td>--noninteractive</td>
1723 1742 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
1724 1743 <tr><td>-q</td>
1725 1744 <td>--quiet</td>
1726 1745 <td>suppress output</td></tr>
1727 1746 <tr><td>-v</td>
1728 1747 <td>--verbose</td>
1729 1748 <td>enable additional output</td></tr>
1730 1749 <tr><td></td>
1731 1750 <td>--config CONFIG [+]</td>
1732 1751 <td>set/override config option (use 'section.name=value')</td></tr>
1733 1752 <tr><td></td>
1734 1753 <td>--debug</td>
1735 1754 <td>enable debugging output</td></tr>
1736 1755 <tr><td></td>
1737 1756 <td>--debugger</td>
1738 1757 <td>start debugger</td></tr>
1739 1758 <tr><td></td>
1740 1759 <td>--encoding ENCODE</td>
1741 1760 <td>set the charset encoding (default: ascii)</td></tr>
1742 1761 <tr><td></td>
1743 1762 <td>--encodingmode MODE</td>
1744 1763 <td>set the charset encoding mode (default: strict)</td></tr>
1745 1764 <tr><td></td>
1746 1765 <td>--traceback</td>
1747 1766 <td>always print a traceback on exception</td></tr>
1748 1767 <tr><td></td>
1749 1768 <td>--time</td>
1750 1769 <td>time how long the command takes</td></tr>
1751 1770 <tr><td></td>
1752 1771 <td>--profile</td>
1753 1772 <td>print command execution profile</td></tr>
1754 1773 <tr><td></td>
1755 1774 <td>--version</td>
1756 1775 <td>output version information and exit</td></tr>
1757 1776 <tr><td>-h</td>
1758 1777 <td>--help</td>
1759 1778 <td>display help and exit</td></tr>
1760 1779 <tr><td></td>
1761 1780 <td>--hidden</td>
1762 1781 <td>consider hidden changesets</td></tr>
1763 1782 </table>
1764 1783
1765 1784 </div>
1766 1785 </div>
1767 1786 </div>
1768 1787
1769 1788 <script type="text/javascript">process_dates()</script>
1770 1789
1771 1790
1772 1791 </body>
1773 1792 </html>
1774 1793
1775 1794
1776 1795 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/remove"
1777 1796 200 Script output follows
1778 1797
1779 1798 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1780 1799 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1781 1800 <head>
1782 1801 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1783 1802 <meta name="robots" content="index, nofollow" />
1784 1803 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1785 1804 <script type="text/javascript" src="/static/mercurial.js"></script>
1786 1805
1787 1806 <title>Help: remove</title>
1788 1807 </head>
1789 1808 <body>
1790 1809
1791 1810 <div class="container">
1792 1811 <div class="menu">
1793 1812 <div class="logo">
1794 1813 <a href="http://mercurial.selenic.com/">
1795 1814 <img src="/static/hglogo.png" alt="mercurial" /></a>
1796 1815 </div>
1797 1816 <ul>
1798 1817 <li><a href="/shortlog">log</a></li>
1799 1818 <li><a href="/graph">graph</a></li>
1800 1819 <li><a href="/tags">tags</a></li>
1801 1820 <li><a href="/bookmarks">bookmarks</a></li>
1802 1821 <li><a href="/branches">branches</a></li>
1803 1822 </ul>
1804 1823 <ul>
1805 1824 <li class="active"><a href="/help">help</a></li>
1806 1825 </ul>
1807 1826 </div>
1808 1827
1809 1828 <div class="main">
1810 1829 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1811 1830 <h3>Help: remove</h3>
1812 1831
1813 1832 <form class="search" action="/log">
1814 1833
1815 1834 <p><input name="rev" id="search1" type="text" size="30" /></p>
1816 1835 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1817 1836 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1818 1837 </form>
1819 1838 <div id="doc">
1820 1839 <p>
1821 1840 hg remove [OPTION]... FILE...
1822 1841 </p>
1823 1842 <p>
1824 1843 aliases: rm
1825 1844 </p>
1826 1845 <p>
1827 1846 remove the specified files on the next commit
1828 1847 </p>
1829 1848 <p>
1830 1849 Schedule the indicated files for removal from the current branch.
1831 1850 </p>
1832 1851 <p>
1833 1852 This command schedules the files to be removed at the next commit.
1834 1853 To undo a remove before that, see &quot;hg revert&quot;. To undo added
1835 1854 files, see &quot;hg forget&quot;.
1836 1855 </p>
1837 1856 <p>
1838 1857 -A/--after can be used to remove only files that have already
1839 1858 been deleted, -f/--force can be used to force deletion, and -Af
1840 1859 can be used to remove files from the next revision without
1841 1860 deleting them from the working directory.
1842 1861 </p>
1843 1862 <p>
1844 1863 The following table details the behavior of remove for different
1845 1864 file states (columns) and option combinations (rows). The file
1846 1865 states are Added [A], Clean [C], Modified [M] and Missing [!]
1847 1866 (as reported by &quot;hg status&quot;). The actions are Warn, Remove
1848 1867 (from branch) and Delete (from disk):
1849 1868 </p>
1850 1869 <table>
1851 1870 <tr><td>opt/state</td>
1852 1871 <td>A</td>
1853 1872 <td>C</td>
1854 1873 <td>M</td>
1855 1874 <td>!</td></tr>
1856 1875 <tr><td>none</td>
1857 1876 <td>W</td>
1858 1877 <td>RD</td>
1859 1878 <td>W</td>
1860 1879 <td>R</td></tr>
1861 1880 <tr><td>-f</td>
1862 1881 <td>R</td>
1863 1882 <td>RD</td>
1864 1883 <td>RD</td>
1865 1884 <td>R</td></tr>
1866 1885 <tr><td>-A</td>
1867 1886 <td>W</td>
1868 1887 <td>W</td>
1869 1888 <td>W</td>
1870 1889 <td>R</td></tr>
1871 1890 <tr><td>-Af</td>
1872 1891 <td>R</td>
1873 1892 <td>R</td>
1874 1893 <td>R</td>
1875 1894 <td>R</td></tr>
1876 1895 </table>
1877 1896 <p>
1878 1897 Note that remove never deletes files in Added [A] state from the
1879 1898 working directory, not even if option --force is specified.
1880 1899 </p>
1881 1900 <p>
1882 1901 Returns 0 on success, 1 if any warnings encountered.
1883 1902 </p>
1884 1903 <p>
1885 1904 options ([+] can be repeated):
1886 1905 </p>
1887 1906 <table>
1888 1907 <tr><td>-A</td>
1889 1908 <td>--after</td>
1890 1909 <td>record delete for missing files</td></tr>
1891 1910 <tr><td>-f</td>
1892 1911 <td>--force</td>
1893 1912 <td>remove (and delete) file even if added or modified</td></tr>
1894 1913 <tr><td>-I</td>
1895 1914 <td>--include PATTERN [+]</td>
1896 1915 <td>include names matching the given patterns</td></tr>
1897 1916 <tr><td>-X</td>
1898 1917 <td>--exclude PATTERN [+]</td>
1899 1918 <td>exclude names matching the given patterns</td></tr>
1900 1919 </table>
1901 1920 <p>
1902 1921 global options ([+] can be repeated):
1903 1922 </p>
1904 1923 <table>
1905 1924 <tr><td>-R</td>
1906 1925 <td>--repository REPO</td>
1907 1926 <td>repository root directory or name of overlay bundle file</td></tr>
1908 1927 <tr><td></td>
1909 1928 <td>--cwd DIR</td>
1910 1929 <td>change working directory</td></tr>
1911 1930 <tr><td>-y</td>
1912 1931 <td>--noninteractive</td>
1913 1932 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
1914 1933 <tr><td>-q</td>
1915 1934 <td>--quiet</td>
1916 1935 <td>suppress output</td></tr>
1917 1936 <tr><td>-v</td>
1918 1937 <td>--verbose</td>
1919 1938 <td>enable additional output</td></tr>
1920 1939 <tr><td></td>
1921 1940 <td>--config CONFIG [+]</td>
1922 1941 <td>set/override config option (use 'section.name=value')</td></tr>
1923 1942 <tr><td></td>
1924 1943 <td>--debug</td>
1925 1944 <td>enable debugging output</td></tr>
1926 1945 <tr><td></td>
1927 1946 <td>--debugger</td>
1928 1947 <td>start debugger</td></tr>
1929 1948 <tr><td></td>
1930 1949 <td>--encoding ENCODE</td>
1931 1950 <td>set the charset encoding (default: ascii)</td></tr>
1932 1951 <tr><td></td>
1933 1952 <td>--encodingmode MODE</td>
1934 1953 <td>set the charset encoding mode (default: strict)</td></tr>
1935 1954 <tr><td></td>
1936 1955 <td>--traceback</td>
1937 1956 <td>always print a traceback on exception</td></tr>
1938 1957 <tr><td></td>
1939 1958 <td>--time</td>
1940 1959 <td>time how long the command takes</td></tr>
1941 1960 <tr><td></td>
1942 1961 <td>--profile</td>
1943 1962 <td>print command execution profile</td></tr>
1944 1963 <tr><td></td>
1945 1964 <td>--version</td>
1946 1965 <td>output version information and exit</td></tr>
1947 1966 <tr><td>-h</td>
1948 1967 <td>--help</td>
1949 1968 <td>display help and exit</td></tr>
1950 1969 <tr><td></td>
1951 1970 <td>--hidden</td>
1952 1971 <td>consider hidden changesets</td></tr>
1953 1972 </table>
1954 1973
1955 1974 </div>
1956 1975 </div>
1957 1976 </div>
1958 1977
1959 1978 <script type="text/javascript">process_dates()</script>
1960 1979
1961 1980
1962 1981 </body>
1963 1982 </html>
1964 1983
1965 1984
1966 1985 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/revisions"
1967 1986 200 Script output follows
1968 1987
1969 1988 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1970 1989 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1971 1990 <head>
1972 1991 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1973 1992 <meta name="robots" content="index, nofollow" />
1974 1993 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1975 1994 <script type="text/javascript" src="/static/mercurial.js"></script>
1976 1995
1977 1996 <title>Help: revisions</title>
1978 1997 </head>
1979 1998 <body>
1980 1999
1981 2000 <div class="container">
1982 2001 <div class="menu">
1983 2002 <div class="logo">
1984 2003 <a href="http://mercurial.selenic.com/">
1985 2004 <img src="/static/hglogo.png" alt="mercurial" /></a>
1986 2005 </div>
1987 2006 <ul>
1988 2007 <li><a href="/shortlog">log</a></li>
1989 2008 <li><a href="/graph">graph</a></li>
1990 2009 <li><a href="/tags">tags</a></li>
1991 2010 <li><a href="/bookmarks">bookmarks</a></li>
1992 2011 <li><a href="/branches">branches</a></li>
1993 2012 </ul>
1994 2013 <ul>
1995 2014 <li class="active"><a href="/help">help</a></li>
1996 2015 </ul>
1997 2016 </div>
1998 2017
1999 2018 <div class="main">
2000 2019 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2001 2020 <h3>Help: revisions</h3>
2002 2021
2003 2022 <form class="search" action="/log">
2004 2023
2005 2024 <p><input name="rev" id="search1" type="text" size="30" /></p>
2006 2025 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2007 2026 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2008 2027 </form>
2009 2028 <div id="doc">
2010 2029 <h1>Specifying Single Revisions</h1>
2011 2030 <p>
2012 2031 Mercurial supports several ways to specify individual revisions.
2013 2032 </p>
2014 2033 <p>
2015 2034 A plain integer is treated as a revision number. Negative integers are
2016 2035 treated as sequential offsets from the tip, with -1 denoting the tip,
2017 2036 -2 denoting the revision prior to the tip, and so forth.
2018 2037 </p>
2019 2038 <p>
2020 2039 A 40-digit hexadecimal string is treated as a unique revision
2021 2040 identifier.
2022 2041 </p>
2023 2042 <p>
2024 2043 A hexadecimal string less than 40 characters long is treated as a
2025 2044 unique revision identifier and is referred to as a short-form
2026 2045 identifier. A short-form identifier is only valid if it is the prefix
2027 2046 of exactly one full-length identifier.
2028 2047 </p>
2029 2048 <p>
2030 2049 Any other string is treated as a bookmark, tag, or branch name. A
2031 2050 bookmark is a movable pointer to a revision. A tag is a permanent name
2032 2051 associated with a revision. A branch name denotes the tipmost open branch head
2033 2052 of that branch - or if they are all closed, the tipmost closed head of the
2034 2053 branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
2035 2054 </p>
2036 2055 <p>
2037 2056 The reserved name &quot;tip&quot; always identifies the most recent revision.
2038 2057 </p>
2039 2058 <p>
2040 2059 The reserved name &quot;null&quot; indicates the null revision. This is the
2041 2060 revision of an empty repository, and the parent of revision 0.
2042 2061 </p>
2043 2062 <p>
2044 2063 The reserved name &quot;.&quot; indicates the working directory parent. If no
2045 2064 working directory is checked out, it is equivalent to null. If an
2046 2065 uncommitted merge is in progress, &quot;.&quot; is the revision of the first
2047 2066 parent.
2048 2067 </p>
2049 2068
2050 2069 </div>
2051 2070 </div>
2052 2071 </div>
2053 2072
2054 2073 <script type="text/javascript">process_dates()</script>
2055 2074
2056 2075
2057 2076 </body>
2058 2077 </html>
2059 2078
2060 2079
2061 2080 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
2062 2081
2063 2082 #endif
General Comments 0
You need to be logged in to leave comments. Login now