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