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