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