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