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