##// END OF EJS Templates
merge: add --tool argument to merge and resolve...
Steve Borho -
r12750:05bd2658 default
parent child Browse files
Show More
@@ -1,4460 +1,4482 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, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, sys, difflib, time, tempfile
12 12 import hg, util, revlog, extensions, copies, error
13 13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 15 import merge as mergemod
16 16 import minirst, revset
17 17 import dagparser
18 18
19 19 # Commands start here, listed alphabetically
20 20
21 21 def add(ui, repo, *pats, **opts):
22 22 """add the specified files on the next commit
23 23
24 24 Schedule files to be version controlled and added to the
25 25 repository.
26 26
27 27 The files will be added to the repository at the next commit. To
28 28 undo an add before that, see :hg:`forget`.
29 29
30 30 If no names are given, add all files to the repository.
31 31
32 32 .. container:: verbose
33 33
34 34 An example showing how new (unknown) files are added
35 35 automatically by :hg:`add`::
36 36
37 37 $ ls
38 38 foo.c
39 39 $ hg status
40 40 ? foo.c
41 41 $ hg add
42 42 adding foo.c
43 43 $ hg status
44 44 A foo.c
45 45
46 46 Returns 0 if all files are successfully added.
47 47 """
48 48
49 49 m = cmdutil.match(repo, pats, opts)
50 50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 51 opts.get('subrepos'), prefix="")
52 52 return rejected and 1 or 0
53 53
54 54 def addremove(ui, repo, *pats, **opts):
55 55 """add all new files, delete all missing files
56 56
57 57 Add all new files and remove all missing files from the
58 58 repository.
59 59
60 60 New files are ignored if they match any of the patterns in
61 61 .hgignore. As with add, these changes take effect at the next
62 62 commit.
63 63
64 64 Use the -s/--similarity option to detect renamed files. With a
65 65 parameter greater than 0, this compares every removed file with
66 66 every added file and records those similar enough as renames. This
67 67 option takes a percentage between 0 (disabled) and 100 (files must
68 68 be identical) as its parameter. Detecting renamed files this way
69 69 can be expensive. After using this option, :hg:`status -C` can be
70 70 used to check which files were identified as moved or renamed.
71 71
72 72 Returns 0 if all files are successfully added.
73 73 """
74 74 try:
75 75 sim = float(opts.get('similarity') or 100)
76 76 except ValueError:
77 77 raise util.Abort(_('similarity must be a number'))
78 78 if sim < 0 or sim > 100:
79 79 raise util.Abort(_('similarity must be between 0 and 100'))
80 80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81 81
82 82 def annotate(ui, repo, *pats, **opts):
83 83 """show changeset information by line for each file
84 84
85 85 List changes in files, showing the revision id responsible for
86 86 each line
87 87
88 88 This command is useful for discovering when a change was made and
89 89 by whom.
90 90
91 91 Without the -a/--text option, annotate will avoid processing files
92 92 it detects as binary. With -a, annotate will annotate the file
93 93 anyway, although the results will probably be neither useful
94 94 nor desirable.
95 95
96 96 Returns 0 on success.
97 97 """
98 98 if opts.get('follow'):
99 99 # --follow is deprecated and now just an alias for -f/--file
100 100 # to mimic the behavior of Mercurial before version 1.5
101 101 opts['file'] = 1
102 102
103 103 datefunc = ui.quiet and util.shortdate or util.datestr
104 104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105 105
106 106 if not pats:
107 107 raise util.Abort(_('at least one filename or pattern is required'))
108 108
109 109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 110 ('number', lambda x: str(x[0].rev())),
111 111 ('changeset', lambda x: short(x[0].node())),
112 112 ('date', getdate),
113 113 ('file', lambda x: x[0].path()),
114 114 ]
115 115
116 116 if (not opts.get('user') and not opts.get('changeset')
117 117 and not opts.get('date') and not opts.get('file')):
118 118 opts['number'] = 1
119 119
120 120 linenumber = opts.get('line_number') is not None
121 121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123 123
124 124 funcmap = [func for op, func in opmap if opts.get(op)]
125 125 if linenumber:
126 126 lastfunc = funcmap[-1]
127 127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128 128
129 129 ctx = repo[opts.get('rev')]
130 130 m = cmdutil.match(repo, pats, opts)
131 131 follow = not opts.get('no_follow')
132 132 for abs in ctx.walk(m):
133 133 fctx = ctx[abs]
134 134 if not opts.get('text') and util.binary(fctx.data()):
135 135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 136 continue
137 137
138 138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 139 pieces = []
140 140
141 141 for f in funcmap:
142 142 l = [f(n) for n, dummy in lines]
143 143 if l:
144 144 sized = [(x, encoding.colwidth(x)) for x in l]
145 145 ml = max([w for x, w in sized])
146 146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147 147
148 148 if pieces:
149 149 for p, l in zip(zip(*pieces), lines):
150 150 ui.write("%s: %s" % (" ".join(p), l[1]))
151 151
152 152 def archive(ui, repo, dest, **opts):
153 153 '''create an unversioned archive of a repository revision
154 154
155 155 By default, the revision used is the parent of the working
156 156 directory; use -r/--rev to specify a different revision.
157 157
158 158 The archive type is automatically detected based on file
159 159 extension (or override using -t/--type).
160 160
161 161 Valid types are:
162 162
163 163 :``files``: a directory full of files (default)
164 164 :``tar``: tar archive, uncompressed
165 165 :``tbz2``: tar archive, compressed using bzip2
166 166 :``tgz``: tar archive, compressed using gzip
167 167 :``uzip``: zip archive, uncompressed
168 168 :``zip``: zip archive, compressed using deflate
169 169
170 170 The exact name of the destination archive or directory is given
171 171 using a format string; see :hg:`help export` for details.
172 172
173 173 Each member added to an archive file has a directory prefix
174 174 prepended. Use -p/--prefix to specify a format string for the
175 175 prefix. The default is the basename of the archive, with suffixes
176 176 removed.
177 177
178 178 Returns 0 on success.
179 179 '''
180 180
181 181 ctx = repo[opts.get('rev')]
182 182 if not ctx:
183 183 raise util.Abort(_('no working directory: please specify a revision'))
184 184 node = ctx.node()
185 185 dest = cmdutil.make_filename(repo, dest, node)
186 186 if os.path.realpath(dest) == repo.root:
187 187 raise util.Abort(_('repository root cannot be destination'))
188 188
189 189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 190 prefix = opts.get('prefix')
191 191
192 192 if dest == '-':
193 193 if kind == 'files':
194 194 raise util.Abort(_('cannot archive plain files to stdout'))
195 195 dest = sys.stdout
196 196 if not prefix:
197 197 prefix = os.path.basename(repo.root) + '-%h'
198 198
199 199 prefix = cmdutil.make_filename(repo, prefix, node)
200 200 matchfn = cmdutil.match(repo, [], opts)
201 201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 202 matchfn, prefix, subrepos=opts.get('subrepos'))
203 203
204 204 def backout(ui, repo, node=None, rev=None, **opts):
205 205 '''reverse effect of earlier changeset
206 206
207 207 The backout command merges the reverse effect of the reverted
208 208 changeset into the working directory.
209 209
210 210 With the --merge option, it first commits the reverted changes
211 211 as a new changeset. This new changeset is a child of the reverted
212 212 changeset.
213 213 The --merge option remembers the parent of the working directory
214 214 before starting the backout, then merges the new head with that
215 215 changeset afterwards.
216 216 This will result in an explicit merge in the history.
217 217
218 218 If you backout a changeset other than the original parent of the
219 219 working directory, the result of this merge is not committed,
220 220 as with a normal merge. Otherwise, no merge is needed and the
221 221 commit is automatic.
222 222
223 223 Note that the default behavior (without --merge) has changed in
224 224 version 1.7. To restore the previous default behavior, use
225 225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 226 the ongoing merge.
227 227
228 228 See :hg:`help dates` for a list of formats valid for -d/--date.
229 229
230 230 Returns 0 on success.
231 231 '''
232 232 if rev and node:
233 233 raise util.Abort(_("please specify just one revision"))
234 234
235 235 if not rev:
236 236 rev = node
237 237
238 238 if not rev:
239 239 raise util.Abort(_("please specify a revision to backout"))
240 240
241 241 date = opts.get('date')
242 242 if date:
243 243 opts['date'] = util.parsedate(date)
244 244
245 245 cmdutil.bail_if_changed(repo)
246 246 node = repo.lookup(rev)
247 247
248 248 op1, op2 = repo.dirstate.parents()
249 249 a = repo.changelog.ancestor(op1, node)
250 250 if a != node:
251 251 raise util.Abort(_('cannot backout change on a different branch'))
252 252
253 253 p1, p2 = repo.changelog.parents(node)
254 254 if p1 == nullid:
255 255 raise util.Abort(_('cannot backout a change with no parents'))
256 256 if p2 != nullid:
257 257 if not opts.get('parent'):
258 258 raise util.Abort(_('cannot backout a merge changeset without '
259 259 '--parent'))
260 260 p = repo.lookup(opts['parent'])
261 261 if p not in (p1, p2):
262 262 raise util.Abort(_('%s is not a parent of %s') %
263 263 (short(p), short(node)))
264 264 parent = p
265 265 else:
266 266 if opts.get('parent'):
267 267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 268 parent = p1
269 269
270 270 # the backout should appear on the same branch
271 271 branch = repo.dirstate.branch()
272 272 hg.clean(repo, node, show_stats=False)
273 273 repo.dirstate.setbranch(branch)
274 274 revert_opts = opts.copy()
275 275 revert_opts['date'] = None
276 276 revert_opts['all'] = True
277 277 revert_opts['rev'] = hex(parent)
278 278 revert_opts['no_backup'] = None
279 279 revert(ui, repo, **revert_opts)
280 280 if not opts.get('merge') and op1 != node:
281 281 return hg.update(repo, op1)
282 282
283 283 commit_opts = opts.copy()
284 284 commit_opts['addremove'] = False
285 285 if not commit_opts['message'] and not commit_opts['logfile']:
286 286 # we don't translate commit messages
287 287 commit_opts['message'] = "Backed out changeset %s" % short(node)
288 288 commit_opts['force_editor'] = True
289 289 commit(ui, repo, **commit_opts)
290 290 def nice(node):
291 291 return '%d:%s' % (repo.changelog.rev(node), short(node))
292 292 ui.status(_('changeset %s backs out changeset %s\n') %
293 293 (nice(repo.changelog.tip()), nice(node)))
294 294 if opts.get('merge') and op1 != node:
295 295 hg.clean(repo, op1, show_stats=False)
296 296 ui.status(_('merging with changeset %s\n')
297 297 % nice(repo.changelog.tip()))
298 298 return hg.merge(repo, hex(repo.changelog.tip()))
299 299 return 0
300 300
301 301 def bisect(ui, repo, rev=None, extra=None, command=None,
302 302 reset=None, good=None, bad=None, skip=None, noupdate=None):
303 303 """subdivision search of changesets
304 304
305 305 This command helps to find changesets which introduce problems. To
306 306 use, mark the earliest changeset you know exhibits the problem as
307 307 bad, then mark the latest changeset which is free from the problem
308 308 as good. Bisect will update your working directory to a revision
309 309 for testing (unless the -U/--noupdate option is specified). Once
310 310 you have performed tests, mark the working directory as good or
311 311 bad, and bisect will either update to another candidate changeset
312 312 or announce that it has found the bad revision.
313 313
314 314 As a shortcut, you can also use the revision argument to mark a
315 315 revision as good or bad without checking it out first.
316 316
317 317 If you supply a command, it will be used for automatic bisection.
318 318 Its exit status will be used to mark revisions as good or bad:
319 319 status 0 means good, 125 means to skip the revision, 127
320 320 (command not found) will abort the bisection, and any other
321 321 non-zero exit status means the revision is bad.
322 322
323 323 Returns 0 on success.
324 324 """
325 325 def print_result(nodes, good):
326 326 displayer = cmdutil.show_changeset(ui, repo, {})
327 327 if len(nodes) == 1:
328 328 # narrowed it down to a single revision
329 329 if good:
330 330 ui.write(_("The first good revision is:\n"))
331 331 else:
332 332 ui.write(_("The first bad revision is:\n"))
333 333 displayer.show(repo[nodes[0]])
334 334 parents = repo[nodes[0]].parents()
335 335 if len(parents) > 1:
336 336 side = good and state['bad'] or state['good']
337 337 num = len(set(i.node() for i in parents) & set(side))
338 338 if num == 1:
339 339 common = parents[0].ancestor(parents[1])
340 340 ui.write(_('Not all ancestors of this changeset have been'
341 341 ' checked.\nTo check the other ancestors, start'
342 342 ' from the common ancestor, %s.\n' % common))
343 343 else:
344 344 # multiple possible revisions
345 345 if good:
346 346 ui.write(_("Due to skipped revisions, the first "
347 347 "good revision could be any of:\n"))
348 348 else:
349 349 ui.write(_("Due to skipped revisions, the first "
350 350 "bad revision could be any of:\n"))
351 351 for n in nodes:
352 352 displayer.show(repo[n])
353 353 displayer.close()
354 354
355 355 def check_state(state, interactive=True):
356 356 if not state['good'] or not state['bad']:
357 357 if (good or bad or skip or reset) and interactive:
358 358 return
359 359 if not state['good']:
360 360 raise util.Abort(_('cannot bisect (no known good revisions)'))
361 361 else:
362 362 raise util.Abort(_('cannot bisect (no known bad revisions)'))
363 363 return True
364 364
365 365 # backward compatibility
366 366 if rev in "good bad reset init".split():
367 367 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
368 368 cmd, rev, extra = rev, extra, None
369 369 if cmd == "good":
370 370 good = True
371 371 elif cmd == "bad":
372 372 bad = True
373 373 else:
374 374 reset = True
375 375 elif extra or good + bad + skip + reset + bool(command) > 1:
376 376 raise util.Abort(_('incompatible arguments'))
377 377
378 378 if reset:
379 379 p = repo.join("bisect.state")
380 380 if os.path.exists(p):
381 381 os.unlink(p)
382 382 return
383 383
384 384 state = hbisect.load_state(repo)
385 385
386 386 if command:
387 387 changesets = 1
388 388 try:
389 389 while changesets:
390 390 # update state
391 391 status = util.system(command)
392 392 if status == 125:
393 393 transition = "skip"
394 394 elif status == 0:
395 395 transition = "good"
396 396 # status < 0 means process was killed
397 397 elif status == 127:
398 398 raise util.Abort(_("failed to execute %s") % command)
399 399 elif status < 0:
400 400 raise util.Abort(_("%s killed") % command)
401 401 else:
402 402 transition = "bad"
403 403 ctx = repo[rev or '.']
404 404 state[transition].append(ctx.node())
405 405 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
406 406 check_state(state, interactive=False)
407 407 # bisect
408 408 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
409 409 # update to next check
410 410 cmdutil.bail_if_changed(repo)
411 411 hg.clean(repo, nodes[0], show_stats=False)
412 412 finally:
413 413 hbisect.save_state(repo, state)
414 414 print_result(nodes, good)
415 415 return
416 416
417 417 # update state
418 418
419 419 if rev:
420 420 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
421 421 else:
422 422 nodes = [repo.lookup('.')]
423 423
424 424 if good or bad or skip:
425 425 if good:
426 426 state['good'] += nodes
427 427 elif bad:
428 428 state['bad'] += nodes
429 429 elif skip:
430 430 state['skip'] += nodes
431 431 hbisect.save_state(repo, state)
432 432
433 433 if not check_state(state):
434 434 return
435 435
436 436 # actually bisect
437 437 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
438 438 if changesets == 0:
439 439 print_result(nodes, good)
440 440 else:
441 441 assert len(nodes) == 1 # only a single node can be tested next
442 442 node = nodes[0]
443 443 # compute the approximate number of remaining tests
444 444 tests, size = 0, 2
445 445 while size <= changesets:
446 446 tests, size = tests + 1, size * 2
447 447 rev = repo.changelog.rev(node)
448 448 ui.write(_("Testing changeset %d:%s "
449 449 "(%d changesets remaining, ~%d tests)\n")
450 450 % (rev, short(node), changesets, tests))
451 451 if not noupdate:
452 452 cmdutil.bail_if_changed(repo)
453 453 return hg.clean(repo, node)
454 454
455 455 def branch(ui, repo, label=None, **opts):
456 456 """set or show the current branch name
457 457
458 458 With no argument, show the current branch name. With one argument,
459 459 set the working directory branch name (the branch will not exist
460 460 in the repository until the next commit). Standard practice
461 461 recommends that primary development take place on the 'default'
462 462 branch.
463 463
464 464 Unless -f/--force is specified, branch will not let you set a
465 465 branch name that already exists, even if it's inactive.
466 466
467 467 Use -C/--clean to reset the working directory branch to that of
468 468 the parent of the working directory, negating a previous branch
469 469 change.
470 470
471 471 Use the command :hg:`update` to switch to an existing branch. Use
472 472 :hg:`commit --close-branch` to mark this branch as closed.
473 473
474 474 Returns 0 on success.
475 475 """
476 476
477 477 if opts.get('clean'):
478 478 label = repo[None].parents()[0].branch()
479 479 repo.dirstate.setbranch(label)
480 480 ui.status(_('reset working directory to branch %s\n') % label)
481 481 elif label:
482 482 utflabel = encoding.fromlocal(label)
483 483 if not opts.get('force') and utflabel in repo.branchtags():
484 484 if label not in [p.branch() for p in repo.parents()]:
485 485 raise util.Abort(_('a branch of the same name already exists'
486 486 " (use 'hg update' to switch to it)"))
487 487 repo.dirstate.setbranch(utflabel)
488 488 ui.status(_('marked working directory as branch %s\n') % label)
489 489 else:
490 490 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
491 491
492 492 def branches(ui, repo, active=False, closed=False):
493 493 """list repository named branches
494 494
495 495 List the repository's named branches, indicating which ones are
496 496 inactive. If -c/--closed is specified, also list branches which have
497 497 been marked closed (see :hg:`commit --close-branch`).
498 498
499 499 If -a/--active is specified, only show active branches. A branch
500 500 is considered active if it contains repository heads.
501 501
502 502 Use the command :hg:`update` to switch to an existing branch.
503 503
504 504 Returns 0.
505 505 """
506 506
507 507 hexfunc = ui.debugflag and hex or short
508 508 activebranches = [repo[n].branch() for n in repo.heads()]
509 509 def testactive(tag, node):
510 510 realhead = tag in activebranches
511 511 open = node in repo.branchheads(tag, closed=False)
512 512 return realhead and open
513 513 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
514 514 for tag, node in repo.branchtags().items()],
515 515 reverse=True)
516 516
517 517 for isactive, node, tag in branches:
518 518 if (not active) or isactive:
519 519 encodedtag = encoding.tolocal(tag)
520 520 if ui.quiet:
521 521 ui.write("%s\n" % encodedtag)
522 522 else:
523 523 hn = repo.lookup(node)
524 524 if isactive:
525 525 label = 'branches.active'
526 526 notice = ''
527 527 elif hn not in repo.branchheads(tag, closed=False):
528 528 if not closed:
529 529 continue
530 530 label = 'branches.closed'
531 531 notice = _(' (closed)')
532 532 else:
533 533 label = 'branches.inactive'
534 534 notice = _(' (inactive)')
535 535 if tag == repo.dirstate.branch():
536 536 label = 'branches.current'
537 537 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
538 538 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
539 539 encodedtag = ui.label(encodedtag, label)
540 540 ui.write("%s %s%s\n" % (encodedtag, rev, notice))
541 541
542 542 def bundle(ui, repo, fname, dest=None, **opts):
543 543 """create a changegroup file
544 544
545 545 Generate a compressed changegroup file collecting changesets not
546 546 known to be in another repository.
547 547
548 548 If you omit the destination repository, then hg assumes the
549 549 destination will have all the nodes you specify with --base
550 550 parameters. To create a bundle containing all changesets, use
551 551 -a/--all (or --base null).
552 552
553 553 You can change compression method with the -t/--type option.
554 554 The available compression methods are: none, bzip2, and
555 555 gzip (by default, bundles are compressed using bzip2).
556 556
557 557 The bundle file can then be transferred using conventional means
558 558 and applied to another repository with the unbundle or pull
559 559 command. This is useful when direct push and pull are not
560 560 available or when exporting an entire repository is undesirable.
561 561
562 562 Applying bundles preserves all changeset contents including
563 563 permissions, copy/rename information, and revision history.
564 564
565 565 Returns 0 on success, 1 if no changes found.
566 566 """
567 567 revs = opts.get('rev') or None
568 568 if opts.get('all'):
569 569 base = ['null']
570 570 else:
571 571 base = opts.get('base')
572 572 if base:
573 573 if dest:
574 574 raise util.Abort(_("--base is incompatible with specifying "
575 575 "a destination"))
576 576 base = [repo.lookup(rev) for rev in base]
577 577 # create the right base
578 578 # XXX: nodesbetween / changegroup* should be "fixed" instead
579 579 o = []
580 580 has = set((nullid,))
581 581 for n in base:
582 582 has.update(repo.changelog.reachable(n))
583 583 if revs:
584 584 revs = [repo.lookup(rev) for rev in revs]
585 585 visit = revs[:]
586 586 has.difference_update(visit)
587 587 else:
588 588 visit = repo.changelog.heads()
589 589 seen = {}
590 590 while visit:
591 591 n = visit.pop(0)
592 592 parents = [p for p in repo.changelog.parents(n) if p not in has]
593 593 if len(parents) == 0:
594 594 if n not in has:
595 595 o.append(n)
596 596 else:
597 597 for p in parents:
598 598 if p not in seen:
599 599 seen[p] = 1
600 600 visit.append(p)
601 601 else:
602 602 dest = ui.expandpath(dest or 'default-push', dest or 'default')
603 603 dest, branches = hg.parseurl(dest, opts.get('branch'))
604 604 other = hg.repository(hg.remoteui(repo, opts), dest)
605 605 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
606 606 if revs:
607 607 revs = [repo.lookup(rev) for rev in revs]
608 608 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
609 609
610 610 if not o:
611 611 ui.status(_("no changes found\n"))
612 612 return 1
613 613
614 614 if revs:
615 615 cg = repo.changegroupsubset(o, revs, 'bundle')
616 616 else:
617 617 cg = repo.changegroup(o, 'bundle')
618 618
619 619 bundletype = opts.get('type', 'bzip2').lower()
620 620 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
621 621 bundletype = btypes.get(bundletype)
622 622 if bundletype not in changegroup.bundletypes:
623 623 raise util.Abort(_('unknown bundle type specified with --type'))
624 624
625 625 changegroup.writebundle(cg, fname, bundletype)
626 626
627 627 def cat(ui, repo, file1, *pats, **opts):
628 628 """output the current or given revision of files
629 629
630 630 Print the specified files as they were at the given revision. If
631 631 no revision is given, the parent of the working directory is used,
632 632 or tip if no revision is checked out.
633 633
634 634 Output may be to a file, in which case the name of the file is
635 635 given using a format string. The formatting rules are the same as
636 636 for the export command, with the following additions:
637 637
638 638 :``%s``: basename of file being printed
639 639 :``%d``: dirname of file being printed, or '.' if in repository root
640 640 :``%p``: root-relative path name of file being printed
641 641
642 642 Returns 0 on success.
643 643 """
644 644 ctx = cmdutil.revsingle(repo, opts.get('rev'))
645 645 err = 1
646 646 m = cmdutil.match(repo, (file1,) + pats, opts)
647 647 for abs in ctx.walk(m):
648 648 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
649 649 data = ctx[abs].data()
650 650 if opts.get('decode'):
651 651 data = repo.wwritedata(abs, data)
652 652 fp.write(data)
653 653 err = 0
654 654 return err
655 655
656 656 def clone(ui, source, dest=None, **opts):
657 657 """make a copy of an existing repository
658 658
659 659 Create a copy of an existing repository in a new directory.
660 660
661 661 If no destination directory name is specified, it defaults to the
662 662 basename of the source.
663 663
664 664 The location of the source is added to the new repository's
665 665 .hg/hgrc file, as the default to be used for future pulls.
666 666
667 667 See :hg:`help urls` for valid source format details.
668 668
669 669 It is possible to specify an ``ssh://`` URL as the destination, but no
670 670 .hg/hgrc and working directory will be created on the remote side.
671 671 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
672 672
673 673 A set of changesets (tags, or branch names) to pull may be specified
674 674 by listing each changeset (tag, or branch name) with -r/--rev.
675 675 If -r/--rev is used, the cloned repository will contain only a subset
676 676 of the changesets of the source repository. Only the set of changesets
677 677 defined by all -r/--rev options (including all their ancestors)
678 678 will be pulled into the destination repository.
679 679 No subsequent changesets (including subsequent tags) will be present
680 680 in the destination.
681 681
682 682 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
683 683 local source repositories.
684 684
685 685 For efficiency, hardlinks are used for cloning whenever the source
686 686 and destination are on the same filesystem (note this applies only
687 687 to the repository data, not to the working directory). Some
688 688 filesystems, such as AFS, implement hardlinking incorrectly, but
689 689 do not report errors. In these cases, use the --pull option to
690 690 avoid hardlinking.
691 691
692 692 In some cases, you can clone repositories and the working directory
693 693 using full hardlinks with ::
694 694
695 695 $ cp -al REPO REPOCLONE
696 696
697 697 This is the fastest way to clone, but it is not always safe. The
698 698 operation is not atomic (making sure REPO is not modified during
699 699 the operation is up to you) and you have to make sure your editor
700 700 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
701 701 this is not compatible with certain extensions that place their
702 702 metadata under the .hg directory, such as mq.
703 703
704 704 Mercurial will update the working directory to the first applicable
705 705 revision from this list:
706 706
707 707 a) null if -U or the source repository has no changesets
708 708 b) if -u . and the source repository is local, the first parent of
709 709 the source repository's working directory
710 710 c) the changeset specified with -u (if a branch name, this means the
711 711 latest head of that branch)
712 712 d) the changeset specified with -r
713 713 e) the tipmost head specified with -b
714 714 f) the tipmost head specified with the url#branch source syntax
715 715 g) the tipmost head of the default branch
716 716 h) tip
717 717
718 718 Returns 0 on success.
719 719 """
720 720 if opts.get('noupdate') and opts.get('updaterev'):
721 721 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
722 722
723 723 r = hg.clone(hg.remoteui(ui, opts), source, dest,
724 724 pull=opts.get('pull'),
725 725 stream=opts.get('uncompressed'),
726 726 rev=opts.get('rev'),
727 727 update=opts.get('updaterev') or not opts.get('noupdate'),
728 728 branch=opts.get('branch'))
729 729
730 730 return r is None
731 731
732 732 def commit(ui, repo, *pats, **opts):
733 733 """commit the specified files or all outstanding changes
734 734
735 735 Commit changes to the given files into the repository. Unlike a
736 736 centralized RCS, this operation is a local operation. See
737 737 :hg:`push` for a way to actively distribute your changes.
738 738
739 739 If a list of files is omitted, all changes reported by :hg:`status`
740 740 will be committed.
741 741
742 742 If you are committing the result of a merge, do not provide any
743 743 filenames or -I/-X filters.
744 744
745 745 If no commit message is specified, Mercurial starts your
746 746 configured editor where you can enter a message. In case your
747 747 commit fails, you will find a backup of your message in
748 748 ``.hg/last-message.txt``.
749 749
750 750 See :hg:`help dates` for a list of formats valid for -d/--date.
751 751
752 752 Returns 0 on success, 1 if nothing changed.
753 753 """
754 754 extra = {}
755 755 if opts.get('close_branch'):
756 756 if repo['.'].node() not in repo.branchheads():
757 757 # The topo heads set is included in the branch heads set of the
758 758 # current branch, so it's sufficient to test branchheads
759 759 raise util.Abort(_('can only close branch heads'))
760 760 extra['close'] = 1
761 761 e = cmdutil.commiteditor
762 762 if opts.get('force_editor'):
763 763 e = cmdutil.commitforceeditor
764 764
765 765 def commitfunc(ui, repo, message, match, opts):
766 766 return repo.commit(message, opts.get('user'), opts.get('date'), match,
767 767 editor=e, extra=extra)
768 768
769 769 branch = repo[None].branch()
770 770 bheads = repo.branchheads(branch)
771 771
772 772 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
773 773 if not node:
774 774 ui.status(_("nothing changed\n"))
775 775 return 1
776 776
777 777 ctx = repo[node]
778 778 parents = ctx.parents()
779 779
780 780 if bheads and not [x for x in parents
781 781 if x.node() in bheads and x.branch() == branch]:
782 782 ui.status(_('created new head\n'))
783 783 # The message is not printed for initial roots. For the other
784 784 # changesets, it is printed in the following situations:
785 785 #
786 786 # Par column: for the 2 parents with ...
787 787 # N: null or no parent
788 788 # B: parent is on another named branch
789 789 # C: parent is a regular non head changeset
790 790 # H: parent was a branch head of the current branch
791 791 # Msg column: whether we print "created new head" message
792 792 # In the following, it is assumed that there already exists some
793 793 # initial branch heads of the current branch, otherwise nothing is
794 794 # printed anyway.
795 795 #
796 796 # Par Msg Comment
797 797 # NN y additional topo root
798 798 #
799 799 # BN y additional branch root
800 800 # CN y additional topo head
801 801 # HN n usual case
802 802 #
803 803 # BB y weird additional branch root
804 804 # CB y branch merge
805 805 # HB n merge with named branch
806 806 #
807 807 # CC y additional head from merge
808 808 # CH n merge with a head
809 809 #
810 810 # HH n head merge: head count decreases
811 811
812 812 if not opts.get('close_branch'):
813 813 for r in parents:
814 814 if r.extra().get('close') and r.branch() == branch:
815 815 ui.status(_('reopening closed branch head %d\n') % r)
816 816
817 817 if ui.debugflag:
818 818 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
819 819 elif ui.verbose:
820 820 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
821 821
822 822 def copy(ui, repo, *pats, **opts):
823 823 """mark files as copied for the next commit
824 824
825 825 Mark dest as having copies of source files. If dest is a
826 826 directory, copies are put in that directory. If dest is a file,
827 827 the source must be a single file.
828 828
829 829 By default, this command copies the contents of files as they
830 830 exist in the working directory. If invoked with -A/--after, the
831 831 operation is recorded, but no copying is performed.
832 832
833 833 This command takes effect with the next commit. To undo a copy
834 834 before that, see :hg:`revert`.
835 835
836 836 Returns 0 on success, 1 if errors are encountered.
837 837 """
838 838 wlock = repo.wlock(False)
839 839 try:
840 840 return cmdutil.copy(ui, repo, pats, opts)
841 841 finally:
842 842 wlock.release()
843 843
844 844 def debugancestor(ui, repo, *args):
845 845 """find the ancestor revision of two revisions in a given index"""
846 846 if len(args) == 3:
847 847 index, rev1, rev2 = args
848 848 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
849 849 lookup = r.lookup
850 850 elif len(args) == 2:
851 851 if not repo:
852 852 raise util.Abort(_("there is no Mercurial repository here "
853 853 "(.hg not found)"))
854 854 rev1, rev2 = args
855 855 r = repo.changelog
856 856 lookup = repo.lookup
857 857 else:
858 858 raise util.Abort(_('either two or three arguments required'))
859 859 a = r.ancestor(lookup(rev1), lookup(rev2))
860 860 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
861 861
862 862 def debugbuilddag(ui, repo, text,
863 863 mergeable_file=False,
864 864 appended_file=False,
865 865 overwritten_file=False,
866 866 new_file=False):
867 867 """builds a repo with a given dag from scratch in the current empty repo
868 868
869 869 Elements:
870 870
871 871 - "+n" is a linear run of n nodes based on the current default parent
872 872 - "." is a single node based on the current default parent
873 873 - "$" resets the default parent to null (implied at the start);
874 874 otherwise the default parent is always the last node created
875 875 - "<p" sets the default parent to the backref p
876 876 - "*p" is a fork at parent p, which is a backref
877 877 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
878 878 - "/p2" is a merge of the preceding node and p2
879 879 - ":tag" defines a local tag for the preceding node
880 880 - "@branch" sets the named branch for subsequent nodes
881 881 - "!command" runs the command using your shell
882 882 - "!!my command\\n" is like "!", but to the end of the line
883 883 - "#...\\n" is a comment up to the end of the line
884 884
885 885 Whitespace between the above elements is ignored.
886 886
887 887 A backref is either
888 888
889 889 - a number n, which references the node curr-n, where curr is the current
890 890 node, or
891 891 - the name of a local tag you placed earlier using ":tag", or
892 892 - empty to denote the default parent.
893 893
894 894 All string valued-elements are either strictly alphanumeric, or must
895 895 be enclosed in double quotes ("..."), with "\\" as escape character.
896 896
897 897 Note that the --overwritten-file and --appended-file options imply the
898 898 use of "HGMERGE=internal:local" during DAG buildup.
899 899 """
900 900
901 901 if not (mergeable_file or appended_file or overwritten_file or new_file):
902 902 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
903 903
904 904 if len(repo.changelog) > 0:
905 905 raise util.Abort(_('repository is not empty'))
906 906
907 907 if overwritten_file or appended_file:
908 908 # we don't want to fail in merges during buildup
909 909 os.environ['HGMERGE'] = 'internal:local'
910 910
911 911 def writefile(fname, text, fmode="wb"):
912 912 f = open(fname, fmode)
913 913 try:
914 914 f.write(text)
915 915 finally:
916 916 f.close()
917 917
918 918 if mergeable_file:
919 919 linesperrev = 2
920 920 # determine number of revs in DAG
921 921 n = 0
922 922 for type, data in dagparser.parsedag(text):
923 923 if type == 'n':
924 924 n += 1
925 925 # make a file with k lines per rev
926 926 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
927 927 + "\n")
928 928
929 929 at = -1
930 930 atbranch = 'default'
931 931 for type, data in dagparser.parsedag(text):
932 932 if type == 'n':
933 933 ui.status('node %s\n' % str(data))
934 934 id, ps = data
935 935 p1 = ps[0]
936 936 if p1 != at:
937 937 update(ui, repo, node=str(p1), clean=True)
938 938 at = p1
939 939 if repo.dirstate.branch() != atbranch:
940 940 branch(ui, repo, atbranch, force=True)
941 941 if len(ps) > 1:
942 942 p2 = ps[1]
943 943 merge(ui, repo, node=p2)
944 944
945 945 if mergeable_file:
946 946 f = open("mf", "rb+")
947 947 try:
948 948 lines = f.read().split("\n")
949 949 lines[id * linesperrev] += " r%i" % id
950 950 f.seek(0)
951 951 f.write("\n".join(lines))
952 952 finally:
953 953 f.close()
954 954
955 955 if appended_file:
956 956 writefile("af", "r%i\n" % id, "ab")
957 957
958 958 if overwritten_file:
959 959 writefile("of", "r%i\n" % id)
960 960
961 961 if new_file:
962 962 writefile("nf%i" % id, "r%i\n" % id)
963 963
964 964 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
965 965 at = id
966 966 elif type == 'l':
967 967 id, name = data
968 968 ui.status('tag %s\n' % name)
969 969 tag(ui, repo, name, local=True)
970 970 elif type == 'a':
971 971 ui.status('branch %s\n' % data)
972 972 atbranch = data
973 973 elif type in 'cC':
974 974 r = util.system(data, cwd=repo.root)
975 975 if r:
976 976 desc, r = util.explain_exit(r)
977 977 raise util.Abort(_('%s command %s') % (data, desc))
978 978
979 979 def debugcommands(ui, cmd='', *args):
980 980 """list all available commands and options"""
981 981 for cmd, vals in sorted(table.iteritems()):
982 982 cmd = cmd.split('|')[0].strip('^')
983 983 opts = ', '.join([i[1] for i in vals[1]])
984 984 ui.write('%s: %s\n' % (cmd, opts))
985 985
986 986 def debugcomplete(ui, cmd='', **opts):
987 987 """returns the completion list associated with the given command"""
988 988
989 989 if opts.get('options'):
990 990 options = []
991 991 otables = [globalopts]
992 992 if cmd:
993 993 aliases, entry = cmdutil.findcmd(cmd, table, False)
994 994 otables.append(entry[1])
995 995 for t in otables:
996 996 for o in t:
997 997 if "(DEPRECATED)" in o[3]:
998 998 continue
999 999 if o[0]:
1000 1000 options.append('-%s' % o[0])
1001 1001 options.append('--%s' % o[1])
1002 1002 ui.write("%s\n" % "\n".join(options))
1003 1003 return
1004 1004
1005 1005 cmdlist = cmdutil.findpossible(cmd, table)
1006 1006 if ui.verbose:
1007 1007 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1008 1008 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1009 1009
1010 1010 def debugfsinfo(ui, path = "."):
1011 1011 """show information detected about current filesystem"""
1012 1012 open('.debugfsinfo', 'w').write('')
1013 1013 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1014 1014 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1015 1015 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1016 1016 and 'yes' or 'no'))
1017 1017 os.unlink('.debugfsinfo')
1018 1018
1019 1019 def debugrebuildstate(ui, repo, rev="tip"):
1020 1020 """rebuild the dirstate as it would look like for the given revision"""
1021 1021 ctx = repo[rev]
1022 1022 wlock = repo.wlock()
1023 1023 try:
1024 1024 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1025 1025 finally:
1026 1026 wlock.release()
1027 1027
1028 1028 def debugcheckstate(ui, repo):
1029 1029 """validate the correctness of the current dirstate"""
1030 1030 parent1, parent2 = repo.dirstate.parents()
1031 1031 m1 = repo[parent1].manifest()
1032 1032 m2 = repo[parent2].manifest()
1033 1033 errors = 0
1034 1034 for f in repo.dirstate:
1035 1035 state = repo.dirstate[f]
1036 1036 if state in "nr" and f not in m1:
1037 1037 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1038 1038 errors += 1
1039 1039 if state in "a" and f in m1:
1040 1040 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1041 1041 errors += 1
1042 1042 if state in "m" and f not in m1 and f not in m2:
1043 1043 ui.warn(_("%s in state %s, but not in either manifest\n") %
1044 1044 (f, state))
1045 1045 errors += 1
1046 1046 for f in m1:
1047 1047 state = repo.dirstate[f]
1048 1048 if state not in "nrm":
1049 1049 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1050 1050 errors += 1
1051 1051 if errors:
1052 1052 error = _(".hg/dirstate inconsistent with current parent's manifest")
1053 1053 raise util.Abort(error)
1054 1054
1055 1055 def showconfig(ui, repo, *values, **opts):
1056 1056 """show combined config settings from all hgrc files
1057 1057
1058 1058 With no arguments, print names and values of all config items.
1059 1059
1060 1060 With one argument of the form section.name, print just the value
1061 1061 of that config item.
1062 1062
1063 1063 With multiple arguments, print names and values of all config
1064 1064 items with matching section names.
1065 1065
1066 1066 With --debug, the source (filename and line number) is printed
1067 1067 for each config item.
1068 1068
1069 1069 Returns 0 on success.
1070 1070 """
1071 1071
1072 1072 for f in util.rcpath():
1073 1073 ui.debug(_('read config from: %s\n') % f)
1074 1074 untrusted = bool(opts.get('untrusted'))
1075 1075 if values:
1076 1076 sections = [v for v in values if '.' not in v]
1077 1077 items = [v for v in values if '.' in v]
1078 1078 if len(items) > 1 or items and sections:
1079 1079 raise util.Abort(_('only one config item permitted'))
1080 1080 for section, name, value in ui.walkconfig(untrusted=untrusted):
1081 1081 sectname = section + '.' + name
1082 1082 if values:
1083 1083 for v in values:
1084 1084 if v == section:
1085 1085 ui.debug('%s: ' %
1086 1086 ui.configsource(section, name, untrusted))
1087 1087 ui.write('%s=%s\n' % (sectname, value))
1088 1088 elif v == sectname:
1089 1089 ui.debug('%s: ' %
1090 1090 ui.configsource(section, name, untrusted))
1091 1091 ui.write(value, '\n')
1092 1092 else:
1093 1093 ui.debug('%s: ' %
1094 1094 ui.configsource(section, name, untrusted))
1095 1095 ui.write('%s=%s\n' % (sectname, value))
1096 1096
1097 1097 def debugpushkey(ui, repopath, namespace, *keyinfo):
1098 1098 '''access the pushkey key/value protocol
1099 1099
1100 1100 With two args, list the keys in the given namespace.
1101 1101
1102 1102 With five args, set a key to new if it currently is set to old.
1103 1103 Reports success or failure.
1104 1104 '''
1105 1105
1106 1106 target = hg.repository(ui, repopath)
1107 1107 if keyinfo:
1108 1108 key, old, new = keyinfo
1109 1109 r = target.pushkey(namespace, key, old, new)
1110 1110 ui.status(str(r) + '\n')
1111 1111 return not(r)
1112 1112 else:
1113 1113 for k, v in target.listkeys(namespace).iteritems():
1114 1114 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1115 1115 v.encode('string-escape')))
1116 1116
1117 1117 def debugrevspec(ui, repo, expr):
1118 1118 '''parse and apply a revision specification'''
1119 1119 if ui.verbose:
1120 1120 tree = revset.parse(expr)
1121 1121 ui.note(tree, "\n")
1122 1122 func = revset.match(expr)
1123 1123 for c in func(repo, range(len(repo))):
1124 1124 ui.write("%s\n" % c)
1125 1125
1126 1126 def debugsetparents(ui, repo, rev1, rev2=None):
1127 1127 """manually set the parents of the current working directory
1128 1128
1129 1129 This is useful for writing repository conversion tools, but should
1130 1130 be used with care.
1131 1131
1132 1132 Returns 0 on success.
1133 1133 """
1134 1134
1135 1135 if not rev2:
1136 1136 rev2 = hex(nullid)
1137 1137
1138 1138 wlock = repo.wlock()
1139 1139 try:
1140 1140 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1141 1141 finally:
1142 1142 wlock.release()
1143 1143
1144 1144 def debugstate(ui, repo, nodates=None):
1145 1145 """show the contents of the current dirstate"""
1146 1146 timestr = ""
1147 1147 showdate = not nodates
1148 1148 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1149 1149 if showdate:
1150 1150 if ent[3] == -1:
1151 1151 # Pad or slice to locale representation
1152 1152 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1153 1153 time.localtime(0)))
1154 1154 timestr = 'unset'
1155 1155 timestr = (timestr[:locale_len] +
1156 1156 ' ' * (locale_len - len(timestr)))
1157 1157 else:
1158 1158 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1159 1159 time.localtime(ent[3]))
1160 1160 if ent[1] & 020000:
1161 1161 mode = 'lnk'
1162 1162 else:
1163 1163 mode = '%3o' % (ent[1] & 0777)
1164 1164 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1165 1165 for f in repo.dirstate.copies():
1166 1166 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1167 1167
1168 1168 def debugsub(ui, repo, rev=None):
1169 1169 if rev == '':
1170 1170 rev = None
1171 1171 for k, v in sorted(repo[rev].substate.items()):
1172 1172 ui.write('path %s\n' % k)
1173 1173 ui.write(' source %s\n' % v[0])
1174 1174 ui.write(' revision %s\n' % v[1])
1175 1175
1176 1176 def debugdag(ui, repo, file_=None, *revs, **opts):
1177 1177 """format the changelog or an index DAG as a concise textual description
1178 1178
1179 1179 If you pass a revlog index, the revlog's DAG is emitted. If you list
1180 1180 revision numbers, they get labelled in the output as rN.
1181 1181
1182 1182 Otherwise, the changelog DAG of the current repo is emitted.
1183 1183 """
1184 1184 spaces = opts.get('spaces')
1185 1185 dots = opts.get('dots')
1186 1186 if file_:
1187 1187 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1188 1188 revs = set((int(r) for r in revs))
1189 1189 def events():
1190 1190 for r in rlog:
1191 1191 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1192 1192 if r in revs:
1193 1193 yield 'l', (r, "r%i" % r)
1194 1194 elif repo:
1195 1195 cl = repo.changelog
1196 1196 tags = opts.get('tags')
1197 1197 branches = opts.get('branches')
1198 1198 if tags:
1199 1199 labels = {}
1200 1200 for l, n in repo.tags().items():
1201 1201 labels.setdefault(cl.rev(n), []).append(l)
1202 1202 def events():
1203 1203 b = "default"
1204 1204 for r in cl:
1205 1205 if branches:
1206 1206 newb = cl.read(cl.node(r))[5]['branch']
1207 1207 if newb != b:
1208 1208 yield 'a', newb
1209 1209 b = newb
1210 1210 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1211 1211 if tags:
1212 1212 ls = labels.get(r)
1213 1213 if ls:
1214 1214 for l in ls:
1215 1215 yield 'l', (r, l)
1216 1216 else:
1217 1217 raise util.Abort(_('need repo for changelog dag'))
1218 1218
1219 1219 for line in dagparser.dagtextlines(events(),
1220 1220 addspaces=spaces,
1221 1221 wraplabels=True,
1222 1222 wrapannotations=True,
1223 1223 wrapnonlinear=dots,
1224 1224 usedots=dots,
1225 1225 maxlinewidth=70):
1226 1226 ui.write(line)
1227 1227 ui.write("\n")
1228 1228
1229 1229 def debugdata(ui, repo, file_, rev):
1230 1230 """dump the contents of a data file revision"""
1231 1231 r = None
1232 1232 if repo:
1233 1233 filelog = repo.file(file_)
1234 1234 if len(filelog):
1235 1235 r = filelog
1236 1236 if not r:
1237 1237 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1238 1238 try:
1239 1239 ui.write(r.revision(r.lookup(rev)))
1240 1240 except KeyError:
1241 1241 raise util.Abort(_('invalid revision identifier %s') % rev)
1242 1242
1243 1243 def debugdate(ui, date, range=None, **opts):
1244 1244 """parse and display a date"""
1245 1245 if opts["extended"]:
1246 1246 d = util.parsedate(date, util.extendeddateformats)
1247 1247 else:
1248 1248 d = util.parsedate(date)
1249 1249 ui.write("internal: %s %s\n" % d)
1250 1250 ui.write("standard: %s\n" % util.datestr(d))
1251 1251 if range:
1252 1252 m = util.matchdate(range)
1253 1253 ui.write("match: %s\n" % m(d[0]))
1254 1254
1255 1255 def debugindex(ui, repo, file_):
1256 1256 """dump the contents of an index file"""
1257 1257 r = None
1258 1258 if repo:
1259 1259 filelog = repo.file(file_)
1260 1260 if len(filelog):
1261 1261 r = filelog
1262 1262 if not r:
1263 1263 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1264 1264 ui.write(" rev offset length base linkrev"
1265 1265 " nodeid p1 p2\n")
1266 1266 for i in r:
1267 1267 node = r.node(i)
1268 1268 try:
1269 1269 pp = r.parents(node)
1270 1270 except:
1271 1271 pp = [nullid, nullid]
1272 1272 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1273 1273 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1274 1274 short(node), short(pp[0]), short(pp[1])))
1275 1275
1276 1276 def debugindexdot(ui, repo, file_):
1277 1277 """dump an index DAG as a graphviz dot file"""
1278 1278 r = None
1279 1279 if repo:
1280 1280 filelog = repo.file(file_)
1281 1281 if len(filelog):
1282 1282 r = filelog
1283 1283 if not r:
1284 1284 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1285 1285 ui.write("digraph G {\n")
1286 1286 for i in r:
1287 1287 node = r.node(i)
1288 1288 pp = r.parents(node)
1289 1289 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1290 1290 if pp[1] != nullid:
1291 1291 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1292 1292 ui.write("}\n")
1293 1293
1294 1294 def debuginstall(ui):
1295 1295 '''test Mercurial installation
1296 1296
1297 1297 Returns 0 on success.
1298 1298 '''
1299 1299
1300 1300 def writetemp(contents):
1301 1301 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1302 1302 f = os.fdopen(fd, "wb")
1303 1303 f.write(contents)
1304 1304 f.close()
1305 1305 return name
1306 1306
1307 1307 problems = 0
1308 1308
1309 1309 # encoding
1310 1310 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1311 1311 try:
1312 1312 encoding.fromlocal("test")
1313 1313 except util.Abort, inst:
1314 1314 ui.write(" %s\n" % inst)
1315 1315 ui.write(_(" (check that your locale is properly set)\n"))
1316 1316 problems += 1
1317 1317
1318 1318 # compiled modules
1319 1319 ui.status(_("Checking installed modules (%s)...\n")
1320 1320 % os.path.dirname(__file__))
1321 1321 try:
1322 1322 import bdiff, mpatch, base85, osutil
1323 1323 except Exception, inst:
1324 1324 ui.write(" %s\n" % inst)
1325 1325 ui.write(_(" One or more extensions could not be found"))
1326 1326 ui.write(_(" (check that you compiled the extensions)\n"))
1327 1327 problems += 1
1328 1328
1329 1329 # templates
1330 1330 ui.status(_("Checking templates...\n"))
1331 1331 try:
1332 1332 import templater
1333 1333 templater.templater(templater.templatepath("map-cmdline.default"))
1334 1334 except Exception, inst:
1335 1335 ui.write(" %s\n" % inst)
1336 1336 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1337 1337 problems += 1
1338 1338
1339 1339 # patch
1340 1340 ui.status(_("Checking patch...\n"))
1341 1341 patchproblems = 0
1342 1342 a = "1\n2\n3\n4\n"
1343 1343 b = "1\n2\n3\ninsert\n4\n"
1344 1344 fa = writetemp(a)
1345 1345 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1346 1346 os.path.basename(fa))
1347 1347 fd = writetemp(d)
1348 1348
1349 1349 files = {}
1350 1350 try:
1351 1351 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1352 1352 except util.Abort, e:
1353 1353 ui.write(_(" patch call failed:\n"))
1354 1354 ui.write(" " + str(e) + "\n")
1355 1355 patchproblems += 1
1356 1356 else:
1357 1357 if list(files) != [os.path.basename(fa)]:
1358 1358 ui.write(_(" unexpected patch output!\n"))
1359 1359 patchproblems += 1
1360 1360 a = open(fa).read()
1361 1361 if a != b:
1362 1362 ui.write(_(" patch test failed!\n"))
1363 1363 patchproblems += 1
1364 1364
1365 1365 if patchproblems:
1366 1366 if ui.config('ui', 'patch'):
1367 1367 ui.write(_(" (Current patch tool may be incompatible with patch,"
1368 1368 " or misconfigured. Please check your configuration"
1369 1369 " file)\n"))
1370 1370 else:
1371 1371 ui.write(_(" Internal patcher failure, please report this error"
1372 1372 " to http://mercurial.selenic.com/bts/\n"))
1373 1373 problems += patchproblems
1374 1374
1375 1375 os.unlink(fa)
1376 1376 os.unlink(fd)
1377 1377
1378 1378 # editor
1379 1379 ui.status(_("Checking commit editor...\n"))
1380 1380 editor = ui.geteditor()
1381 1381 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1382 1382 if not cmdpath:
1383 1383 if editor == 'vi':
1384 1384 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1385 1385 ui.write(_(" (specify a commit editor in your configuration"
1386 1386 " file)\n"))
1387 1387 else:
1388 1388 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1389 1389 ui.write(_(" (specify a commit editor in your configuration"
1390 1390 " file)\n"))
1391 1391 problems += 1
1392 1392
1393 1393 # check username
1394 1394 ui.status(_("Checking username...\n"))
1395 1395 try:
1396 1396 ui.username()
1397 1397 except util.Abort, e:
1398 1398 ui.write(" %s\n" % e)
1399 1399 ui.write(_(" (specify a username in your configuration file)\n"))
1400 1400 problems += 1
1401 1401
1402 1402 if not problems:
1403 1403 ui.status(_("No problems detected\n"))
1404 1404 else:
1405 1405 ui.write(_("%s problems detected,"
1406 1406 " please check your install!\n") % problems)
1407 1407
1408 1408 return problems
1409 1409
1410 1410 def debugrename(ui, repo, file1, *pats, **opts):
1411 1411 """dump rename information"""
1412 1412
1413 1413 ctx = repo[opts.get('rev')]
1414 1414 m = cmdutil.match(repo, (file1,) + pats, opts)
1415 1415 for abs in ctx.walk(m):
1416 1416 fctx = ctx[abs]
1417 1417 o = fctx.filelog().renamed(fctx.filenode())
1418 1418 rel = m.rel(abs)
1419 1419 if o:
1420 1420 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1421 1421 else:
1422 1422 ui.write(_("%s not renamed\n") % rel)
1423 1423
1424 1424 def debugwalk(ui, repo, *pats, **opts):
1425 1425 """show how files match on given patterns"""
1426 1426 m = cmdutil.match(repo, pats, opts)
1427 1427 items = list(repo.walk(m))
1428 1428 if not items:
1429 1429 return
1430 1430 fmt = 'f %%-%ds %%-%ds %%s' % (
1431 1431 max([len(abs) for abs in items]),
1432 1432 max([len(m.rel(abs)) for abs in items]))
1433 1433 for abs in items:
1434 1434 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1435 1435 ui.write("%s\n" % line.rstrip())
1436 1436
1437 1437 def diff(ui, repo, *pats, **opts):
1438 1438 """diff repository (or selected files)
1439 1439
1440 1440 Show differences between revisions for the specified files.
1441 1441
1442 1442 Differences between files are shown using the unified diff format.
1443 1443
1444 1444 .. note::
1445 1445 diff may generate unexpected results for merges, as it will
1446 1446 default to comparing against the working directory's first
1447 1447 parent changeset if no revisions are specified.
1448 1448
1449 1449 When two revision arguments are given, then changes are shown
1450 1450 between those revisions. If only one revision is specified then
1451 1451 that revision is compared to the working directory, and, when no
1452 1452 revisions are specified, the working directory files are compared
1453 1453 to its parent.
1454 1454
1455 1455 Alternatively you can specify -c/--change with a revision to see
1456 1456 the changes in that changeset relative to its first parent.
1457 1457
1458 1458 Without the -a/--text option, diff will avoid generating diffs of
1459 1459 files it detects as binary. With -a, diff will generate a diff
1460 1460 anyway, probably with undesirable results.
1461 1461
1462 1462 Use the -g/--git option to generate diffs in the git extended diff
1463 1463 format. For more information, read :hg:`help diffs`.
1464 1464
1465 1465 Returns 0 on success.
1466 1466 """
1467 1467
1468 1468 revs = opts.get('rev')
1469 1469 change = opts.get('change')
1470 1470 stat = opts.get('stat')
1471 1471 reverse = opts.get('reverse')
1472 1472
1473 1473 if revs and change:
1474 1474 msg = _('cannot specify --rev and --change at the same time')
1475 1475 raise util.Abort(msg)
1476 1476 elif change:
1477 1477 node2 = repo.lookup(change)
1478 1478 node1 = repo[node2].parents()[0].node()
1479 1479 else:
1480 1480 node1, node2 = cmdutil.revpair(repo, revs)
1481 1481
1482 1482 if reverse:
1483 1483 node1, node2 = node2, node1
1484 1484
1485 1485 diffopts = patch.diffopts(ui, opts)
1486 1486 m = cmdutil.match(repo, pats, opts)
1487 1487 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1488 1488 listsubrepos=opts.get('subrepos'))
1489 1489
1490 1490 def export(ui, repo, *changesets, **opts):
1491 1491 """dump the header and diffs for one or more changesets
1492 1492
1493 1493 Print the changeset header and diffs for one or more revisions.
1494 1494
1495 1495 The information shown in the changeset header is: author, date,
1496 1496 branch name (if non-default), changeset hash, parent(s) and commit
1497 1497 comment.
1498 1498
1499 1499 .. note::
1500 1500 export may generate unexpected diff output for merge
1501 1501 changesets, as it will compare the merge changeset against its
1502 1502 first parent only.
1503 1503
1504 1504 Output may be to a file, in which case the name of the file is
1505 1505 given using a format string. The formatting rules are as follows:
1506 1506
1507 1507 :``%%``: literal "%" character
1508 1508 :``%H``: changeset hash (40 hexadecimal digits)
1509 1509 :``%N``: number of patches being generated
1510 1510 :``%R``: changeset revision number
1511 1511 :``%b``: basename of the exporting repository
1512 1512 :``%h``: short-form changeset hash (12 hexadecimal digits)
1513 1513 :``%n``: zero-padded sequence number, starting at 1
1514 1514 :``%r``: zero-padded changeset revision number
1515 1515
1516 1516 Without the -a/--text option, export will avoid generating diffs
1517 1517 of files it detects as binary. With -a, export will generate a
1518 1518 diff anyway, probably with undesirable results.
1519 1519
1520 1520 Use the -g/--git option to generate diffs in the git extended diff
1521 1521 format. See :hg:`help diffs` for more information.
1522 1522
1523 1523 With the --switch-parent option, the diff will be against the
1524 1524 second parent. It can be useful to review a merge.
1525 1525
1526 1526 Returns 0 on success.
1527 1527 """
1528 1528 changesets += tuple(opts.get('rev', []))
1529 1529 if not changesets:
1530 1530 raise util.Abort(_("export requires at least one changeset"))
1531 1531 revs = cmdutil.revrange(repo, changesets)
1532 1532 if len(revs) > 1:
1533 1533 ui.note(_('exporting patches:\n'))
1534 1534 else:
1535 1535 ui.note(_('exporting patch:\n'))
1536 1536 cmdutil.export(repo, revs, template=opts.get('output'),
1537 1537 switch_parent=opts.get('switch_parent'),
1538 1538 opts=patch.diffopts(ui, opts))
1539 1539
1540 1540 def forget(ui, repo, *pats, **opts):
1541 1541 """forget the specified files on the next commit
1542 1542
1543 1543 Mark the specified files so they will no longer be tracked
1544 1544 after the next commit.
1545 1545
1546 1546 This only removes files from the current branch, not from the
1547 1547 entire project history, and it does not delete them from the
1548 1548 working directory.
1549 1549
1550 1550 To undo a forget before the next commit, see :hg:`add`.
1551 1551
1552 1552 Returns 0 on success.
1553 1553 """
1554 1554
1555 1555 if not pats:
1556 1556 raise util.Abort(_('no files specified'))
1557 1557
1558 1558 m = cmdutil.match(repo, pats, opts)
1559 1559 s = repo.status(match=m, clean=True)
1560 1560 forget = sorted(s[0] + s[1] + s[3] + s[6])
1561 1561 errs = 0
1562 1562
1563 1563 for f in m.files():
1564 1564 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1565 1565 ui.warn(_('not removing %s: file is already untracked\n')
1566 1566 % m.rel(f))
1567 1567 errs = 1
1568 1568
1569 1569 for f in forget:
1570 1570 if ui.verbose or not m.exact(f):
1571 1571 ui.status(_('removing %s\n') % m.rel(f))
1572 1572
1573 1573 repo[None].remove(forget, unlink=False)
1574 1574 return errs
1575 1575
1576 1576 def grep(ui, repo, pattern, *pats, **opts):
1577 1577 """search for a pattern in specified files and revisions
1578 1578
1579 1579 Search revisions of files for a regular expression.
1580 1580
1581 1581 This command behaves differently than Unix grep. It only accepts
1582 1582 Python/Perl regexps. It searches repository history, not the
1583 1583 working directory. It always prints the revision number in which a
1584 1584 match appears.
1585 1585
1586 1586 By default, grep only prints output for the first revision of a
1587 1587 file in which it finds a match. To get it to print every revision
1588 1588 that contains a change in match status ("-" for a match that
1589 1589 becomes a non-match, or "+" for a non-match that becomes a match),
1590 1590 use the --all flag.
1591 1591
1592 1592 Returns 0 if a match is found, 1 otherwise.
1593 1593 """
1594 1594 reflags = 0
1595 1595 if opts.get('ignore_case'):
1596 1596 reflags |= re.I
1597 1597 try:
1598 1598 regexp = re.compile(pattern, reflags)
1599 1599 except re.error, inst:
1600 1600 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1601 1601 return 1
1602 1602 sep, eol = ':', '\n'
1603 1603 if opts.get('print0'):
1604 1604 sep = eol = '\0'
1605 1605
1606 1606 getfile = util.lrucachefunc(repo.file)
1607 1607
1608 1608 def matchlines(body):
1609 1609 begin = 0
1610 1610 linenum = 0
1611 1611 while True:
1612 1612 match = regexp.search(body, begin)
1613 1613 if not match:
1614 1614 break
1615 1615 mstart, mend = match.span()
1616 1616 linenum += body.count('\n', begin, mstart) + 1
1617 1617 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1618 1618 begin = body.find('\n', mend) + 1 or len(body)
1619 1619 lend = begin - 1
1620 1620 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1621 1621
1622 1622 class linestate(object):
1623 1623 def __init__(self, line, linenum, colstart, colend):
1624 1624 self.line = line
1625 1625 self.linenum = linenum
1626 1626 self.colstart = colstart
1627 1627 self.colend = colend
1628 1628
1629 1629 def __hash__(self):
1630 1630 return hash((self.linenum, self.line))
1631 1631
1632 1632 def __eq__(self, other):
1633 1633 return self.line == other.line
1634 1634
1635 1635 matches = {}
1636 1636 copies = {}
1637 1637 def grepbody(fn, rev, body):
1638 1638 matches[rev].setdefault(fn, [])
1639 1639 m = matches[rev][fn]
1640 1640 for lnum, cstart, cend, line in matchlines(body):
1641 1641 s = linestate(line, lnum, cstart, cend)
1642 1642 m.append(s)
1643 1643
1644 1644 def difflinestates(a, b):
1645 1645 sm = difflib.SequenceMatcher(None, a, b)
1646 1646 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1647 1647 if tag == 'insert':
1648 1648 for i in xrange(blo, bhi):
1649 1649 yield ('+', b[i])
1650 1650 elif tag == 'delete':
1651 1651 for i in xrange(alo, ahi):
1652 1652 yield ('-', a[i])
1653 1653 elif tag == 'replace':
1654 1654 for i in xrange(alo, ahi):
1655 1655 yield ('-', a[i])
1656 1656 for i in xrange(blo, bhi):
1657 1657 yield ('+', b[i])
1658 1658
1659 1659 def display(fn, ctx, pstates, states):
1660 1660 rev = ctx.rev()
1661 1661 datefunc = ui.quiet and util.shortdate or util.datestr
1662 1662 found = False
1663 1663 filerevmatches = {}
1664 1664 if opts.get('all'):
1665 1665 iter = difflinestates(pstates, states)
1666 1666 else:
1667 1667 iter = [('', l) for l in states]
1668 1668 for change, l in iter:
1669 1669 cols = [fn, str(rev)]
1670 1670 before, match, after = None, None, None
1671 1671 if opts.get('line_number'):
1672 1672 cols.append(str(l.linenum))
1673 1673 if opts.get('all'):
1674 1674 cols.append(change)
1675 1675 if opts.get('user'):
1676 1676 cols.append(ui.shortuser(ctx.user()))
1677 1677 if opts.get('date'):
1678 1678 cols.append(datefunc(ctx.date()))
1679 1679 if opts.get('files_with_matches'):
1680 1680 c = (fn, rev)
1681 1681 if c in filerevmatches:
1682 1682 continue
1683 1683 filerevmatches[c] = 1
1684 1684 else:
1685 1685 before = l.line[:l.colstart]
1686 1686 match = l.line[l.colstart:l.colend]
1687 1687 after = l.line[l.colend:]
1688 1688 ui.write(sep.join(cols))
1689 1689 if before is not None:
1690 1690 ui.write(sep + before)
1691 1691 ui.write(match, label='grep.match')
1692 1692 ui.write(after)
1693 1693 ui.write(eol)
1694 1694 found = True
1695 1695 return found
1696 1696
1697 1697 skip = {}
1698 1698 revfiles = {}
1699 1699 matchfn = cmdutil.match(repo, pats, opts)
1700 1700 found = False
1701 1701 follow = opts.get('follow')
1702 1702
1703 1703 def prep(ctx, fns):
1704 1704 rev = ctx.rev()
1705 1705 pctx = ctx.parents()[0]
1706 1706 parent = pctx.rev()
1707 1707 matches.setdefault(rev, {})
1708 1708 matches.setdefault(parent, {})
1709 1709 files = revfiles.setdefault(rev, [])
1710 1710 for fn in fns:
1711 1711 flog = getfile(fn)
1712 1712 try:
1713 1713 fnode = ctx.filenode(fn)
1714 1714 except error.LookupError:
1715 1715 continue
1716 1716
1717 1717 copied = flog.renamed(fnode)
1718 1718 copy = follow and copied and copied[0]
1719 1719 if copy:
1720 1720 copies.setdefault(rev, {})[fn] = copy
1721 1721 if fn in skip:
1722 1722 if copy:
1723 1723 skip[copy] = True
1724 1724 continue
1725 1725 files.append(fn)
1726 1726
1727 1727 if fn not in matches[rev]:
1728 1728 grepbody(fn, rev, flog.read(fnode))
1729 1729
1730 1730 pfn = copy or fn
1731 1731 if pfn not in matches[parent]:
1732 1732 try:
1733 1733 fnode = pctx.filenode(pfn)
1734 1734 grepbody(pfn, parent, flog.read(fnode))
1735 1735 except error.LookupError:
1736 1736 pass
1737 1737
1738 1738 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1739 1739 rev = ctx.rev()
1740 1740 parent = ctx.parents()[0].rev()
1741 1741 for fn in sorted(revfiles.get(rev, [])):
1742 1742 states = matches[rev][fn]
1743 1743 copy = copies.get(rev, {}).get(fn)
1744 1744 if fn in skip:
1745 1745 if copy:
1746 1746 skip[copy] = True
1747 1747 continue
1748 1748 pstates = matches.get(parent, {}).get(copy or fn, [])
1749 1749 if pstates or states:
1750 1750 r = display(fn, ctx, pstates, states)
1751 1751 found = found or r
1752 1752 if r and not opts.get('all'):
1753 1753 skip[fn] = True
1754 1754 if copy:
1755 1755 skip[copy] = True
1756 1756 del matches[rev]
1757 1757 del revfiles[rev]
1758 1758
1759 1759 return not found
1760 1760
1761 1761 def heads(ui, repo, *branchrevs, **opts):
1762 1762 """show current repository heads or show branch heads
1763 1763
1764 1764 With no arguments, show all repository branch heads.
1765 1765
1766 1766 Repository "heads" are changesets with no child changesets. They are
1767 1767 where development generally takes place and are the usual targets
1768 1768 for update and merge operations. Branch heads are changesets that have
1769 1769 no child changeset on the same branch.
1770 1770
1771 1771 If one or more REVs are given, only branch heads on the branches
1772 1772 associated with the specified changesets are shown.
1773 1773
1774 1774 If -c/--closed is specified, also show branch heads marked closed
1775 1775 (see :hg:`commit --close-branch`).
1776 1776
1777 1777 If STARTREV is specified, only those heads that are descendants of
1778 1778 STARTREV will be displayed.
1779 1779
1780 1780 If -t/--topo is specified, named branch mechanics will be ignored and only
1781 1781 changesets without children will be shown.
1782 1782
1783 1783 Returns 0 if matching heads are found, 1 if not.
1784 1784 """
1785 1785
1786 1786 if opts.get('rev'):
1787 1787 start = repo.lookup(opts['rev'])
1788 1788 else:
1789 1789 start = None
1790 1790
1791 1791 if opts.get('topo'):
1792 1792 heads = [repo[h] for h in repo.heads(start)]
1793 1793 else:
1794 1794 heads = []
1795 1795 for b, ls in repo.branchmap().iteritems():
1796 1796 if start is None:
1797 1797 heads += [repo[h] for h in ls]
1798 1798 continue
1799 1799 startrev = repo.changelog.rev(start)
1800 1800 descendants = set(repo.changelog.descendants(startrev))
1801 1801 descendants.add(startrev)
1802 1802 rev = repo.changelog.rev
1803 1803 heads += [repo[h] for h in ls if rev(h) in descendants]
1804 1804
1805 1805 if branchrevs:
1806 1806 decode, encode = encoding.fromlocal, encoding.tolocal
1807 1807 branches = set(repo[decode(br)].branch() for br in branchrevs)
1808 1808 heads = [h for h in heads if h.branch() in branches]
1809 1809
1810 1810 if not opts.get('closed'):
1811 1811 heads = [h for h in heads if not h.extra().get('close')]
1812 1812
1813 1813 if opts.get('active') and branchrevs:
1814 1814 dagheads = repo.heads(start)
1815 1815 heads = [h for h in heads if h.node() in dagheads]
1816 1816
1817 1817 if branchrevs:
1818 1818 haveheads = set(h.branch() for h in heads)
1819 1819 if branches - haveheads:
1820 1820 headless = ', '.join(encode(b) for b in branches - haveheads)
1821 1821 msg = _('no open branch heads found on branches %s')
1822 1822 if opts.get('rev'):
1823 1823 msg += _(' (started at %s)' % opts['rev'])
1824 1824 ui.warn((msg + '\n') % headless)
1825 1825
1826 1826 if not heads:
1827 1827 return 1
1828 1828
1829 1829 heads = sorted(heads, key=lambda x: -x.rev())
1830 1830 displayer = cmdutil.show_changeset(ui, repo, opts)
1831 1831 for ctx in heads:
1832 1832 displayer.show(ctx)
1833 1833 displayer.close()
1834 1834
1835 1835 def help_(ui, name=None, with_version=False, unknowncmd=False):
1836 1836 """show help for a given topic or a help overview
1837 1837
1838 1838 With no arguments, print a list of commands with short help messages.
1839 1839
1840 1840 Given a topic, extension, or command name, print help for that
1841 1841 topic.
1842 1842
1843 1843 Returns 0 if successful.
1844 1844 """
1845 1845 option_lists = []
1846 1846 textwidth = ui.termwidth() - 2
1847 1847
1848 1848 def addglobalopts(aliases):
1849 1849 if ui.verbose:
1850 1850 option_lists.append((_("global options:"), globalopts))
1851 1851 if name == 'shortlist':
1852 1852 option_lists.append((_('use "hg help" for the full list '
1853 1853 'of commands'), ()))
1854 1854 else:
1855 1855 if name == 'shortlist':
1856 1856 msg = _('use "hg help" for the full list of commands '
1857 1857 'or "hg -v" for details')
1858 1858 elif aliases:
1859 1859 msg = _('use "hg -v help%s" to show aliases and '
1860 1860 'global options') % (name and " " + name or "")
1861 1861 else:
1862 1862 msg = _('use "hg -v help %s" to show global options') % name
1863 1863 option_lists.append((msg, ()))
1864 1864
1865 1865 def helpcmd(name):
1866 1866 if with_version:
1867 1867 version_(ui)
1868 1868 ui.write('\n')
1869 1869
1870 1870 try:
1871 1871 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1872 1872 except error.AmbiguousCommand, inst:
1873 1873 # py3k fix: except vars can't be used outside the scope of the
1874 1874 # except block, nor can be used inside a lambda. python issue4617
1875 1875 prefix = inst.args[0]
1876 1876 select = lambda c: c.lstrip('^').startswith(prefix)
1877 1877 helplist(_('list of commands:\n\n'), select)
1878 1878 return
1879 1879
1880 1880 # check if it's an invalid alias and display its error if it is
1881 1881 if getattr(entry[0], 'badalias', False):
1882 1882 if not unknowncmd:
1883 1883 entry[0](ui)
1884 1884 return
1885 1885
1886 1886 # synopsis
1887 1887 if len(entry) > 2:
1888 1888 if entry[2].startswith('hg'):
1889 1889 ui.write("%s\n" % entry[2])
1890 1890 else:
1891 1891 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1892 1892 else:
1893 1893 ui.write('hg %s\n' % aliases[0])
1894 1894
1895 1895 # aliases
1896 1896 if not ui.quiet and len(aliases) > 1:
1897 1897 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1898 1898
1899 1899 # description
1900 1900 doc = gettext(entry[0].__doc__)
1901 1901 if not doc:
1902 1902 doc = _("(no help text available)")
1903 1903 if hasattr(entry[0], 'definition'): # aliased command
1904 1904 if entry[0].definition.startswith('!'): # shell alias
1905 1905 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1906 1906 else:
1907 1907 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1908 1908 if ui.quiet:
1909 1909 doc = doc.splitlines()[0]
1910 1910 keep = ui.verbose and ['verbose'] or []
1911 1911 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1912 1912 ui.write("\n%s\n" % formatted)
1913 1913 if pruned:
1914 1914 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1915 1915
1916 1916 if not ui.quiet:
1917 1917 # options
1918 1918 if entry[1]:
1919 1919 option_lists.append((_("options:\n"), entry[1]))
1920 1920
1921 1921 addglobalopts(False)
1922 1922
1923 1923 def helplist(header, select=None):
1924 1924 h = {}
1925 1925 cmds = {}
1926 1926 for c, e in table.iteritems():
1927 1927 f = c.split("|", 1)[0]
1928 1928 if select and not select(f):
1929 1929 continue
1930 1930 if (not select and name != 'shortlist' and
1931 1931 e[0].__module__ != __name__):
1932 1932 continue
1933 1933 if name == "shortlist" and not f.startswith("^"):
1934 1934 continue
1935 1935 f = f.lstrip("^")
1936 1936 if not ui.debugflag and f.startswith("debug"):
1937 1937 continue
1938 1938 doc = e[0].__doc__
1939 1939 if doc and 'DEPRECATED' in doc and not ui.verbose:
1940 1940 continue
1941 1941 doc = gettext(doc)
1942 1942 if not doc:
1943 1943 doc = _("(no help text available)")
1944 1944 h[f] = doc.splitlines()[0].rstrip()
1945 1945 cmds[f] = c.lstrip("^")
1946 1946
1947 1947 if not h:
1948 1948 ui.status(_('no commands defined\n'))
1949 1949 return
1950 1950
1951 1951 ui.status(header)
1952 1952 fns = sorted(h)
1953 1953 m = max(map(len, fns))
1954 1954 for f in fns:
1955 1955 if ui.verbose:
1956 1956 commands = cmds[f].replace("|",", ")
1957 1957 ui.write(" %s:\n %s\n"%(commands, h[f]))
1958 1958 else:
1959 1959 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1960 1960 initindent=' %-*s ' % (m, f),
1961 1961 hangindent=' ' * (m + 4))))
1962 1962
1963 1963 if not ui.quiet:
1964 1964 addglobalopts(True)
1965 1965
1966 1966 def helptopic(name):
1967 1967 for names, header, doc in help.helptable:
1968 1968 if name in names:
1969 1969 break
1970 1970 else:
1971 1971 raise error.UnknownCommand(name)
1972 1972
1973 1973 # description
1974 1974 if not doc:
1975 1975 doc = _("(no help text available)")
1976 1976 if hasattr(doc, '__call__'):
1977 1977 doc = doc()
1978 1978
1979 1979 ui.write("%s\n\n" % header)
1980 1980 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1981 1981
1982 1982 def helpext(name):
1983 1983 try:
1984 1984 mod = extensions.find(name)
1985 1985 doc = gettext(mod.__doc__) or _('no help text available')
1986 1986 except KeyError:
1987 1987 mod = None
1988 1988 doc = extensions.disabledext(name)
1989 1989 if not doc:
1990 1990 raise error.UnknownCommand(name)
1991 1991
1992 1992 if '\n' not in doc:
1993 1993 head, tail = doc, ""
1994 1994 else:
1995 1995 head, tail = doc.split('\n', 1)
1996 1996 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1997 1997 if tail:
1998 1998 ui.write(minirst.format(tail, textwidth))
1999 1999 ui.status('\n\n')
2000 2000
2001 2001 if mod:
2002 2002 try:
2003 2003 ct = mod.cmdtable
2004 2004 except AttributeError:
2005 2005 ct = {}
2006 2006 modcmds = set([c.split('|', 1)[0] for c in ct])
2007 2007 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2008 2008 else:
2009 2009 ui.write(_('use "hg help extensions" for information on enabling '
2010 2010 'extensions\n'))
2011 2011
2012 2012 def helpextcmd(name):
2013 2013 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
2014 2014 doc = gettext(mod.__doc__).splitlines()[0]
2015 2015
2016 2016 msg = help.listexts(_("'%s' is provided by the following "
2017 2017 "extension:") % cmd, {ext: doc}, len(ext),
2018 2018 indent=4)
2019 2019 ui.write(minirst.format(msg, textwidth))
2020 2020 ui.write('\n\n')
2021 2021 ui.write(_('use "hg help extensions" for information on enabling '
2022 2022 'extensions\n'))
2023 2023
2024 2024 if name and name != 'shortlist':
2025 2025 i = None
2026 2026 if unknowncmd:
2027 2027 queries = (helpextcmd,)
2028 2028 else:
2029 2029 queries = (helptopic, helpcmd, helpext, helpextcmd)
2030 2030 for f in queries:
2031 2031 try:
2032 2032 f(name)
2033 2033 i = None
2034 2034 break
2035 2035 except error.UnknownCommand, inst:
2036 2036 i = inst
2037 2037 if i:
2038 2038 raise i
2039 2039
2040 2040 else:
2041 2041 # program name
2042 2042 if ui.verbose or with_version:
2043 2043 version_(ui)
2044 2044 else:
2045 2045 ui.status(_("Mercurial Distributed SCM\n"))
2046 2046 ui.status('\n')
2047 2047
2048 2048 # list of commands
2049 2049 if name == "shortlist":
2050 2050 header = _('basic commands:\n\n')
2051 2051 else:
2052 2052 header = _('list of commands:\n\n')
2053 2053
2054 2054 helplist(header)
2055 2055 if name != 'shortlist':
2056 2056 exts, maxlength = extensions.enabled()
2057 2057 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2058 2058 if text:
2059 2059 ui.write("\n%s\n" % minirst.format(text, textwidth))
2060 2060
2061 2061 # list all option lists
2062 2062 opt_output = []
2063 2063 multioccur = False
2064 2064 for title, options in option_lists:
2065 2065 opt_output.append(("\n%s" % title, None))
2066 2066 for option in options:
2067 2067 if len(option) == 5:
2068 2068 shortopt, longopt, default, desc, optlabel = option
2069 2069 else:
2070 2070 shortopt, longopt, default, desc = option
2071 2071 optlabel = _("VALUE") # default label
2072 2072
2073 2073 if _("DEPRECATED") in desc and not ui.verbose:
2074 2074 continue
2075 2075 if isinstance(default, list):
2076 2076 numqualifier = " %s [+]" % optlabel
2077 2077 multioccur = True
2078 2078 elif (default is not None) and not isinstance(default, bool):
2079 2079 numqualifier = " %s" % optlabel
2080 2080 else:
2081 2081 numqualifier = ""
2082 2082 opt_output.append(("%2s%s" %
2083 2083 (shortopt and "-%s" % shortopt,
2084 2084 longopt and " --%s%s" %
2085 2085 (longopt, numqualifier)),
2086 2086 "%s%s" % (desc,
2087 2087 default
2088 2088 and _(" (default: %s)") % default
2089 2089 or "")))
2090 2090 if multioccur:
2091 2091 msg = _("\n[+] marked option can be specified multiple times")
2092 2092 if ui.verbose and name != 'shortlist':
2093 2093 opt_output.append((msg, None))
2094 2094 else:
2095 2095 opt_output.insert(-1, (msg, None))
2096 2096
2097 2097 if not name:
2098 2098 ui.write(_("\nadditional help topics:\n\n"))
2099 2099 topics = []
2100 2100 for names, header, doc in help.helptable:
2101 2101 topics.append((sorted(names, key=len, reverse=True)[0], header))
2102 2102 topics_len = max([len(s[0]) for s in topics])
2103 2103 for t, desc in topics:
2104 2104 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2105 2105
2106 2106 if opt_output:
2107 2107 colwidth = encoding.colwidth
2108 2108 # normalize: (opt or message, desc or None, width of opt)
2109 2109 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2110 2110 for opt, desc in opt_output]
2111 2111 hanging = max([e[2] for e in entries])
2112 2112 for opt, desc, width in entries:
2113 2113 if desc:
2114 2114 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2115 2115 hangindent = ' ' * (hanging + 3)
2116 2116 ui.write('%s\n' % (util.wrap(desc, textwidth,
2117 2117 initindent=initindent,
2118 2118 hangindent=hangindent)))
2119 2119 else:
2120 2120 ui.write("%s\n" % opt)
2121 2121
2122 2122 def identify(ui, repo, source=None,
2123 2123 rev=None, num=None, id=None, branch=None, tags=None):
2124 2124 """identify the working copy or specified revision
2125 2125
2126 2126 With no revision, print a summary of the current state of the
2127 2127 repository.
2128 2128
2129 2129 Specifying a path to a repository root or Mercurial bundle will
2130 2130 cause lookup to operate on that repository/bundle.
2131 2131
2132 2132 This summary identifies the repository state using one or two
2133 2133 parent hash identifiers, followed by a "+" if there are
2134 2134 uncommitted changes in the working directory, a list of tags for
2135 2135 this revision and a branch name for non-default branches.
2136 2136
2137 2137 Returns 0 if successful.
2138 2138 """
2139 2139
2140 2140 if not repo and not source:
2141 2141 raise util.Abort(_("there is no Mercurial repository here "
2142 2142 "(.hg not found)"))
2143 2143
2144 2144 hexfunc = ui.debugflag and hex or short
2145 2145 default = not (num or id or branch or tags)
2146 2146 output = []
2147 2147
2148 2148 revs = []
2149 2149 if source:
2150 2150 source, branches = hg.parseurl(ui.expandpath(source))
2151 2151 repo = hg.repository(ui, source)
2152 2152 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2153 2153
2154 2154 if not repo.local():
2155 2155 if not rev and revs:
2156 2156 rev = revs[0]
2157 2157 if not rev:
2158 2158 rev = "tip"
2159 2159 if num or branch or tags:
2160 2160 raise util.Abort(
2161 2161 "can't query remote revision number, branch, or tags")
2162 2162 output = [hexfunc(repo.lookup(rev))]
2163 2163 elif not rev:
2164 2164 ctx = repo[None]
2165 2165 parents = ctx.parents()
2166 2166 changed = False
2167 2167 if default or id or num:
2168 2168 changed = util.any(repo.status())
2169 2169 if default or id:
2170 2170 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2171 2171 (changed) and "+" or "")]
2172 2172 if num:
2173 2173 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2174 2174 (changed) and "+" or ""))
2175 2175 else:
2176 2176 ctx = repo[rev]
2177 2177 if default or id:
2178 2178 output = [hexfunc(ctx.node())]
2179 2179 if num:
2180 2180 output.append(str(ctx.rev()))
2181 2181
2182 2182 if repo.local() and default and not ui.quiet:
2183 2183 b = encoding.tolocal(ctx.branch())
2184 2184 if b != 'default':
2185 2185 output.append("(%s)" % b)
2186 2186
2187 2187 # multiple tags for a single parent separated by '/'
2188 2188 t = "/".join(ctx.tags())
2189 2189 if t:
2190 2190 output.append(t)
2191 2191
2192 2192 if branch:
2193 2193 output.append(encoding.tolocal(ctx.branch()))
2194 2194
2195 2195 if tags:
2196 2196 output.extend(ctx.tags())
2197 2197
2198 2198 ui.write("%s\n" % ' '.join(output))
2199 2199
2200 2200 def import_(ui, repo, patch1, *patches, **opts):
2201 2201 """import an ordered set of patches
2202 2202
2203 2203 Import a list of patches and commit them individually (unless
2204 2204 --no-commit is specified).
2205 2205
2206 2206 If there are outstanding changes in the working directory, import
2207 2207 will abort unless given the -f/--force flag.
2208 2208
2209 2209 You can import a patch straight from a mail message. Even patches
2210 2210 as attachments work (to use the body part, it must have type
2211 2211 text/plain or text/x-patch). From and Subject headers of email
2212 2212 message are used as default committer and commit message. All
2213 2213 text/plain body parts before first diff are added to commit
2214 2214 message.
2215 2215
2216 2216 If the imported patch was generated by :hg:`export`, user and
2217 2217 description from patch override values from message headers and
2218 2218 body. Values given on command line with -m/--message and -u/--user
2219 2219 override these.
2220 2220
2221 2221 If --exact is specified, import will set the working directory to
2222 2222 the parent of each patch before applying it, and will abort if the
2223 2223 resulting changeset has a different ID than the one recorded in
2224 2224 the patch. This may happen due to character set problems or other
2225 2225 deficiencies in the text patch format.
2226 2226
2227 2227 With -s/--similarity, hg will attempt to discover renames and
2228 2228 copies in the patch in the same way as 'addremove'.
2229 2229
2230 2230 To read a patch from standard input, use "-" as the patch name. If
2231 2231 a URL is specified, the patch will be downloaded from it.
2232 2232 See :hg:`help dates` for a list of formats valid for -d/--date.
2233 2233
2234 2234 Returns 0 on success.
2235 2235 """
2236 2236 patches = (patch1,) + patches
2237 2237
2238 2238 date = opts.get('date')
2239 2239 if date:
2240 2240 opts['date'] = util.parsedate(date)
2241 2241
2242 2242 try:
2243 2243 sim = float(opts.get('similarity') or 0)
2244 2244 except ValueError:
2245 2245 raise util.Abort(_('similarity must be a number'))
2246 2246 if sim < 0 or sim > 100:
2247 2247 raise util.Abort(_('similarity must be between 0 and 100'))
2248 2248
2249 2249 if opts.get('exact') or not opts.get('force'):
2250 2250 cmdutil.bail_if_changed(repo)
2251 2251
2252 2252 d = opts["base"]
2253 2253 strip = opts["strip"]
2254 2254 wlock = lock = None
2255 2255
2256 2256 def tryone(ui, hunk):
2257 2257 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2258 2258 patch.extract(ui, hunk)
2259 2259
2260 2260 if not tmpname:
2261 2261 return None
2262 2262 commitid = _('to working directory')
2263 2263
2264 2264 try:
2265 2265 cmdline_message = cmdutil.logmessage(opts)
2266 2266 if cmdline_message:
2267 2267 # pickup the cmdline msg
2268 2268 message = cmdline_message
2269 2269 elif message:
2270 2270 # pickup the patch msg
2271 2271 message = message.strip()
2272 2272 else:
2273 2273 # launch the editor
2274 2274 message = None
2275 2275 ui.debug('message:\n%s\n' % message)
2276 2276
2277 2277 wp = repo.parents()
2278 2278 if opts.get('exact'):
2279 2279 if not nodeid or not p1:
2280 2280 raise util.Abort(_('not a Mercurial patch'))
2281 2281 p1 = repo.lookup(p1)
2282 2282 p2 = repo.lookup(p2 or hex(nullid))
2283 2283
2284 2284 if p1 != wp[0].node():
2285 2285 hg.clean(repo, p1)
2286 2286 repo.dirstate.setparents(p1, p2)
2287 2287 elif p2:
2288 2288 try:
2289 2289 p1 = repo.lookup(p1)
2290 2290 p2 = repo.lookup(p2)
2291 2291 if p1 == wp[0].node():
2292 2292 repo.dirstate.setparents(p1, p2)
2293 2293 except error.RepoError:
2294 2294 pass
2295 2295 if opts.get('exact') or opts.get('import_branch'):
2296 2296 repo.dirstate.setbranch(branch or 'default')
2297 2297
2298 2298 files = {}
2299 2299 try:
2300 2300 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2301 2301 files=files, eolmode=None)
2302 2302 finally:
2303 2303 files = cmdutil.updatedir(ui, repo, files,
2304 2304 similarity=sim / 100.0)
2305 2305 if not opts.get('no_commit'):
2306 2306 if opts.get('exact'):
2307 2307 m = None
2308 2308 else:
2309 2309 m = cmdutil.matchfiles(repo, files or [])
2310 2310 n = repo.commit(message, opts.get('user') or user,
2311 2311 opts.get('date') or date, match=m,
2312 2312 editor=cmdutil.commiteditor)
2313 2313 if opts.get('exact'):
2314 2314 if hex(n) != nodeid:
2315 2315 repo.rollback()
2316 2316 raise util.Abort(_('patch is damaged'
2317 2317 ' or loses information'))
2318 2318 # Force a dirstate write so that the next transaction
2319 2319 # backups an up-do-date file.
2320 2320 repo.dirstate.write()
2321 2321 if n:
2322 2322 commitid = short(n)
2323 2323
2324 2324 return commitid
2325 2325 finally:
2326 2326 os.unlink(tmpname)
2327 2327
2328 2328 try:
2329 2329 wlock = repo.wlock()
2330 2330 lock = repo.lock()
2331 2331 lastcommit = None
2332 2332 for p in patches:
2333 2333 pf = os.path.join(d, p)
2334 2334
2335 2335 if pf == '-':
2336 2336 ui.status(_("applying patch from stdin\n"))
2337 2337 pf = sys.stdin
2338 2338 else:
2339 2339 ui.status(_("applying %s\n") % p)
2340 2340 pf = url.open(ui, pf)
2341 2341
2342 2342 haspatch = False
2343 2343 for hunk in patch.split(pf):
2344 2344 commitid = tryone(ui, hunk)
2345 2345 if commitid:
2346 2346 haspatch = True
2347 2347 if lastcommit:
2348 2348 ui.status(_('applied %s\n') % lastcommit)
2349 2349 lastcommit = commitid
2350 2350
2351 2351 if not haspatch:
2352 2352 raise util.Abort(_('no diffs found'))
2353 2353
2354 2354 finally:
2355 2355 release(lock, wlock)
2356 2356
2357 2357 def incoming(ui, repo, source="default", **opts):
2358 2358 """show new changesets found in source
2359 2359
2360 2360 Show new changesets found in the specified path/URL or the default
2361 2361 pull location. These are the changesets that would have been pulled
2362 2362 if a pull at the time you issued this command.
2363 2363
2364 2364 For remote repository, using --bundle avoids downloading the
2365 2365 changesets twice if the incoming is followed by a pull.
2366 2366
2367 2367 See pull for valid source format details.
2368 2368
2369 2369 Returns 0 if there are incoming changes, 1 otherwise.
2370 2370 """
2371 2371 if opts.get('bundle') and opts.get('subrepos'):
2372 2372 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2373 2373
2374 2374 ret = hg.incoming(ui, repo, source, opts)
2375 2375 return ret
2376 2376
2377 2377 def init(ui, dest=".", **opts):
2378 2378 """create a new repository in the given directory
2379 2379
2380 2380 Initialize a new repository in the given directory. If the given
2381 2381 directory does not exist, it will be created.
2382 2382
2383 2383 If no directory is given, the current directory is used.
2384 2384
2385 2385 It is possible to specify an ``ssh://`` URL as the destination.
2386 2386 See :hg:`help urls` for more information.
2387 2387
2388 2388 Returns 0 on success.
2389 2389 """
2390 2390 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2391 2391
2392 2392 def locate(ui, repo, *pats, **opts):
2393 2393 """locate files matching specific patterns
2394 2394
2395 2395 Print files under Mercurial control in the working directory whose
2396 2396 names match the given patterns.
2397 2397
2398 2398 By default, this command searches all directories in the working
2399 2399 directory. To search just the current directory and its
2400 2400 subdirectories, use "--include .".
2401 2401
2402 2402 If no patterns are given to match, this command prints the names
2403 2403 of all files under Mercurial control in the working directory.
2404 2404
2405 2405 If you want to feed the output of this command into the "xargs"
2406 2406 command, use the -0 option to both this command and "xargs". This
2407 2407 will avoid the problem of "xargs" treating single filenames that
2408 2408 contain whitespace as multiple filenames.
2409 2409
2410 2410 Returns 0 if a match is found, 1 otherwise.
2411 2411 """
2412 2412 end = opts.get('print0') and '\0' or '\n'
2413 2413 rev = opts.get('rev') or None
2414 2414
2415 2415 ret = 1
2416 2416 m = cmdutil.match(repo, pats, opts, default='relglob')
2417 2417 m.bad = lambda x, y: False
2418 2418 for abs in repo[rev].walk(m):
2419 2419 if not rev and abs not in repo.dirstate:
2420 2420 continue
2421 2421 if opts.get('fullpath'):
2422 2422 ui.write(repo.wjoin(abs), end)
2423 2423 else:
2424 2424 ui.write(((pats and m.rel(abs)) or abs), end)
2425 2425 ret = 0
2426 2426
2427 2427 return ret
2428 2428
2429 2429 def log(ui, repo, *pats, **opts):
2430 2430 """show revision history of entire repository or files
2431 2431
2432 2432 Print the revision history of the specified files or the entire
2433 2433 project.
2434 2434
2435 2435 File history is shown without following rename or copy history of
2436 2436 files. Use -f/--follow with a filename to follow history across
2437 2437 renames and copies. --follow without a filename will only show
2438 2438 ancestors or descendants of the starting revision. --follow-first
2439 2439 only follows the first parent of merge revisions.
2440 2440
2441 2441 If no revision range is specified, the default is tip:0 unless
2442 2442 --follow is set, in which case the working directory parent is
2443 2443 used as the starting revision. You can specify a revision set for
2444 2444 log, see :hg:`help revsets` for more information.
2445 2445
2446 2446 See :hg:`help dates` for a list of formats valid for -d/--date.
2447 2447
2448 2448 By default this command prints revision number and changeset id,
2449 2449 tags, non-trivial parents, user, date and time, and a summary for
2450 2450 each commit. When the -v/--verbose switch is used, the list of
2451 2451 changed files and full commit message are shown.
2452 2452
2453 2453 .. note::
2454 2454 log -p/--patch may generate unexpected diff output for merge
2455 2455 changesets, as it will only compare the merge changeset against
2456 2456 its first parent. Also, only files different from BOTH parents
2457 2457 will appear in files:.
2458 2458
2459 2459 Returns 0 on success.
2460 2460 """
2461 2461
2462 2462 matchfn = cmdutil.match(repo, pats, opts)
2463 2463 limit = cmdutil.loglimit(opts)
2464 2464 count = 0
2465 2465
2466 2466 endrev = None
2467 2467 if opts.get('copies') and opts.get('rev'):
2468 2468 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2469 2469
2470 2470 df = False
2471 2471 if opts["date"]:
2472 2472 df = util.matchdate(opts["date"])
2473 2473
2474 2474 branches = opts.get('branch', []) + opts.get('only_branch', [])
2475 2475 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2476 2476
2477 2477 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2478 2478 def prep(ctx, fns):
2479 2479 rev = ctx.rev()
2480 2480 parents = [p for p in repo.changelog.parentrevs(rev)
2481 2481 if p != nullrev]
2482 2482 if opts.get('no_merges') and len(parents) == 2:
2483 2483 return
2484 2484 if opts.get('only_merges') and len(parents) != 2:
2485 2485 return
2486 2486 if opts.get('branch') and ctx.branch() not in opts['branch']:
2487 2487 return
2488 2488 if df and not df(ctx.date()[0]):
2489 2489 return
2490 2490 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2491 2491 return
2492 2492 if opts.get('keyword'):
2493 2493 for k in [kw.lower() for kw in opts['keyword']]:
2494 2494 if (k in ctx.user().lower() or
2495 2495 k in ctx.description().lower() or
2496 2496 k in " ".join(ctx.files()).lower()):
2497 2497 break
2498 2498 else:
2499 2499 return
2500 2500
2501 2501 copies = None
2502 2502 if opts.get('copies') and rev:
2503 2503 copies = []
2504 2504 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2505 2505 for fn in ctx.files():
2506 2506 rename = getrenamed(fn, rev)
2507 2507 if rename:
2508 2508 copies.append((fn, rename[0]))
2509 2509
2510 2510 revmatchfn = None
2511 2511 if opts.get('patch') or opts.get('stat'):
2512 2512 if opts.get('follow') or opts.get('follow_first'):
2513 2513 # note: this might be wrong when following through merges
2514 2514 revmatchfn = cmdutil.match(repo, fns, default='path')
2515 2515 else:
2516 2516 revmatchfn = matchfn
2517 2517
2518 2518 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2519 2519
2520 2520 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2521 2521 if count == limit:
2522 2522 break
2523 2523 if displayer.flush(ctx.rev()):
2524 2524 count += 1
2525 2525 displayer.close()
2526 2526
2527 2527 def manifest(ui, repo, node=None, rev=None):
2528 2528 """output the current or given revision of the project manifest
2529 2529
2530 2530 Print a list of version controlled files for the given revision.
2531 2531 If no revision is given, the first parent of the working directory
2532 2532 is used, or the null revision if no revision is checked out.
2533 2533
2534 2534 With -v, print file permissions, symlink and executable bits.
2535 2535 With --debug, print file revision hashes.
2536 2536
2537 2537 Returns 0 on success.
2538 2538 """
2539 2539
2540 2540 if rev and node:
2541 2541 raise util.Abort(_("please specify just one revision"))
2542 2542
2543 2543 if not node:
2544 2544 node = rev
2545 2545
2546 2546 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2547 2547 ctx = repo[node]
2548 2548 for f in ctx:
2549 2549 if ui.debugflag:
2550 2550 ui.write("%40s " % hex(ctx.manifest()[f]))
2551 2551 if ui.verbose:
2552 2552 ui.write(decor[ctx.flags(f)])
2553 2553 ui.write("%s\n" % f)
2554 2554
2555 2555 def merge(ui, repo, node=None, **opts):
2556 2556 """merge working directory with another revision
2557 2557
2558 2558 The current working directory is updated with all changes made in
2559 2559 the requested revision since the last common predecessor revision.
2560 2560
2561 2561 Files that changed between either parent are marked as changed for
2562 2562 the next commit and a commit must be performed before any further
2563 2563 updates to the repository are allowed. The next commit will have
2564 2564 two parents.
2565 2565
2566 ``--tool`` can be used to specify the merge tool used for file
2567 merges. It overrides the HGMERGE environment variable and your
2568 configuration files.
2569
2566 2570 If no revision is specified, the working directory's parent is a
2567 2571 head revision, and the current branch contains exactly one other
2568 2572 head, the other head is merged with by default. Otherwise, an
2569 2573 explicit revision with which to merge with must be provided.
2570 2574
2575 :hg:`resolve` must be used to resolve unresolved files.
2576
2571 2577 To undo an uncommitted merge, use :hg:`update --clean .` which
2572 2578 will check out a clean copy of the original merge parent, losing
2573 2579 all changes.
2574 2580
2575 2581 Returns 0 on success, 1 if there are unresolved files.
2576 2582 """
2577 2583
2578 2584 if opts.get('rev') and node:
2579 2585 raise util.Abort(_("please specify just one revision"))
2580 2586 if not node:
2581 2587 node = opts.get('rev')
2582 2588
2589 t = opts.get('tool')
2590 if t:
2591 if 'HGMERGE' in os.environ:
2592 os.environ['HGMERGE'] = t
2593 ui.setconfig('ui', 'merge', t)
2594
2583 2595 if not node:
2584 2596 branch = repo.changectx(None).branch()
2585 2597 bheads = repo.branchheads(branch)
2586 2598 if len(bheads) > 2:
2587 2599 raise util.Abort(_(
2588 2600 'branch \'%s\' has %d heads - '
2589 2601 'please merge with an explicit rev\n'
2590 2602 '(run \'hg heads .\' to see heads)')
2591 2603 % (branch, len(bheads)))
2592 2604
2593 2605 parent = repo.dirstate.parents()[0]
2594 2606 if len(bheads) == 1:
2595 2607 if len(repo.heads()) > 1:
2596 2608 raise util.Abort(_(
2597 2609 'branch \'%s\' has one head - '
2598 2610 'please merge with an explicit rev\n'
2599 2611 '(run \'hg heads\' to see all heads)')
2600 2612 % branch)
2601 2613 msg = _('there is nothing to merge')
2602 2614 if parent != repo.lookup(repo[None].branch()):
2603 2615 msg = _('%s - use "hg update" instead') % msg
2604 2616 raise util.Abort(msg)
2605 2617
2606 2618 if parent not in bheads:
2607 2619 raise util.Abort(_('working dir not at a head rev - '
2608 2620 'use "hg update" or merge with an explicit rev'))
2609 2621 node = parent == bheads[0] and bheads[-1] or bheads[0]
2610 2622
2611 2623 if opts.get('preview'):
2612 2624 # find nodes that are ancestors of p2 but not of p1
2613 2625 p1 = repo.lookup('.')
2614 2626 p2 = repo.lookup(node)
2615 2627 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2616 2628
2617 2629 displayer = cmdutil.show_changeset(ui, repo, opts)
2618 2630 for node in nodes:
2619 2631 displayer.show(repo[node])
2620 2632 displayer.close()
2621 2633 return 0
2622 2634
2623 2635 return hg.merge(repo, node, force=opts.get('force'))
2624 2636
2625 2637 def outgoing(ui, repo, dest=None, **opts):
2626 2638 """show changesets not found in the destination
2627 2639
2628 2640 Show changesets not found in the specified destination repository
2629 2641 or the default push location. These are the changesets that would
2630 2642 be pushed if a push was requested.
2631 2643
2632 2644 See pull for details of valid destination formats.
2633 2645
2634 2646 Returns 0 if there are outgoing changes, 1 otherwise.
2635 2647 """
2636 2648 ret = hg.outgoing(ui, repo, dest, opts)
2637 2649 return ret
2638 2650
2639 2651 def parents(ui, repo, file_=None, **opts):
2640 2652 """show the parents of the working directory or revision
2641 2653
2642 2654 Print the working directory's parent revisions. If a revision is
2643 2655 given via -r/--rev, the parent of that revision will be printed.
2644 2656 If a file argument is given, the revision in which the file was
2645 2657 last changed (before the working directory revision or the
2646 2658 argument to --rev if given) is printed.
2647 2659
2648 2660 Returns 0 on success.
2649 2661 """
2650 2662 rev = opts.get('rev')
2651 2663 if rev:
2652 2664 ctx = repo[rev]
2653 2665 else:
2654 2666 ctx = repo[None]
2655 2667
2656 2668 if file_:
2657 2669 m = cmdutil.match(repo, (file_,), opts)
2658 2670 if m.anypats() or len(m.files()) != 1:
2659 2671 raise util.Abort(_('can only specify an explicit filename'))
2660 2672 file_ = m.files()[0]
2661 2673 filenodes = []
2662 2674 for cp in ctx.parents():
2663 2675 if not cp:
2664 2676 continue
2665 2677 try:
2666 2678 filenodes.append(cp.filenode(file_))
2667 2679 except error.LookupError:
2668 2680 pass
2669 2681 if not filenodes:
2670 2682 raise util.Abort(_("'%s' not found in manifest!") % file_)
2671 2683 fl = repo.file(file_)
2672 2684 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2673 2685 else:
2674 2686 p = [cp.node() for cp in ctx.parents()]
2675 2687
2676 2688 displayer = cmdutil.show_changeset(ui, repo, opts)
2677 2689 for n in p:
2678 2690 if n != nullid:
2679 2691 displayer.show(repo[n])
2680 2692 displayer.close()
2681 2693
2682 2694 def paths(ui, repo, search=None):
2683 2695 """show aliases for remote repositories
2684 2696
2685 2697 Show definition of symbolic path name NAME. If no name is given,
2686 2698 show definition of all available names.
2687 2699
2688 2700 Path names are defined in the [paths] section of your
2689 2701 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2690 2702 repository, ``.hg/hgrc`` is used, too.
2691 2703
2692 2704 The path names ``default`` and ``default-push`` have a special
2693 2705 meaning. When performing a push or pull operation, they are used
2694 2706 as fallbacks if no location is specified on the command-line.
2695 2707 When ``default-push`` is set, it will be used for push and
2696 2708 ``default`` will be used for pull; otherwise ``default`` is used
2697 2709 as the fallback for both. When cloning a repository, the clone
2698 2710 source is written as ``default`` in ``.hg/hgrc``. Note that
2699 2711 ``default`` and ``default-push`` apply to all inbound (e.g.
2700 2712 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2701 2713 :hg:`bundle`) operations.
2702 2714
2703 2715 See :hg:`help urls` for more information.
2704 2716
2705 2717 Returns 0 on success.
2706 2718 """
2707 2719 if search:
2708 2720 for name, path in ui.configitems("paths"):
2709 2721 if name == search:
2710 2722 ui.write("%s\n" % url.hidepassword(path))
2711 2723 return
2712 2724 ui.warn(_("not found!\n"))
2713 2725 return 1
2714 2726 else:
2715 2727 for name, path in ui.configitems("paths"):
2716 2728 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2717 2729
2718 2730 def postincoming(ui, repo, modheads, optupdate, checkout):
2719 2731 if modheads == 0:
2720 2732 return
2721 2733 if optupdate:
2722 2734 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2723 2735 return hg.update(repo, checkout)
2724 2736 else:
2725 2737 ui.status(_("not updating, since new heads added\n"))
2726 2738 if modheads > 1:
2727 2739 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2728 2740 else:
2729 2741 ui.status(_("(run 'hg update' to get a working copy)\n"))
2730 2742
2731 2743 def pull(ui, repo, source="default", **opts):
2732 2744 """pull changes from the specified source
2733 2745
2734 2746 Pull changes from a remote repository to a local one.
2735 2747
2736 2748 This finds all changes from the repository at the specified path
2737 2749 or URL and adds them to a local repository (the current one unless
2738 2750 -R is specified). By default, this does not update the copy of the
2739 2751 project in the working directory.
2740 2752
2741 2753 Use :hg:`incoming` if you want to see what would have been added
2742 2754 by a pull at the time you issued this command. If you then decide
2743 2755 to add those changes to the repository, you should use :hg:`pull
2744 2756 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2745 2757
2746 2758 If SOURCE is omitted, the 'default' path will be used.
2747 2759 See :hg:`help urls` for more information.
2748 2760
2749 2761 Returns 0 on success, 1 if an update had unresolved files.
2750 2762 """
2751 2763 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2752 2764 other = hg.repository(hg.remoteui(repo, opts), source)
2753 2765 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2754 2766 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2755 2767 if revs:
2756 2768 try:
2757 2769 revs = [other.lookup(rev) for rev in revs]
2758 2770 except error.CapabilityError:
2759 2771 err = _("other repository doesn't support revision lookup, "
2760 2772 "so a rev cannot be specified.")
2761 2773 raise util.Abort(err)
2762 2774
2763 2775 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2764 2776 if checkout:
2765 2777 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2766 2778 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2767 2779
2768 2780 def push(ui, repo, dest=None, **opts):
2769 2781 """push changes to the specified destination
2770 2782
2771 2783 Push changesets from the local repository to the specified
2772 2784 destination.
2773 2785
2774 2786 This operation is symmetrical to pull: it is identical to a pull
2775 2787 in the destination repository from the current one.
2776 2788
2777 2789 By default, push will not allow creation of new heads at the
2778 2790 destination, since multiple heads would make it unclear which head
2779 2791 to use. In this situation, it is recommended to pull and merge
2780 2792 before pushing.
2781 2793
2782 2794 Use --new-branch if you want to allow push to create a new named
2783 2795 branch that is not present at the destination. This allows you to
2784 2796 only create a new branch without forcing other changes.
2785 2797
2786 2798 Use -f/--force to override the default behavior and push all
2787 2799 changesets on all branches.
2788 2800
2789 2801 If -r/--rev is used, the specified revision and all its ancestors
2790 2802 will be pushed to the remote repository.
2791 2803
2792 2804 Please see :hg:`help urls` for important details about ``ssh://``
2793 2805 URLs. If DESTINATION is omitted, a default path will be used.
2794 2806
2795 2807 Returns 0 if push was successful, 1 if nothing to push.
2796 2808 """
2797 2809 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2798 2810 dest, branches = hg.parseurl(dest, opts.get('branch'))
2799 2811 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2800 2812 other = hg.repository(hg.remoteui(repo, opts), dest)
2801 2813 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2802 2814 if revs:
2803 2815 revs = [repo.lookup(rev) for rev in revs]
2804 2816
2805 2817 # push subrepos depth-first for coherent ordering
2806 2818 c = repo['']
2807 2819 subs = c.substate # only repos that are committed
2808 2820 for s in sorted(subs):
2809 2821 if not c.sub(s).push(opts.get('force')):
2810 2822 return False
2811 2823
2812 2824 r = repo.push(other, opts.get('force'), revs=revs,
2813 2825 newbranch=opts.get('new_branch'))
2814 2826 return r == 0
2815 2827
2816 2828 def recover(ui, repo):
2817 2829 """roll back an interrupted transaction
2818 2830
2819 2831 Recover from an interrupted commit or pull.
2820 2832
2821 2833 This command tries to fix the repository status after an
2822 2834 interrupted operation. It should only be necessary when Mercurial
2823 2835 suggests it.
2824 2836
2825 2837 Returns 0 if successful, 1 if nothing to recover or verify fails.
2826 2838 """
2827 2839 if repo.recover():
2828 2840 return hg.verify(repo)
2829 2841 return 1
2830 2842
2831 2843 def remove(ui, repo, *pats, **opts):
2832 2844 """remove the specified files on the next commit
2833 2845
2834 2846 Schedule the indicated files for removal from the repository.
2835 2847
2836 2848 This only removes files from the current branch, not from the
2837 2849 entire project history. -A/--after can be used to remove only
2838 2850 files that have already been deleted, -f/--force can be used to
2839 2851 force deletion, and -Af can be used to remove files from the next
2840 2852 revision without deleting them from the working directory.
2841 2853
2842 2854 The following table details the behavior of remove for different
2843 2855 file states (columns) and option combinations (rows). The file
2844 2856 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2845 2857 reported by :hg:`status`). The actions are Warn, Remove (from
2846 2858 branch) and Delete (from disk)::
2847 2859
2848 2860 A C M !
2849 2861 none W RD W R
2850 2862 -f R RD RD R
2851 2863 -A W W W R
2852 2864 -Af R R R R
2853 2865
2854 2866 This command schedules the files to be removed at the next commit.
2855 2867 To undo a remove before that, see :hg:`revert`.
2856 2868
2857 2869 Returns 0 on success, 1 if any warnings encountered.
2858 2870 """
2859 2871
2860 2872 ret = 0
2861 2873 after, force = opts.get('after'), opts.get('force')
2862 2874 if not pats and not after:
2863 2875 raise util.Abort(_('no files specified'))
2864 2876
2865 2877 m = cmdutil.match(repo, pats, opts)
2866 2878 s = repo.status(match=m, clean=True)
2867 2879 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2868 2880
2869 2881 for f in m.files():
2870 2882 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2871 2883 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2872 2884 ret = 1
2873 2885
2874 2886 if force:
2875 2887 remove, forget = modified + deleted + clean, added
2876 2888 elif after:
2877 2889 remove, forget = deleted, []
2878 2890 for f in modified + added + clean:
2879 2891 ui.warn(_('not removing %s: file still exists (use -f'
2880 2892 ' to force removal)\n') % m.rel(f))
2881 2893 ret = 1
2882 2894 else:
2883 2895 remove, forget = deleted + clean, []
2884 2896 for f in modified:
2885 2897 ui.warn(_('not removing %s: file is modified (use -f'
2886 2898 ' to force removal)\n') % m.rel(f))
2887 2899 ret = 1
2888 2900 for f in added:
2889 2901 ui.warn(_('not removing %s: file has been marked for add (use -f'
2890 2902 ' to force removal)\n') % m.rel(f))
2891 2903 ret = 1
2892 2904
2893 2905 for f in sorted(remove + forget):
2894 2906 if ui.verbose or not m.exact(f):
2895 2907 ui.status(_('removing %s\n') % m.rel(f))
2896 2908
2897 2909 repo[None].forget(forget)
2898 2910 repo[None].remove(remove, unlink=not after)
2899 2911 return ret
2900 2912
2901 2913 def rename(ui, repo, *pats, **opts):
2902 2914 """rename files; equivalent of copy + remove
2903 2915
2904 2916 Mark dest as copies of sources; mark sources for deletion. If dest
2905 2917 is a directory, copies are put in that directory. If dest is a
2906 2918 file, there can only be one source.
2907 2919
2908 2920 By default, this command copies the contents of files as they
2909 2921 exist in the working directory. If invoked with -A/--after, the
2910 2922 operation is recorded, but no copying is performed.
2911 2923
2912 2924 This command takes effect at the next commit. To undo a rename
2913 2925 before that, see :hg:`revert`.
2914 2926
2915 2927 Returns 0 on success, 1 if errors are encountered.
2916 2928 """
2917 2929 wlock = repo.wlock(False)
2918 2930 try:
2919 2931 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2920 2932 finally:
2921 2933 wlock.release()
2922 2934
2923 2935 def resolve(ui, repo, *pats, **opts):
2924 2936 """redo merges or set/view the merge status of files
2925 2937
2926 2938 Merges with unresolved conflicts are often the result of
2927 2939 non-interactive merging using the ``internal:merge`` configuration
2928 2940 setting, or a command-line merge tool like ``diff3``. The resolve
2929 2941 command is used to manage the files involved in a merge, after
2930 2942 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2931 2943 working directory must have two parents).
2932 2944
2933 2945 The resolve command can be used in the following ways:
2934 2946
2935 - :hg:`resolve FILE...`: attempt to re-merge the specified files,
2936 discarding any previous merge attempts. Re-merging is not
2947 - :hg:`resolve [--tool] FILE...`: attempt to re-merge the specified
2948 files, discarding any previous merge attempts. Re-merging is not
2937 2949 performed for files already marked as resolved. Use ``--all/-a``
2938 to selects all unresolved files.
2950 to selects all unresolved files. ``--tool`` can be used to specify
2951 the merge tool used for the given files. It overrides the HGMERGE
2952 environment variable and your configuration files.
2939 2953
2940 2954 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2941 2955 (e.g. after having manually fixed-up the files). The default is
2942 2956 to mark all unresolved files.
2943 2957
2944 2958 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2945 2959 default is to mark all resolved files.
2946 2960
2947 2961 - :hg:`resolve -l`: list files which had or still have conflicts.
2948 2962 In the printed list, ``U`` = unresolved and ``R`` = resolved.
2949 2963
2950 2964 Note that Mercurial will not let you commit files with unresolved
2951 2965 merge conflicts. You must use :hg:`resolve -m ...` before you can
2952 2966 commit after a conflicting merge.
2953 2967
2954 2968 Returns 0 on success, 1 if any files fail a resolve attempt.
2955 2969 """
2956 2970
2957 2971 all, mark, unmark, show, nostatus = \
2958 2972 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2959 2973
2960 2974 if (show and (mark or unmark)) or (mark and unmark):
2961 2975 raise util.Abort(_("too many options specified"))
2962 2976 if pats and all:
2963 2977 raise util.Abort(_("can't specify --all and patterns"))
2964 2978 if not (all or pats or show or mark or unmark):
2965 2979 raise util.Abort(_('no files or directories specified; '
2966 2980 'use --all to remerge all files'))
2967 2981
2982 t = opts.get('tool')
2983 if t:
2984 if 'HGMERGE' in os.environ:
2985 os.environ['HGMERGE'] = t
2986 ui.setconfig('ui', 'merge', t)
2987
2968 2988 ms = mergemod.mergestate(repo)
2969 2989 m = cmdutil.match(repo, pats, opts)
2970 2990 ret = 0
2971 2991
2972 2992 for f in ms:
2973 2993 if m(f):
2974 2994 if show:
2975 2995 if nostatus:
2976 2996 ui.write("%s\n" % f)
2977 2997 else:
2978 2998 ui.write("%s %s\n" % (ms[f].upper(), f),
2979 2999 label='resolve.' +
2980 3000 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2981 3001 elif mark:
2982 3002 ms.mark(f, "r")
2983 3003 elif unmark:
2984 3004 ms.mark(f, "u")
2985 3005 else:
2986 3006 wctx = repo[None]
2987 3007 mctx = wctx.parents()[-1]
2988 3008
2989 3009 # backup pre-resolve (merge uses .orig for its own purposes)
2990 3010 a = repo.wjoin(f)
2991 3011 util.copyfile(a, a + ".resolve")
2992 3012
2993 3013 # resolve file
2994 3014 if ms.resolve(f, wctx, mctx):
2995 3015 ret = 1
2996 3016
2997 3017 # replace filemerge's .orig file with our resolve file
2998 3018 util.rename(a + ".resolve", a + ".orig")
2999 3019
3000 3020 ms.commit()
3001 3021 return ret
3002 3022
3003 3023 def revert(ui, repo, *pats, **opts):
3004 3024 """restore individual files or directories to an earlier state
3005 3025
3006 3026 .. note::
3007 3027 This command is most likely not what you are looking for.
3008 3028 revert will partially overwrite content in the working
3009 3029 directory without changing the working directory parents. Use
3010 3030 :hg:`update -r rev` to check out earlier revisions, or
3011 3031 :hg:`update --clean .` to undo a merge which has added another
3012 3032 parent.
3013 3033
3014 3034 With no revision specified, revert the named files or directories
3015 3035 to the contents they had in the parent of the working directory.
3016 3036 This restores the contents of the affected files to an unmodified
3017 3037 state and unschedules adds, removes, copies, and renames. If the
3018 3038 working directory has two parents, you must explicitly specify a
3019 3039 revision.
3020 3040
3021 3041 Using the -r/--rev option, revert the given files or directories
3022 3042 to their contents as of a specific revision. This can be helpful
3023 3043 to "roll back" some or all of an earlier change. See :hg:`help
3024 3044 dates` for a list of formats valid for -d/--date.
3025 3045
3026 3046 Revert modifies the working directory. It does not commit any
3027 3047 changes, or change the parent of the working directory. If you
3028 3048 revert to a revision other than the parent of the working
3029 3049 directory, the reverted files will thus appear modified
3030 3050 afterwards.
3031 3051
3032 3052 If a file has been deleted, it is restored. If the executable mode
3033 3053 of a file was changed, it is reset.
3034 3054
3035 3055 If names are given, all files matching the names are reverted.
3036 3056 If no arguments are given, no files are reverted.
3037 3057
3038 3058 Modified files are saved with a .orig suffix before reverting.
3039 3059 To disable these backups, use --no-backup.
3040 3060
3041 3061 Returns 0 on success.
3042 3062 """
3043 3063
3044 3064 if opts.get("date"):
3045 3065 if opts.get("rev"):
3046 3066 raise util.Abort(_("you can't specify a revision and a date"))
3047 3067 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3048 3068
3049 3069 if not pats and not opts.get('all'):
3050 3070 raise util.Abort(_('no files or directories specified; '
3051 3071 'use --all to revert the whole repo'))
3052 3072
3053 3073 parent, p2 = repo.dirstate.parents()
3054 3074 if not opts.get('rev') and p2 != nullid:
3055 3075 raise util.Abort(_('uncommitted merge - please provide a '
3056 3076 'specific revision'))
3057 3077 ctx = repo[opts.get('rev')]
3058 3078 node = ctx.node()
3059 3079 mf = ctx.manifest()
3060 3080 if node == parent:
3061 3081 pmf = mf
3062 3082 else:
3063 3083 pmf = None
3064 3084
3065 3085 # need all matching names in dirstate and manifest of target rev,
3066 3086 # so have to walk both. do not print errors if files exist in one
3067 3087 # but not other.
3068 3088
3069 3089 names = {}
3070 3090
3071 3091 wlock = repo.wlock()
3072 3092 try:
3073 3093 # walk dirstate.
3074 3094
3075 3095 m = cmdutil.match(repo, pats, opts)
3076 3096 m.bad = lambda x, y: False
3077 3097 for abs in repo.walk(m):
3078 3098 names[abs] = m.rel(abs), m.exact(abs)
3079 3099
3080 3100 # walk target manifest.
3081 3101
3082 3102 def badfn(path, msg):
3083 3103 if path in names:
3084 3104 return
3085 3105 path_ = path + '/'
3086 3106 for f in names:
3087 3107 if f.startswith(path_):
3088 3108 return
3089 3109 ui.warn("%s: %s\n" % (m.rel(path), msg))
3090 3110
3091 3111 m = cmdutil.match(repo, pats, opts)
3092 3112 m.bad = badfn
3093 3113 for abs in repo[node].walk(m):
3094 3114 if abs not in names:
3095 3115 names[abs] = m.rel(abs), m.exact(abs)
3096 3116
3097 3117 m = cmdutil.matchfiles(repo, names)
3098 3118 changes = repo.status(match=m)[:4]
3099 3119 modified, added, removed, deleted = map(set, changes)
3100 3120
3101 3121 # if f is a rename, also revert the source
3102 3122 cwd = repo.getcwd()
3103 3123 for f in added:
3104 3124 src = repo.dirstate.copied(f)
3105 3125 if src and src not in names and repo.dirstate[src] == 'r':
3106 3126 removed.add(src)
3107 3127 names[src] = (repo.pathto(src, cwd), True)
3108 3128
3109 3129 def removeforget(abs):
3110 3130 if repo.dirstate[abs] == 'a':
3111 3131 return _('forgetting %s\n')
3112 3132 return _('removing %s\n')
3113 3133
3114 3134 revert = ([], _('reverting %s\n'))
3115 3135 add = ([], _('adding %s\n'))
3116 3136 remove = ([], removeforget)
3117 3137 undelete = ([], _('undeleting %s\n'))
3118 3138
3119 3139 disptable = (
3120 3140 # dispatch table:
3121 3141 # file state
3122 3142 # action if in target manifest
3123 3143 # action if not in target manifest
3124 3144 # make backup if in target manifest
3125 3145 # make backup if not in target manifest
3126 3146 (modified, revert, remove, True, True),
3127 3147 (added, revert, remove, True, False),
3128 3148 (removed, undelete, None, False, False),
3129 3149 (deleted, revert, remove, False, False),
3130 3150 )
3131 3151
3132 3152 for abs, (rel, exact) in sorted(names.items()):
3133 3153 mfentry = mf.get(abs)
3134 3154 target = repo.wjoin(abs)
3135 3155 def handle(xlist, dobackup):
3136 3156 xlist[0].append(abs)
3137 3157 if (dobackup and not opts.get('no_backup') and
3138 3158 os.path.lexists(target)):
3139 3159 bakname = "%s.orig" % rel
3140 3160 ui.note(_('saving current version of %s as %s\n') %
3141 3161 (rel, bakname))
3142 3162 if not opts.get('dry_run'):
3143 3163 util.rename(target, bakname)
3144 3164 if ui.verbose or not exact:
3145 3165 msg = xlist[1]
3146 3166 if not isinstance(msg, basestring):
3147 3167 msg = msg(abs)
3148 3168 ui.status(msg % rel)
3149 3169 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3150 3170 if abs not in table:
3151 3171 continue
3152 3172 # file has changed in dirstate
3153 3173 if mfentry:
3154 3174 handle(hitlist, backuphit)
3155 3175 elif misslist is not None:
3156 3176 handle(misslist, backupmiss)
3157 3177 break
3158 3178 else:
3159 3179 if abs not in repo.dirstate:
3160 3180 if mfentry:
3161 3181 handle(add, True)
3162 3182 elif exact:
3163 3183 ui.warn(_('file not managed: %s\n') % rel)
3164 3184 continue
3165 3185 # file has not changed in dirstate
3166 3186 if node == parent:
3167 3187 if exact:
3168 3188 ui.warn(_('no changes needed to %s\n') % rel)
3169 3189 continue
3170 3190 if pmf is None:
3171 3191 # only need parent manifest in this unlikely case,
3172 3192 # so do not read by default
3173 3193 pmf = repo[parent].manifest()
3174 3194 if abs in pmf:
3175 3195 if mfentry:
3176 3196 # if version of file is same in parent and target
3177 3197 # manifests, do nothing
3178 3198 if (pmf[abs] != mfentry or
3179 3199 pmf.flags(abs) != mf.flags(abs)):
3180 3200 handle(revert, False)
3181 3201 else:
3182 3202 handle(remove, False)
3183 3203
3184 3204 if not opts.get('dry_run'):
3185 3205 def checkout(f):
3186 3206 fc = ctx[f]
3187 3207 repo.wwrite(f, fc.data(), fc.flags())
3188 3208
3189 3209 audit_path = util.path_auditor(repo.root)
3190 3210 for f in remove[0]:
3191 3211 if repo.dirstate[f] == 'a':
3192 3212 repo.dirstate.forget(f)
3193 3213 continue
3194 3214 audit_path(f)
3195 3215 try:
3196 3216 util.unlink(repo.wjoin(f))
3197 3217 except OSError:
3198 3218 pass
3199 3219 repo.dirstate.remove(f)
3200 3220
3201 3221 normal = None
3202 3222 if node == parent:
3203 3223 # We're reverting to our parent. If possible, we'd like status
3204 3224 # to report the file as clean. We have to use normallookup for
3205 3225 # merges to avoid losing information about merged/dirty files.
3206 3226 if p2 != nullid:
3207 3227 normal = repo.dirstate.normallookup
3208 3228 else:
3209 3229 normal = repo.dirstate.normal
3210 3230 for f in revert[0]:
3211 3231 checkout(f)
3212 3232 if normal:
3213 3233 normal(f)
3214 3234
3215 3235 for f in add[0]:
3216 3236 checkout(f)
3217 3237 repo.dirstate.add(f)
3218 3238
3219 3239 normal = repo.dirstate.normallookup
3220 3240 if node == parent and p2 == nullid:
3221 3241 normal = repo.dirstate.normal
3222 3242 for f in undelete[0]:
3223 3243 checkout(f)
3224 3244 normal(f)
3225 3245
3226 3246 finally:
3227 3247 wlock.release()
3228 3248
3229 3249 def rollback(ui, repo, **opts):
3230 3250 """roll back the last transaction (dangerous)
3231 3251
3232 3252 This command should be used with care. There is only one level of
3233 3253 rollback, and there is no way to undo a rollback. It will also
3234 3254 restore the dirstate at the time of the last transaction, losing
3235 3255 any dirstate changes since that time. This command does not alter
3236 3256 the working directory.
3237 3257
3238 3258 Transactions are used to encapsulate the effects of all commands
3239 3259 that create new changesets or propagate existing changesets into a
3240 3260 repository. For example, the following commands are transactional,
3241 3261 and their effects can be rolled back:
3242 3262
3243 3263 - commit
3244 3264 - import
3245 3265 - pull
3246 3266 - push (with this repository as the destination)
3247 3267 - unbundle
3248 3268
3249 3269 This command is not intended for use on public repositories. Once
3250 3270 changes are visible for pull by other users, rolling a transaction
3251 3271 back locally is ineffective (someone else may already have pulled
3252 3272 the changes). Furthermore, a race is possible with readers of the
3253 3273 repository; for example an in-progress pull from the repository
3254 3274 may fail if a rollback is performed.
3255 3275
3256 3276 Returns 0 on success, 1 if no rollback data is available.
3257 3277 """
3258 3278 return repo.rollback(opts.get('dry_run'))
3259 3279
3260 3280 def root(ui, repo):
3261 3281 """print the root (top) of the current working directory
3262 3282
3263 3283 Print the root directory of the current repository.
3264 3284
3265 3285 Returns 0 on success.
3266 3286 """
3267 3287 ui.write(repo.root + "\n")
3268 3288
3269 3289 def serve(ui, repo, **opts):
3270 3290 """start stand-alone webserver
3271 3291
3272 3292 Start a local HTTP repository browser and pull server. You can use
3273 3293 this for ad-hoc sharing and browing of repositories. It is
3274 3294 recommended to use a real web server to serve a repository for
3275 3295 longer periods of time.
3276 3296
3277 3297 Please note that the server does not implement access control.
3278 3298 This means that, by default, anybody can read from the server and
3279 3299 nobody can write to it by default. Set the ``web.allow_push``
3280 3300 option to ``*`` to allow everybody to push to the server. You
3281 3301 should use a real web server if you need to authenticate users.
3282 3302
3283 3303 By default, the server logs accesses to stdout and errors to
3284 3304 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3285 3305 files.
3286 3306
3287 3307 To have the server choose a free port number to listen on, specify
3288 3308 a port number of 0; in this case, the server will print the port
3289 3309 number it uses.
3290 3310
3291 3311 Returns 0 on success.
3292 3312 """
3293 3313
3294 3314 if opts["stdio"]:
3295 3315 if repo is None:
3296 3316 raise error.RepoError(_("There is no Mercurial repository here"
3297 3317 " (.hg not found)"))
3298 3318 s = sshserver.sshserver(ui, repo)
3299 3319 s.serve_forever()
3300 3320
3301 3321 # this way we can check if something was given in the command-line
3302 3322 if opts.get('port'):
3303 3323 opts['port'] = util.getport(opts.get('port'))
3304 3324
3305 3325 baseui = repo and repo.baseui or ui
3306 3326 optlist = ("name templates style address port prefix ipv6"
3307 3327 " accesslog errorlog certificate encoding")
3308 3328 for o in optlist.split():
3309 3329 val = opts.get(o, '')
3310 3330 if val in (None, ''): # should check against default options instead
3311 3331 continue
3312 3332 baseui.setconfig("web", o, val)
3313 3333 if repo and repo.ui != baseui:
3314 3334 repo.ui.setconfig("web", o, val)
3315 3335
3316 3336 o = opts.get('web_conf') or opts.get('webdir_conf')
3317 3337 if not o:
3318 3338 if not repo:
3319 3339 raise error.RepoError(_("There is no Mercurial repository"
3320 3340 " here (.hg not found)"))
3321 3341 o = repo.root
3322 3342
3323 3343 app = hgweb.hgweb(o, baseui=ui)
3324 3344
3325 3345 class service(object):
3326 3346 def init(self):
3327 3347 util.set_signal_handler()
3328 3348 self.httpd = hgweb.server.create_server(ui, app)
3329 3349
3330 3350 if opts['port'] and not ui.verbose:
3331 3351 return
3332 3352
3333 3353 if self.httpd.prefix:
3334 3354 prefix = self.httpd.prefix.strip('/') + '/'
3335 3355 else:
3336 3356 prefix = ''
3337 3357
3338 3358 port = ':%d' % self.httpd.port
3339 3359 if port == ':80':
3340 3360 port = ''
3341 3361
3342 3362 bindaddr = self.httpd.addr
3343 3363 if bindaddr == '0.0.0.0':
3344 3364 bindaddr = '*'
3345 3365 elif ':' in bindaddr: # IPv6
3346 3366 bindaddr = '[%s]' % bindaddr
3347 3367
3348 3368 fqaddr = self.httpd.fqaddr
3349 3369 if ':' in fqaddr:
3350 3370 fqaddr = '[%s]' % fqaddr
3351 3371 if opts['port']:
3352 3372 write = ui.status
3353 3373 else:
3354 3374 write = ui.write
3355 3375 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3356 3376 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3357 3377
3358 3378 def run(self):
3359 3379 self.httpd.serve_forever()
3360 3380
3361 3381 service = service()
3362 3382
3363 3383 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3364 3384
3365 3385 def status(ui, repo, *pats, **opts):
3366 3386 """show changed files in the working directory
3367 3387
3368 3388 Show status of files in the repository. If names are given, only
3369 3389 files that match are shown. Files that are clean or ignored or
3370 3390 the source of a copy/move operation, are not listed unless
3371 3391 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3372 3392 Unless options described with "show only ..." are given, the
3373 3393 options -mardu are used.
3374 3394
3375 3395 Option -q/--quiet hides untracked (unknown and ignored) files
3376 3396 unless explicitly requested with -u/--unknown or -i/--ignored.
3377 3397
3378 3398 .. note::
3379 3399 status may appear to disagree with diff if permissions have
3380 3400 changed or a merge has occurred. The standard diff format does
3381 3401 not report permission changes and diff only reports changes
3382 3402 relative to one merge parent.
3383 3403
3384 3404 If one revision is given, it is used as the base revision.
3385 3405 If two revisions are given, the differences between them are
3386 3406 shown. The --change option can also be used as a shortcut to list
3387 3407 the changed files of a revision from its first parent.
3388 3408
3389 3409 The codes used to show the status of files are::
3390 3410
3391 3411 M = modified
3392 3412 A = added
3393 3413 R = removed
3394 3414 C = clean
3395 3415 ! = missing (deleted by non-hg command, but still tracked)
3396 3416 ? = not tracked
3397 3417 I = ignored
3398 3418 = origin of the previous file listed as A (added)
3399 3419
3400 3420 Returns 0 on success.
3401 3421 """
3402 3422
3403 3423 revs = opts.get('rev')
3404 3424 change = opts.get('change')
3405 3425
3406 3426 if revs and change:
3407 3427 msg = _('cannot specify --rev and --change at the same time')
3408 3428 raise util.Abort(msg)
3409 3429 elif change:
3410 3430 node2 = repo.lookup(change)
3411 3431 node1 = repo[node2].parents()[0].node()
3412 3432 else:
3413 3433 node1, node2 = cmdutil.revpair(repo, revs)
3414 3434
3415 3435 cwd = (pats and repo.getcwd()) or ''
3416 3436 end = opts.get('print0') and '\0' or '\n'
3417 3437 copy = {}
3418 3438 states = 'modified added removed deleted unknown ignored clean'.split()
3419 3439 show = [k for k in states if opts.get(k)]
3420 3440 if opts.get('all'):
3421 3441 show += ui.quiet and (states[:4] + ['clean']) or states
3422 3442 if not show:
3423 3443 show = ui.quiet and states[:4] or states[:5]
3424 3444
3425 3445 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3426 3446 'ignored' in show, 'clean' in show, 'unknown' in show,
3427 3447 opts.get('subrepos'))
3428 3448 changestates = zip(states, 'MAR!?IC', stat)
3429 3449
3430 3450 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3431 3451 ctxn = repo[nullid]
3432 3452 ctx1 = repo[node1]
3433 3453 ctx2 = repo[node2]
3434 3454 added = stat[1]
3435 3455 if node2 is None:
3436 3456 added = stat[0] + stat[1] # merged?
3437 3457
3438 3458 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3439 3459 if k in added:
3440 3460 copy[k] = v
3441 3461 elif v in added:
3442 3462 copy[v] = k
3443 3463
3444 3464 for state, char, files in changestates:
3445 3465 if state in show:
3446 3466 format = "%s %%s%s" % (char, end)
3447 3467 if opts.get('no_status'):
3448 3468 format = "%%s%s" % end
3449 3469
3450 3470 for f in files:
3451 3471 ui.write(format % repo.pathto(f, cwd),
3452 3472 label='status.' + state)
3453 3473 if f in copy:
3454 3474 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3455 3475 label='status.copied')
3456 3476
3457 3477 def summary(ui, repo, **opts):
3458 3478 """summarize working directory state
3459 3479
3460 3480 This generates a brief summary of the working directory state,
3461 3481 including parents, branch, commit status, and available updates.
3462 3482
3463 3483 With the --remote option, this will check the default paths for
3464 3484 incoming and outgoing changes. This can be time-consuming.
3465 3485
3466 3486 Returns 0 on success.
3467 3487 """
3468 3488
3469 3489 ctx = repo[None]
3470 3490 parents = ctx.parents()
3471 3491 pnode = parents[0].node()
3472 3492
3473 3493 for p in parents:
3474 3494 # label with log.changeset (instead of log.parent) since this
3475 3495 # shows a working directory parent *changeset*:
3476 3496 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3477 3497 label='log.changeset')
3478 3498 ui.write(' '.join(p.tags()), label='log.tag')
3479 3499 if p.rev() == -1:
3480 3500 if not len(repo):
3481 3501 ui.write(_(' (empty repository)'))
3482 3502 else:
3483 3503 ui.write(_(' (no revision checked out)'))
3484 3504 ui.write('\n')
3485 3505 if p.description():
3486 3506 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3487 3507 label='log.summary')
3488 3508
3489 3509 branch = ctx.branch()
3490 3510 bheads = repo.branchheads(branch)
3491 3511 m = _('branch: %s\n') % branch
3492 3512 if branch != 'default':
3493 3513 ui.write(m, label='log.branch')
3494 3514 else:
3495 3515 ui.status(m, label='log.branch')
3496 3516
3497 3517 st = list(repo.status(unknown=True))[:6]
3498 3518
3499 3519 c = repo.dirstate.copies()
3500 3520 copied, renamed = [], []
3501 3521 for d, s in c.iteritems():
3502 3522 if s in st[2]:
3503 3523 st[2].remove(s)
3504 3524 renamed.append(d)
3505 3525 else:
3506 3526 copied.append(d)
3507 3527 if d in st[1]:
3508 3528 st[1].remove(d)
3509 3529 st.insert(3, renamed)
3510 3530 st.insert(4, copied)
3511 3531
3512 3532 ms = mergemod.mergestate(repo)
3513 3533 st.append([f for f in ms if ms[f] == 'u'])
3514 3534
3515 3535 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3516 3536 st.append(subs)
3517 3537
3518 3538 labels = [ui.label(_('%d modified'), 'status.modified'),
3519 3539 ui.label(_('%d added'), 'status.added'),
3520 3540 ui.label(_('%d removed'), 'status.removed'),
3521 3541 ui.label(_('%d renamed'), 'status.copied'),
3522 3542 ui.label(_('%d copied'), 'status.copied'),
3523 3543 ui.label(_('%d deleted'), 'status.deleted'),
3524 3544 ui.label(_('%d unknown'), 'status.unknown'),
3525 3545 ui.label(_('%d ignored'), 'status.ignored'),
3526 3546 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3527 3547 ui.label(_('%d subrepos'), 'status.modified')]
3528 3548 t = []
3529 3549 for s, l in zip(st, labels):
3530 3550 if s:
3531 3551 t.append(l % len(s))
3532 3552
3533 3553 t = ', '.join(t)
3534 3554 cleanworkdir = False
3535 3555
3536 3556 if len(parents) > 1:
3537 3557 t += _(' (merge)')
3538 3558 elif branch != parents[0].branch():
3539 3559 t += _(' (new branch)')
3540 3560 elif (parents[0].extra().get('close') and
3541 3561 pnode in repo.branchheads(branch, closed=True)):
3542 3562 t += _(' (head closed)')
3543 3563 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3544 3564 t += _(' (clean)')
3545 3565 cleanworkdir = True
3546 3566 elif pnode not in bheads:
3547 3567 t += _(' (new branch head)')
3548 3568
3549 3569 if cleanworkdir:
3550 3570 ui.status(_('commit: %s\n') % t.strip())
3551 3571 else:
3552 3572 ui.write(_('commit: %s\n') % t.strip())
3553 3573
3554 3574 # all ancestors of branch heads - all ancestors of parent = new csets
3555 3575 new = [0] * len(repo)
3556 3576 cl = repo.changelog
3557 3577 for a in [cl.rev(n) for n in bheads]:
3558 3578 new[a] = 1
3559 3579 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3560 3580 new[a] = 1
3561 3581 for a in [p.rev() for p in parents]:
3562 3582 if a >= 0:
3563 3583 new[a] = 0
3564 3584 for a in cl.ancestors(*[p.rev() for p in parents]):
3565 3585 new[a] = 0
3566 3586 new = sum(new)
3567 3587
3568 3588 if new == 0:
3569 3589 ui.status(_('update: (current)\n'))
3570 3590 elif pnode not in bheads:
3571 3591 ui.write(_('update: %d new changesets (update)\n') % new)
3572 3592 else:
3573 3593 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3574 3594 (new, len(bheads)))
3575 3595
3576 3596 if opts.get('remote'):
3577 3597 t = []
3578 3598 source, branches = hg.parseurl(ui.expandpath('default'))
3579 3599 other = hg.repository(hg.remoteui(repo, {}), source)
3580 3600 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3581 3601 ui.debug('comparing with %s\n' % url.hidepassword(source))
3582 3602 repo.ui.pushbuffer()
3583 3603 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3584 3604 repo.ui.popbuffer()
3585 3605 if incoming:
3586 3606 t.append(_('1 or more incoming'))
3587 3607
3588 3608 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3589 3609 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3590 3610 other = hg.repository(hg.remoteui(repo, {}), dest)
3591 3611 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3592 3612 repo.ui.pushbuffer()
3593 3613 o = discovery.findoutgoing(repo, other)
3594 3614 repo.ui.popbuffer()
3595 3615 o = repo.changelog.nodesbetween(o, None)[0]
3596 3616 if o:
3597 3617 t.append(_('%d outgoing') % len(o))
3598 3618
3599 3619 if t:
3600 3620 ui.write(_('remote: %s\n') % (', '.join(t)))
3601 3621 else:
3602 3622 ui.status(_('remote: (synced)\n'))
3603 3623
3604 3624 def tag(ui, repo, name1, *names, **opts):
3605 3625 """add one or more tags for the current or given revision
3606 3626
3607 3627 Name a particular revision using <name>.
3608 3628
3609 3629 Tags are used to name particular revisions of the repository and are
3610 3630 very useful to compare different revisions, to go back to significant
3611 3631 earlier versions or to mark branch points as releases, etc.
3612 3632
3613 3633 If no revision is given, the parent of the working directory is
3614 3634 used, or tip if no revision is checked out.
3615 3635
3616 3636 To facilitate version control, distribution, and merging of tags,
3617 3637 they are stored as a file named ".hgtags" which is managed
3618 3638 similarly to other project files and can be hand-edited if
3619 3639 necessary. The file '.hg/localtags' is used for local tags (not
3620 3640 shared among repositories).
3621 3641
3622 3642 See :hg:`help dates` for a list of formats valid for -d/--date.
3623 3643
3624 3644 Since tag names have priority over branch names during revision
3625 3645 lookup, using an existing branch name as a tag name is discouraged.
3626 3646
3627 3647 Returns 0 on success.
3628 3648 """
3629 3649
3630 3650 rev_ = "."
3631 3651 names = [t.strip() for t in (name1,) + names]
3632 3652 if len(names) != len(set(names)):
3633 3653 raise util.Abort(_('tag names must be unique'))
3634 3654 for n in names:
3635 3655 if n in ['tip', '.', 'null']:
3636 3656 raise util.Abort(_('the name \'%s\' is reserved') % n)
3637 3657 if not n:
3638 3658 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3639 3659 if opts.get('rev') and opts.get('remove'):
3640 3660 raise util.Abort(_("--rev and --remove are incompatible"))
3641 3661 if opts.get('rev'):
3642 3662 rev_ = opts['rev']
3643 3663 message = opts.get('message')
3644 3664 if opts.get('remove'):
3645 3665 expectedtype = opts.get('local') and 'local' or 'global'
3646 3666 for n in names:
3647 3667 if not repo.tagtype(n):
3648 3668 raise util.Abort(_('tag \'%s\' does not exist') % n)
3649 3669 if repo.tagtype(n) != expectedtype:
3650 3670 if expectedtype == 'global':
3651 3671 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3652 3672 else:
3653 3673 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3654 3674 rev_ = nullid
3655 3675 if not message:
3656 3676 # we don't translate commit messages
3657 3677 message = 'Removed tag %s' % ', '.join(names)
3658 3678 elif not opts.get('force'):
3659 3679 for n in names:
3660 3680 if n in repo.tags():
3661 3681 raise util.Abort(_('tag \'%s\' already exists '
3662 3682 '(use -f to force)') % n)
3663 3683 if not rev_ and repo.dirstate.parents()[1] != nullid:
3664 3684 raise util.Abort(_('uncommitted merge - please provide a '
3665 3685 'specific revision'))
3666 3686 r = repo[rev_].node()
3667 3687
3668 3688 if not message:
3669 3689 # we don't translate commit messages
3670 3690 message = ('Added tag %s for changeset %s' %
3671 3691 (', '.join(names), short(r)))
3672 3692
3673 3693 date = opts.get('date')
3674 3694 if date:
3675 3695 date = util.parsedate(date)
3676 3696
3677 3697 if opts.get('edit'):
3678 3698 message = ui.edit(message, ui.username())
3679 3699
3680 3700 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3681 3701
3682 3702 def tags(ui, repo):
3683 3703 """list repository tags
3684 3704
3685 3705 This lists both regular and local tags. When the -v/--verbose
3686 3706 switch is used, a third column "local" is printed for local tags.
3687 3707
3688 3708 Returns 0 on success.
3689 3709 """
3690 3710
3691 3711 hexfunc = ui.debugflag and hex or short
3692 3712 tagtype = ""
3693 3713
3694 3714 for t, n in reversed(repo.tagslist()):
3695 3715 if ui.quiet:
3696 3716 ui.write("%s\n" % t)
3697 3717 continue
3698 3718
3699 3719 try:
3700 3720 hn = hexfunc(n)
3701 3721 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3702 3722 except error.LookupError:
3703 3723 r = " ?:%s" % hn
3704 3724 else:
3705 3725 spaces = " " * (30 - encoding.colwidth(t))
3706 3726 if ui.verbose:
3707 3727 if repo.tagtype(t) == 'local':
3708 3728 tagtype = " local"
3709 3729 else:
3710 3730 tagtype = ""
3711 3731 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3712 3732
3713 3733 def tip(ui, repo, **opts):
3714 3734 """show the tip revision
3715 3735
3716 3736 The tip revision (usually just called the tip) is the changeset
3717 3737 most recently added to the repository (and therefore the most
3718 3738 recently changed head).
3719 3739
3720 3740 If you have just made a commit, that commit will be the tip. If
3721 3741 you have just pulled changes from another repository, the tip of
3722 3742 that repository becomes the current tip. The "tip" tag is special
3723 3743 and cannot be renamed or assigned to a different changeset.
3724 3744
3725 3745 Returns 0 on success.
3726 3746 """
3727 3747 displayer = cmdutil.show_changeset(ui, repo, opts)
3728 3748 displayer.show(repo[len(repo) - 1])
3729 3749 displayer.close()
3730 3750
3731 3751 def unbundle(ui, repo, fname1, *fnames, **opts):
3732 3752 """apply one or more changegroup files
3733 3753
3734 3754 Apply one or more compressed changegroup files generated by the
3735 3755 bundle command.
3736 3756
3737 3757 Returns 0 on success, 1 if an update has unresolved files.
3738 3758 """
3739 3759 fnames = (fname1,) + fnames
3740 3760
3741 3761 lock = repo.lock()
3742 3762 try:
3743 3763 for fname in fnames:
3744 3764 f = url.open(ui, fname)
3745 3765 gen = changegroup.readbundle(f, fname)
3746 3766 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3747 3767 lock=lock)
3748 3768 finally:
3749 3769 lock.release()
3750 3770
3751 3771 return postincoming(ui, repo, modheads, opts.get('update'), None)
3752 3772
3753 3773 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3754 3774 """update working directory (or switch revisions)
3755 3775
3756 3776 Update the repository's working directory to the specified
3757 3777 changeset. If no changeset is specified, update to the tip of the
3758 3778 current named branch.
3759 3779
3760 3780 If the changeset is not a descendant of the working directory's
3761 3781 parent, the update is aborted. With the -c/--check option, the
3762 3782 working directory is checked for uncommitted changes; if none are
3763 3783 found, the working directory is updated to the specified
3764 3784 changeset.
3765 3785
3766 3786 The following rules apply when the working directory contains
3767 3787 uncommitted changes:
3768 3788
3769 3789 1. If neither -c/--check nor -C/--clean is specified, and if
3770 3790 the requested changeset is an ancestor or descendant of
3771 3791 the working directory's parent, the uncommitted changes
3772 3792 are merged into the requested changeset and the merged
3773 3793 result is left uncommitted. If the requested changeset is
3774 3794 not an ancestor or descendant (that is, it is on another
3775 3795 branch), the update is aborted and the uncommitted changes
3776 3796 are preserved.
3777 3797
3778 3798 2. With the -c/--check option, the update is aborted and the
3779 3799 uncommitted changes are preserved.
3780 3800
3781 3801 3. With the -C/--clean option, uncommitted changes are discarded and
3782 3802 the working directory is updated to the requested changeset.
3783 3803
3784 3804 Use null as the changeset to remove the working directory (like
3785 3805 :hg:`clone -U`).
3786 3806
3787 3807 If you want to update just one file to an older changeset, use
3788 3808 :hg:`revert`.
3789 3809
3790 3810 See :hg:`help dates` for a list of formats valid for -d/--date.
3791 3811
3792 3812 Returns 0 on success, 1 if there are unresolved files.
3793 3813 """
3794 3814 if rev and node:
3795 3815 raise util.Abort(_("please specify just one revision"))
3796 3816
3797 3817 if not rev:
3798 3818 rev = node
3799 3819
3800 3820 rev = cmdutil.revsingle(repo, rev, rev).rev()
3801 3821
3802 3822 if check and clean:
3803 3823 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3804 3824
3805 3825 if check:
3806 3826 # we could use dirty() but we can ignore merge and branch trivia
3807 3827 c = repo[None]
3808 3828 if c.modified() or c.added() or c.removed():
3809 3829 raise util.Abort(_("uncommitted local changes"))
3810 3830
3811 3831 if date:
3812 3832 if rev:
3813 3833 raise util.Abort(_("you can't specify a revision and a date"))
3814 3834 rev = cmdutil.finddate(ui, repo, date)
3815 3835
3816 3836 if clean or check:
3817 3837 return hg.clean(repo, rev)
3818 3838 else:
3819 3839 return hg.update(repo, rev)
3820 3840
3821 3841 def verify(ui, repo):
3822 3842 """verify the integrity of the repository
3823 3843
3824 3844 Verify the integrity of the current repository.
3825 3845
3826 3846 This will perform an extensive check of the repository's
3827 3847 integrity, validating the hashes and checksums of each entry in
3828 3848 the changelog, manifest, and tracked files, as well as the
3829 3849 integrity of their crosslinks and indices.
3830 3850
3831 3851 Returns 0 on success, 1 if errors are encountered.
3832 3852 """
3833 3853 return hg.verify(repo)
3834 3854
3835 3855 def version_(ui):
3836 3856 """output version and copyright information"""
3837 3857 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3838 3858 % util.version())
3839 3859 ui.status(_(
3840 3860 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3841 3861 "This is free software; see the source for copying conditions. "
3842 3862 "There is NO\nwarranty; "
3843 3863 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3844 3864 ))
3845 3865
3846 3866 # Command options and aliases are listed here, alphabetically
3847 3867
3848 3868 globalopts = [
3849 3869 ('R', 'repository', '',
3850 3870 _('repository root directory or name of overlay bundle file'),
3851 3871 _('REPO')),
3852 3872 ('', 'cwd', '',
3853 3873 _('change working directory'), _('DIR')),
3854 3874 ('y', 'noninteractive', None,
3855 3875 _('do not prompt, assume \'yes\' for any required answers')),
3856 3876 ('q', 'quiet', None, _('suppress output')),
3857 3877 ('v', 'verbose', None, _('enable additional output')),
3858 3878 ('', 'config', [],
3859 3879 _('set/override config option (use \'section.name=value\')'),
3860 3880 _('CONFIG')),
3861 3881 ('', 'debug', None, _('enable debugging output')),
3862 3882 ('', 'debugger', None, _('start debugger')),
3863 3883 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3864 3884 _('ENCODE')),
3865 3885 ('', 'encodingmode', encoding.encodingmode,
3866 3886 _('set the charset encoding mode'), _('MODE')),
3867 3887 ('', 'traceback', None, _('always print a traceback on exception')),
3868 3888 ('', 'time', None, _('time how long the command takes')),
3869 3889 ('', 'profile', None, _('print command execution profile')),
3870 3890 ('', 'version', None, _('output version information and exit')),
3871 3891 ('h', 'help', None, _('display help and exit')),
3872 3892 ]
3873 3893
3874 3894 dryrunopts = [('n', 'dry-run', None,
3875 3895 _('do not perform actions, just print output'))]
3876 3896
3877 3897 remoteopts = [
3878 3898 ('e', 'ssh', '',
3879 3899 _('specify ssh command to use'), _('CMD')),
3880 3900 ('', 'remotecmd', '',
3881 3901 _('specify hg command to run on the remote side'), _('CMD')),
3882 3902 ]
3883 3903
3884 3904 walkopts = [
3885 3905 ('I', 'include', [],
3886 3906 _('include names matching the given patterns'), _('PATTERN')),
3887 3907 ('X', 'exclude', [],
3888 3908 _('exclude names matching the given patterns'), _('PATTERN')),
3889 3909 ]
3890 3910
3891 3911 commitopts = [
3892 3912 ('m', 'message', '',
3893 3913 _('use text as commit message'), _('TEXT')),
3894 3914 ('l', 'logfile', '',
3895 3915 _('read commit message from file'), _('FILE')),
3896 3916 ]
3897 3917
3898 3918 commitopts2 = [
3899 3919 ('d', 'date', '',
3900 3920 _('record datecode as commit date'), _('DATE')),
3901 3921 ('u', 'user', '',
3902 3922 _('record the specified user as committer'), _('USER')),
3903 3923 ]
3904 3924
3905 3925 templateopts = [
3906 3926 ('', 'style', '',
3907 3927 _('display using template map file'), _('STYLE')),
3908 3928 ('', 'template', '',
3909 3929 _('display with template'), _('TEMPLATE')),
3910 3930 ]
3911 3931
3912 3932 logopts = [
3913 3933 ('p', 'patch', None, _('show patch')),
3914 3934 ('g', 'git', None, _('use git extended diff format')),
3915 3935 ('l', 'limit', '',
3916 3936 _('limit number of changes displayed'), _('NUM')),
3917 3937 ('M', 'no-merges', None, _('do not show merges')),
3918 3938 ('', 'stat', None, _('output diffstat-style summary of changes')),
3919 3939 ] + templateopts
3920 3940
3921 3941 diffopts = [
3922 3942 ('a', 'text', None, _('treat all files as text')),
3923 3943 ('g', 'git', None, _('use git extended diff format')),
3924 3944 ('', 'nodates', None, _('omit dates from diff headers'))
3925 3945 ]
3926 3946
3927 3947 diffopts2 = [
3928 3948 ('p', 'show-function', None, _('show which function each change is in')),
3929 3949 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3930 3950 ('w', 'ignore-all-space', None,
3931 3951 _('ignore white space when comparing lines')),
3932 3952 ('b', 'ignore-space-change', None,
3933 3953 _('ignore changes in the amount of white space')),
3934 3954 ('B', 'ignore-blank-lines', None,
3935 3955 _('ignore changes whose lines are all blank')),
3936 3956 ('U', 'unified', '',
3937 3957 _('number of lines of context to show'), _('NUM')),
3938 3958 ('', 'stat', None, _('output diffstat-style summary of changes')),
3939 3959 ]
3940 3960
3941 3961 similarityopts = [
3942 3962 ('s', 'similarity', '',
3943 3963 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
3944 3964 ]
3945 3965
3946 3966 subrepoopts = [
3947 3967 ('S', 'subrepos', None,
3948 3968 _('recurse into subrepositories'))
3949 3969 ]
3950 3970
3951 3971 table = {
3952 3972 "^add": (add, walkopts + subrepoopts + dryrunopts,
3953 3973 _('[OPTION]... [FILE]...')),
3954 3974 "addremove":
3955 3975 (addremove, similarityopts + walkopts + dryrunopts,
3956 3976 _('[OPTION]... [FILE]...')),
3957 3977 "^annotate|blame":
3958 3978 (annotate,
3959 3979 [('r', 'rev', '',
3960 3980 _('annotate the specified revision'), _('REV')),
3961 3981 ('', 'follow', None,
3962 3982 _('follow copies/renames and list the filename (DEPRECATED)')),
3963 3983 ('', 'no-follow', None, _("don't follow copies and renames")),
3964 3984 ('a', 'text', None, _('treat all files as text')),
3965 3985 ('u', 'user', None, _('list the author (long with -v)')),
3966 3986 ('f', 'file', None, _('list the filename')),
3967 3987 ('d', 'date', None, _('list the date (short with -q)')),
3968 3988 ('n', 'number', None, _('list the revision number (default)')),
3969 3989 ('c', 'changeset', None, _('list the changeset')),
3970 3990 ('l', 'line-number', None,
3971 3991 _('show line number at the first appearance'))
3972 3992 ] + walkopts,
3973 3993 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3974 3994 "archive":
3975 3995 (archive,
3976 3996 [('', 'no-decode', None, _('do not pass files through decoders')),
3977 3997 ('p', 'prefix', '',
3978 3998 _('directory prefix for files in archive'), _('PREFIX')),
3979 3999 ('r', 'rev', '',
3980 4000 _('revision to distribute'), _('REV')),
3981 4001 ('t', 'type', '',
3982 4002 _('type of distribution to create'), _('TYPE')),
3983 4003 ] + subrepoopts + walkopts,
3984 4004 _('[OPTION]... DEST')),
3985 4005 "backout":
3986 4006 (backout,
3987 4007 [('', 'merge', None,
3988 4008 _('merge with old dirstate parent after backout')),
3989 4009 ('', 'parent', '',
3990 4010 _('parent to choose when backing out merge'), _('REV')),
3991 4011 ('r', 'rev', '',
3992 4012 _('revision to backout'), _('REV')),
3993 4013 ] + walkopts + commitopts + commitopts2,
3994 4014 _('[OPTION]... [-r] REV')),
3995 4015 "bisect":
3996 4016 (bisect,
3997 4017 [('r', 'reset', False, _('reset bisect state')),
3998 4018 ('g', 'good', False, _('mark changeset good')),
3999 4019 ('b', 'bad', False, _('mark changeset bad')),
4000 4020 ('s', 'skip', False, _('skip testing changeset')),
4001 4021 ('c', 'command', '',
4002 4022 _('use command to check changeset state'), _('CMD')),
4003 4023 ('U', 'noupdate', False, _('do not update to target'))],
4004 4024 _("[-gbsr] [-U] [-c CMD] [REV]")),
4005 4025 "branch":
4006 4026 (branch,
4007 4027 [('f', 'force', None,
4008 4028 _('set branch name even if it shadows an existing branch')),
4009 4029 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4010 4030 _('[-fC] [NAME]')),
4011 4031 "branches":
4012 4032 (branches,
4013 4033 [('a', 'active', False,
4014 4034 _('show only branches that have unmerged heads')),
4015 4035 ('c', 'closed', False,
4016 4036 _('show normal and closed branches'))],
4017 4037 _('[-ac]')),
4018 4038 "bundle":
4019 4039 (bundle,
4020 4040 [('f', 'force', None,
4021 4041 _('run even when the destination is unrelated')),
4022 4042 ('r', 'rev', [],
4023 4043 _('a changeset intended to be added to the destination'),
4024 4044 _('REV')),
4025 4045 ('b', 'branch', [],
4026 4046 _('a specific branch you would like to bundle'),
4027 4047 _('BRANCH')),
4028 4048 ('', 'base', [],
4029 4049 _('a base changeset assumed to be available at the destination'),
4030 4050 _('REV')),
4031 4051 ('a', 'all', None, _('bundle all changesets in the repository')),
4032 4052 ('t', 'type', 'bzip2',
4033 4053 _('bundle compression type to use'), _('TYPE')),
4034 4054 ] + remoteopts,
4035 4055 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4036 4056 "cat":
4037 4057 (cat,
4038 4058 [('o', 'output', '',
4039 4059 _('print output to file with formatted name'), _('FORMAT')),
4040 4060 ('r', 'rev', '',
4041 4061 _('print the given revision'), _('REV')),
4042 4062 ('', 'decode', None, _('apply any matching decode filter')),
4043 4063 ] + walkopts,
4044 4064 _('[OPTION]... FILE...')),
4045 4065 "^clone":
4046 4066 (clone,
4047 4067 [('U', 'noupdate', None,
4048 4068 _('the clone will include an empty working copy (only a repository)')),
4049 4069 ('u', 'updaterev', '',
4050 4070 _('revision, tag or branch to check out'), _('REV')),
4051 4071 ('r', 'rev', [],
4052 4072 _('include the specified changeset'), _('REV')),
4053 4073 ('b', 'branch', [],
4054 4074 _('clone only the specified branch'), _('BRANCH')),
4055 4075 ('', 'pull', None, _('use pull protocol to copy metadata')),
4056 4076 ('', 'uncompressed', None,
4057 4077 _('use uncompressed transfer (fast over LAN)')),
4058 4078 ] + remoteopts,
4059 4079 _('[OPTION]... SOURCE [DEST]')),
4060 4080 "^commit|ci":
4061 4081 (commit,
4062 4082 [('A', 'addremove', None,
4063 4083 _('mark new/missing files as added/removed before committing')),
4064 4084 ('', 'close-branch', None,
4065 4085 _('mark a branch as closed, hiding it from the branch list')),
4066 4086 ] + walkopts + commitopts + commitopts2,
4067 4087 _('[OPTION]... [FILE]...')),
4068 4088 "copy|cp":
4069 4089 (copy,
4070 4090 [('A', 'after', None, _('record a copy that has already occurred')),
4071 4091 ('f', 'force', None,
4072 4092 _('forcibly copy over an existing managed file')),
4073 4093 ] + walkopts + dryrunopts,
4074 4094 _('[OPTION]... [SOURCE]... DEST')),
4075 4095 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4076 4096 "debugbuilddag":
4077 4097 (debugbuilddag,
4078 4098 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4079 4099 ('a', 'appended-file', None, _('add single file all revs append to')),
4080 4100 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4081 4101 ('n', 'new-file', None, _('add new file at each rev')),
4082 4102 ],
4083 4103 _('[OPTION]... TEXT')),
4084 4104 "debugcheckstate": (debugcheckstate, [], ''),
4085 4105 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4086 4106 "debugcomplete":
4087 4107 (debugcomplete,
4088 4108 [('o', 'options', None, _('show the command options'))],
4089 4109 _('[-o] CMD')),
4090 4110 "debugdag":
4091 4111 (debugdag,
4092 4112 [('t', 'tags', None, _('use tags as labels')),
4093 4113 ('b', 'branches', None, _('annotate with branch names')),
4094 4114 ('', 'dots', None, _('use dots for runs')),
4095 4115 ('s', 'spaces', None, _('separate elements by spaces')),
4096 4116 ],
4097 4117 _('[OPTION]... [FILE [REV]...]')),
4098 4118 "debugdate":
4099 4119 (debugdate,
4100 4120 [('e', 'extended', None, _('try extended date formats'))],
4101 4121 _('[-e] DATE [RANGE]')),
4102 4122 "debugdata": (debugdata, [], _('FILE REV')),
4103 4123 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4104 4124 "debugindex": (debugindex, [], _('FILE')),
4105 4125 "debugindexdot": (debugindexdot, [], _('FILE')),
4106 4126 "debuginstall": (debuginstall, [], ''),
4107 4127 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4108 4128 "debugrebuildstate":
4109 4129 (debugrebuildstate,
4110 4130 [('r', 'rev', '',
4111 4131 _('revision to rebuild to'), _('REV'))],
4112 4132 _('[-r REV] [REV]')),
4113 4133 "debugrename":
4114 4134 (debugrename,
4115 4135 [('r', 'rev', '',
4116 4136 _('revision to debug'), _('REV'))],
4117 4137 _('[-r REV] FILE')),
4118 4138 "debugrevspec":
4119 4139 (debugrevspec, [], ('REVSPEC')),
4120 4140 "debugsetparents":
4121 4141 (debugsetparents, [], _('REV1 [REV2]')),
4122 4142 "debugstate":
4123 4143 (debugstate,
4124 4144 [('', 'nodates', None, _('do not display the saved mtime'))],
4125 4145 _('[OPTION]...')),
4126 4146 "debugsub":
4127 4147 (debugsub,
4128 4148 [('r', 'rev', '',
4129 4149 _('revision to check'), _('REV'))],
4130 4150 _('[-r REV] [REV]')),
4131 4151 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4132 4152 "^diff":
4133 4153 (diff,
4134 4154 [('r', 'rev', [],
4135 4155 _('revision'), _('REV')),
4136 4156 ('c', 'change', '',
4137 4157 _('change made by revision'), _('REV'))
4138 4158 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4139 4159 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4140 4160 "^export":
4141 4161 (export,
4142 4162 [('o', 'output', '',
4143 4163 _('print output to file with formatted name'), _('FORMAT')),
4144 4164 ('', 'switch-parent', None, _('diff against the second parent')),
4145 4165 ('r', 'rev', [],
4146 4166 _('revisions to export'), _('REV')),
4147 4167 ] + diffopts,
4148 4168 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4149 4169 "^forget":
4150 4170 (forget,
4151 4171 [] + walkopts,
4152 4172 _('[OPTION]... FILE...')),
4153 4173 "grep":
4154 4174 (grep,
4155 4175 [('0', 'print0', None, _('end fields with NUL')),
4156 4176 ('', 'all', None, _('print all revisions that match')),
4157 4177 ('f', 'follow', None,
4158 4178 _('follow changeset history,'
4159 4179 ' or file history across copies and renames')),
4160 4180 ('i', 'ignore-case', None, _('ignore case when matching')),
4161 4181 ('l', 'files-with-matches', None,
4162 4182 _('print only filenames and revisions that match')),
4163 4183 ('n', 'line-number', None, _('print matching line numbers')),
4164 4184 ('r', 'rev', [],
4165 4185 _('only search files changed within revision range'), _('REV')),
4166 4186 ('u', 'user', None, _('list the author (long with -v)')),
4167 4187 ('d', 'date', None, _('list the date (short with -q)')),
4168 4188 ] + walkopts,
4169 4189 _('[OPTION]... PATTERN [FILE]...')),
4170 4190 "heads":
4171 4191 (heads,
4172 4192 [('r', 'rev', '',
4173 4193 _('show only heads which are descendants of STARTREV'),
4174 4194 _('STARTREV')),
4175 4195 ('t', 'topo', False, _('show topological heads only')),
4176 4196 ('a', 'active', False,
4177 4197 _('show active branchheads only (DEPRECATED)')),
4178 4198 ('c', 'closed', False,
4179 4199 _('show normal and closed branch heads')),
4180 4200 ] + templateopts,
4181 4201 _('[-ac] [-r STARTREV] [REV]...')),
4182 4202 "help": (help_, [], _('[TOPIC]')),
4183 4203 "identify|id":
4184 4204 (identify,
4185 4205 [('r', 'rev', '',
4186 4206 _('identify the specified revision'), _('REV')),
4187 4207 ('n', 'num', None, _('show local revision number')),
4188 4208 ('i', 'id', None, _('show global revision id')),
4189 4209 ('b', 'branch', None, _('show branch')),
4190 4210 ('t', 'tags', None, _('show tags'))],
4191 4211 _('[-nibt] [-r REV] [SOURCE]')),
4192 4212 "import|patch":
4193 4213 (import_,
4194 4214 [('p', 'strip', 1,
4195 4215 _('directory strip option for patch. This has the same '
4196 4216 'meaning as the corresponding patch option'),
4197 4217 _('NUM')),
4198 4218 ('b', 'base', '',
4199 4219 _('base path'), _('PATH')),
4200 4220 ('f', 'force', None,
4201 4221 _('skip check for outstanding uncommitted changes')),
4202 4222 ('', 'no-commit', None,
4203 4223 _("don't commit, just update the working directory")),
4204 4224 ('', 'exact', None,
4205 4225 _('apply patch to the nodes from which it was generated')),
4206 4226 ('', 'import-branch', None,
4207 4227 _('use any branch information in patch (implied by --exact)'))] +
4208 4228 commitopts + commitopts2 + similarityopts,
4209 4229 _('[OPTION]... PATCH...')),
4210 4230 "incoming|in":
4211 4231 (incoming,
4212 4232 [('f', 'force', None,
4213 4233 _('run even if remote repository is unrelated')),
4214 4234 ('n', 'newest-first', None, _('show newest record first')),
4215 4235 ('', 'bundle', '',
4216 4236 _('file to store the bundles into'), _('FILE')),
4217 4237 ('r', 'rev', [],
4218 4238 _('a remote changeset intended to be added'), _('REV')),
4219 4239 ('b', 'branch', [],
4220 4240 _('a specific branch you would like to pull'), _('BRANCH')),
4221 4241 ] + logopts + remoteopts + subrepoopts,
4222 4242 _('[-p] [-n] [-M] [-f] [-r REV]...'
4223 4243 ' [--bundle FILENAME] [SOURCE]')),
4224 4244 "^init":
4225 4245 (init,
4226 4246 remoteopts,
4227 4247 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4228 4248 "locate":
4229 4249 (locate,
4230 4250 [('r', 'rev', '',
4231 4251 _('search the repository as it is in REV'), _('REV')),
4232 4252 ('0', 'print0', None,
4233 4253 _('end filenames with NUL, for use with xargs')),
4234 4254 ('f', 'fullpath', None,
4235 4255 _('print complete paths from the filesystem root')),
4236 4256 ] + walkopts,
4237 4257 _('[OPTION]... [PATTERN]...')),
4238 4258 "^log|history":
4239 4259 (log,
4240 4260 [('f', 'follow', None,
4241 4261 _('follow changeset history,'
4242 4262 ' or file history across copies and renames')),
4243 4263 ('', 'follow-first', None,
4244 4264 _('only follow the first parent of merge changesets')),
4245 4265 ('d', 'date', '',
4246 4266 _('show revisions matching date spec'), _('DATE')),
4247 4267 ('C', 'copies', None, _('show copied files')),
4248 4268 ('k', 'keyword', [],
4249 4269 _('do case-insensitive search for a given text'), _('TEXT')),
4250 4270 ('r', 'rev', [],
4251 4271 _('show the specified revision or range'), _('REV')),
4252 4272 ('', 'removed', None, _('include revisions where files were removed')),
4253 4273 ('m', 'only-merges', None, _('show only merges')),
4254 4274 ('u', 'user', [],
4255 4275 _('revisions committed by user'), _('USER')),
4256 4276 ('', 'only-branch', [],
4257 4277 _('show only changesets within the given named branch (DEPRECATED)'),
4258 4278 _('BRANCH')),
4259 4279 ('b', 'branch', [],
4260 4280 _('show changesets within the given named branch'), _('BRANCH')),
4261 4281 ('P', 'prune', [],
4262 4282 _('do not display revision or any of its ancestors'), _('REV')),
4263 4283 ] + logopts + walkopts,
4264 4284 _('[OPTION]... [FILE]')),
4265 4285 "manifest":
4266 4286 (manifest,
4267 4287 [('r', 'rev', '',
4268 4288 _('revision to display'), _('REV'))],
4269 4289 _('[-r REV]')),
4270 4290 "^merge":
4271 4291 (merge,
4272 4292 [('f', 'force', None, _('force a merge with outstanding changes')),
4293 ('t', 'tool', '', _('specify merge tool')),
4273 4294 ('r', 'rev', '',
4274 4295 _('revision to merge'), _('REV')),
4275 4296 ('P', 'preview', None,
4276 4297 _('review revisions to merge (no merge is performed)'))],
4277 4298 _('[-P] [-f] [[-r] REV]')),
4278 4299 "outgoing|out":
4279 4300 (outgoing,
4280 4301 [('f', 'force', None,
4281 4302 _('run even when the destination is unrelated')),
4282 4303 ('r', 'rev', [],
4283 4304 _('a changeset intended to be included in the destination'),
4284 4305 _('REV')),
4285 4306 ('n', 'newest-first', None, _('show newest record first')),
4286 4307 ('b', 'branch', [],
4287 4308 _('a specific branch you would like to push'), _('BRANCH')),
4288 4309 ] + logopts + remoteopts + subrepoopts,
4289 4310 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4290 4311 "parents":
4291 4312 (parents,
4292 4313 [('r', 'rev', '',
4293 4314 _('show parents of the specified revision'), _('REV')),
4294 4315 ] + templateopts,
4295 4316 _('[-r REV] [FILE]')),
4296 4317 "paths": (paths, [], _('[NAME]')),
4297 4318 "^pull":
4298 4319 (pull,
4299 4320 [('u', 'update', None,
4300 4321 _('update to new branch head if changesets were pulled')),
4301 4322 ('f', 'force', None,
4302 4323 _('run even when remote repository is unrelated')),
4303 4324 ('r', 'rev', [],
4304 4325 _('a remote changeset intended to be added'), _('REV')),
4305 4326 ('b', 'branch', [],
4306 4327 _('a specific branch you would like to pull'), _('BRANCH')),
4307 4328 ] + remoteopts,
4308 4329 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4309 4330 "^push":
4310 4331 (push,
4311 4332 [('f', 'force', None, _('force push')),
4312 4333 ('r', 'rev', [],
4313 4334 _('a changeset intended to be included in the destination'),
4314 4335 _('REV')),
4315 4336 ('b', 'branch', [],
4316 4337 _('a specific branch you would like to push'), _('BRANCH')),
4317 4338 ('', 'new-branch', False, _('allow pushing a new branch')),
4318 4339 ] + remoteopts,
4319 4340 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4320 4341 "recover": (recover, []),
4321 4342 "^remove|rm":
4322 4343 (remove,
4323 4344 [('A', 'after', None, _('record delete for missing files')),
4324 4345 ('f', 'force', None,
4325 4346 _('remove (and delete) file even if added or modified')),
4326 4347 ] + walkopts,
4327 4348 _('[OPTION]... FILE...')),
4328 4349 "rename|move|mv":
4329 4350 (rename,
4330 4351 [('A', 'after', None, _('record a rename that has already occurred')),
4331 4352 ('f', 'force', None,
4332 4353 _('forcibly copy over an existing managed file')),
4333 4354 ] + walkopts + dryrunopts,
4334 4355 _('[OPTION]... SOURCE... DEST')),
4335 4356 "resolve":
4336 4357 (resolve,
4337 4358 [('a', 'all', None, _('select all unresolved files')),
4338 4359 ('l', 'list', None, _('list state of files needing merge')),
4339 4360 ('m', 'mark', None, _('mark files as resolved')),
4340 4361 ('u', 'unmark', None, _('mark files as unresolved')),
4362 ('t', 'tool', '', _('specify merge tool')),
4341 4363 ('n', 'no-status', None, _('hide status prefix'))]
4342 4364 + walkopts,
4343 4365 _('[OPTION]... [FILE]...')),
4344 4366 "revert":
4345 4367 (revert,
4346 4368 [('a', 'all', None, _('revert all changes when no arguments given')),
4347 4369 ('d', 'date', '',
4348 4370 _('tipmost revision matching date'), _('DATE')),
4349 4371 ('r', 'rev', '',
4350 4372 _('revert to the specified revision'), _('REV')),
4351 4373 ('', 'no-backup', None, _('do not save backup copies of files')),
4352 4374 ] + walkopts + dryrunopts,
4353 4375 _('[OPTION]... [-r REV] [NAME]...')),
4354 4376 "rollback": (rollback, dryrunopts),
4355 4377 "root": (root, []),
4356 4378 "^serve":
4357 4379 (serve,
4358 4380 [('A', 'accesslog', '',
4359 4381 _('name of access log file to write to'), _('FILE')),
4360 4382 ('d', 'daemon', None, _('run server in background')),
4361 4383 ('', 'daemon-pipefds', '',
4362 4384 _('used internally by daemon mode'), _('NUM')),
4363 4385 ('E', 'errorlog', '',
4364 4386 _('name of error log file to write to'), _('FILE')),
4365 4387 # use string type, then we can check if something was passed
4366 4388 ('p', 'port', '',
4367 4389 _('port to listen on (default: 8000)'), _('PORT')),
4368 4390 ('a', 'address', '',
4369 4391 _('address to listen on (default: all interfaces)'), _('ADDR')),
4370 4392 ('', 'prefix', '',
4371 4393 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4372 4394 ('n', 'name', '',
4373 4395 _('name to show in web pages (default: working directory)'),
4374 4396 _('NAME')),
4375 4397 ('', 'web-conf', '',
4376 4398 _('name of the hgweb config file (see "hg help hgweb")'),
4377 4399 _('FILE')),
4378 4400 ('', 'webdir-conf', '',
4379 4401 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4380 4402 ('', 'pid-file', '',
4381 4403 _('name of file to write process ID to'), _('FILE')),
4382 4404 ('', 'stdio', None, _('for remote clients')),
4383 4405 ('t', 'templates', '',
4384 4406 _('web templates to use'), _('TEMPLATE')),
4385 4407 ('', 'style', '',
4386 4408 _('template style to use'), _('STYLE')),
4387 4409 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4388 4410 ('', 'certificate', '',
4389 4411 _('SSL certificate file'), _('FILE'))],
4390 4412 _('[OPTION]...')),
4391 4413 "showconfig|debugconfig":
4392 4414 (showconfig,
4393 4415 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4394 4416 _('[-u] [NAME]...')),
4395 4417 "^summary|sum":
4396 4418 (summary,
4397 4419 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4398 4420 "^status|st":
4399 4421 (status,
4400 4422 [('A', 'all', None, _('show status of all files')),
4401 4423 ('m', 'modified', None, _('show only modified files')),
4402 4424 ('a', 'added', None, _('show only added files')),
4403 4425 ('r', 'removed', None, _('show only removed files')),
4404 4426 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4405 4427 ('c', 'clean', None, _('show only files without changes')),
4406 4428 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4407 4429 ('i', 'ignored', None, _('show only ignored files')),
4408 4430 ('n', 'no-status', None, _('hide status prefix')),
4409 4431 ('C', 'copies', None, _('show source of copied files')),
4410 4432 ('0', 'print0', None,
4411 4433 _('end filenames with NUL, for use with xargs')),
4412 4434 ('', 'rev', [],
4413 4435 _('show difference from revision'), _('REV')),
4414 4436 ('', 'change', '',
4415 4437 _('list the changed files of a revision'), _('REV')),
4416 4438 ] + walkopts + subrepoopts,
4417 4439 _('[OPTION]... [FILE]...')),
4418 4440 "tag":
4419 4441 (tag,
4420 4442 [('f', 'force', None, _('replace existing tag')),
4421 4443 ('l', 'local', None, _('make the tag local')),
4422 4444 ('r', 'rev', '',
4423 4445 _('revision to tag'), _('REV')),
4424 4446 ('', 'remove', None, _('remove a tag')),
4425 4447 # -l/--local is already there, commitopts cannot be used
4426 4448 ('e', 'edit', None, _('edit commit message')),
4427 4449 ('m', 'message', '',
4428 4450 _('use <text> as commit message'), _('TEXT')),
4429 4451 ] + commitopts2,
4430 4452 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4431 4453 "tags": (tags, [], ''),
4432 4454 "tip":
4433 4455 (tip,
4434 4456 [('p', 'patch', None, _('show patch')),
4435 4457 ('g', 'git', None, _('use git extended diff format')),
4436 4458 ] + templateopts,
4437 4459 _('[-p] [-g]')),
4438 4460 "unbundle":
4439 4461 (unbundle,
4440 4462 [('u', 'update', None,
4441 4463 _('update to new branch head if changesets were unbundled'))],
4442 4464 _('[-u] FILE...')),
4443 4465 "^update|up|checkout|co":
4444 4466 (update,
4445 4467 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4446 4468 ('c', 'check', None,
4447 4469 _('update across branches if no uncommitted changes')),
4448 4470 ('d', 'date', '',
4449 4471 _('tipmost revision matching date'), _('DATE')),
4450 4472 ('r', 'rev', '',
4451 4473 _('revision'), _('REV'))],
4452 4474 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4453 4475 "verify": (verify, []),
4454 4476 "version": (version_, []),
4455 4477 }
4456 4478
4457 4479 norepo = ("clone init version help debugcommands debugcomplete"
4458 4480 " debugdate debuginstall debugfsinfo debugpushkey")
4459 4481 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4460 4482 " debugdata debugindex debugindexdot")
@@ -1,249 +1,249 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 branch
10 10 branches
11 11 bundle
12 12 cat
13 13 clone
14 14 commit
15 15 copy
16 16 diff
17 17 export
18 18 forget
19 19 grep
20 20 heads
21 21 help
22 22 identify
23 23 import
24 24 incoming
25 25 init
26 26 locate
27 27 log
28 28 manifest
29 29 merge
30 30 outgoing
31 31 parents
32 32 paths
33 33 pull
34 34 push
35 35 recover
36 36 remove
37 37 rename
38 38 resolve
39 39 revert
40 40 rollback
41 41 root
42 42 serve
43 43 showconfig
44 44 status
45 45 summary
46 46 tag
47 47 tags
48 48 tip
49 49 unbundle
50 50 update
51 51 verify
52 52 version
53 53
54 54 Show all commands that start with "a"
55 55 $ hg debugcomplete a
56 56 add
57 57 addremove
58 58 annotate
59 59 archive
60 60
61 61 Do not show debug commands if there are other candidates
62 62 $ hg debugcomplete d
63 63 diff
64 64
65 65 Show debug commands if there are no other candidates
66 66 $ hg debugcomplete debug
67 67 debugancestor
68 68 debugbuilddag
69 69 debugcheckstate
70 70 debugcommands
71 71 debugcomplete
72 72 debugconfig
73 73 debugdag
74 74 debugdata
75 75 debugdate
76 76 debugfsinfo
77 77 debugindex
78 78 debugindexdot
79 79 debuginstall
80 80 debugpushkey
81 81 debugrebuildstate
82 82 debugrename
83 83 debugrevspec
84 84 debugsetparents
85 85 debugstate
86 86 debugsub
87 87 debugwalk
88 88
89 89 Do not show the alias of a debug command if there are other candidates
90 90 (this should hide rawcommit)
91 91 $ hg debugcomplete r
92 92 recover
93 93 remove
94 94 rename
95 95 resolve
96 96 revert
97 97 rollback
98 98 root
99 99 Show the alias of a debug command if there are no other candidates
100 100 $ hg debugcomplete rawc
101 101
102 102
103 103 Show the global options
104 104 $ hg debugcomplete --options | sort
105 105 --config
106 106 --cwd
107 107 --debug
108 108 --debugger
109 109 --encoding
110 110 --encodingmode
111 111 --help
112 112 --noninteractive
113 113 --profile
114 114 --quiet
115 115 --repository
116 116 --time
117 117 --traceback
118 118 --verbose
119 119 --version
120 120 -R
121 121 -h
122 122 -q
123 123 -v
124 124 -y
125 125
126 126 Show the options for the "serve" command
127 127 $ hg debugcomplete --options serve | sort
128 128 --accesslog
129 129 --address
130 130 --certificate
131 131 --config
132 132 --cwd
133 133 --daemon
134 134 --daemon-pipefds
135 135 --debug
136 136 --debugger
137 137 --encoding
138 138 --encodingmode
139 139 --errorlog
140 140 --help
141 141 --ipv6
142 142 --name
143 143 --noninteractive
144 144 --pid-file
145 145 --port
146 146 --prefix
147 147 --profile
148 148 --quiet
149 149 --repository
150 150 --stdio
151 151 --style
152 152 --templates
153 153 --time
154 154 --traceback
155 155 --verbose
156 156 --version
157 157 --web-conf
158 158 -6
159 159 -A
160 160 -E
161 161 -R
162 162 -a
163 163 -d
164 164 -h
165 165 -n
166 166 -p
167 167 -q
168 168 -t
169 169 -v
170 170 -y
171 171
172 172 Show an error if we use --options with an ambiguous abbreviation
173 173 $ hg debugcomplete --options s
174 174 hg: command 's' is ambiguous:
175 175 serve showconfig status summary
176 176 [255]
177 177
178 178 Show all commands + options
179 179 $ hg debugcommands
180 180 add: include, exclude, subrepos, dry-run
181 181 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
182 182 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
183 183 commit: addremove, close-branch, include, exclude, message, logfile, date, user
184 184 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
185 185 export: output, switch-parent, rev, text, git, nodates
186 186 forget: include, exclude
187 187 init: ssh, remotecmd
188 188 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
189 merge: force, rev, preview
189 merge: force, tool, rev, preview
190 190 pull: update, force, rev, branch, ssh, remotecmd
191 191 push: force, rev, branch, new-branch, ssh, remotecmd
192 192 remove: after, force, include, exclude
193 193 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
194 194 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
195 195 summary: remote
196 196 update: clean, check, date, rev
197 197 addremove: similarity, include, exclude, dry-run
198 198 archive: no-decode, prefix, rev, type, subrepos, include, exclude
199 199 backout: merge, parent, rev, include, exclude, message, logfile, date, user
200 200 bisect: reset, good, bad, skip, command, noupdate
201 201 branch: force, clean
202 202 branches: active, closed
203 203 bundle: force, rev, branch, base, all, type, ssh, remotecmd
204 204 cat: output, rev, decode, include, exclude
205 205 copy: after, force, include, exclude, dry-run
206 206 debugancestor:
207 207 debugbuilddag: mergeable-file, appended-file, overwritten-file, new-file
208 208 debugcheckstate:
209 209 debugcommands:
210 210 debugcomplete: options
211 211 debugdag: tags, branches, dots, spaces
212 212 debugdata:
213 213 debugdate: extended
214 214 debugfsinfo:
215 215 debugindex:
216 216 debugindexdot:
217 217 debuginstall:
218 218 debugpushkey:
219 219 debugrebuildstate: rev
220 220 debugrename: rev
221 221 debugrevspec:
222 222 debugsetparents:
223 223 debugstate: nodates
224 224 debugsub: rev
225 225 debugwalk: include, exclude
226 226 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
227 227 heads: rev, topo, active, closed, style, template
228 228 help:
229 229 identify: rev, num, id, branch, tags
230 230 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
231 231 incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, subrepos
232 232 locate: rev, print0, fullpath, include, exclude
233 233 manifest: rev
234 234 outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, subrepos
235 235 parents: rev, style, template
236 236 paths:
237 237 recover:
238 238 rename: after, force, include, exclude, dry-run
239 resolve: all, list, mark, unmark, no-status, include, exclude
239 resolve: all, list, mark, unmark, tool, no-status, include, exclude
240 240 revert: all, date, rev, no-backup, include, exclude, dry-run
241 241 rollback: dry-run
242 242 root:
243 243 showconfig: untrusted
244 244 tag: force, local, rev, remove, edit, message, date, user
245 245 tags:
246 246 tip: patch, git, style, template
247 247 unbundle: update
248 248 verify:
249 249 version:
General Comments 0
You need to be logged in to leave comments. Login now