##// END OF EJS Templates
add note about updating one file to update help
Dirkjan Ochtman -
r6842:e37fa751 default
parent child Browse files
Show More
@@ -1,3271 +1,3273 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 repository heads.
375 375
376 376 Use the command 'hg update' to switch to an existing branch.
377 377 """
378 378 hexfunc = ui.debugflag and hex or short
379 379 activebranches = [util.tolocal(repo.changectx(n).branch())
380 380 for n in repo.heads()]
381 381 branches = [(tag in activebranches, repo.changelog.rev(node), tag)
382 382 for tag, node in repo.branchtags().items()]
383 383 branches.sort()
384 384 branches.reverse()
385 385
386 386 for isactive, node, tag in branches:
387 387 if (not active) or isactive:
388 388 if ui.quiet:
389 389 ui.write("%s\n" % tag)
390 390 else:
391 391 rev = str(node).rjust(31 - util.locallen(tag))
392 392 isinactive = ((not isactive) and " (inactive)") or ''
393 393 data = tag, rev, hexfunc(repo.lookup(node)), isinactive
394 394 ui.write("%s %s:%s%s\n" % data)
395 395
396 396 def bundle(ui, repo, fname, dest=None, **opts):
397 397 """create a changegroup file
398 398
399 399 Generate a compressed changegroup file collecting changesets not
400 400 found in the other repository.
401 401
402 402 If no destination repository is specified the destination is
403 403 assumed to have all the nodes specified by one or more --base
404 404 parameters. To create a bundle containing all changesets, use
405 405 --all (or --base null).
406 406
407 407 The bundle file can then be transferred using conventional means and
408 408 applied to another repository with the unbundle or pull command.
409 409 This is useful when direct push and pull are not available or when
410 410 exporting an entire repository is undesirable.
411 411
412 412 Applying bundles preserves all changeset contents including
413 413 permissions, copy/rename information, and revision history.
414 414 """
415 415 revs = opts.get('rev') or None
416 416 if revs:
417 417 revs = [repo.lookup(rev) for rev in revs]
418 418 if opts.get('all'):
419 419 base = ['null']
420 420 else:
421 421 base = opts.get('base')
422 422 if base:
423 423 if dest:
424 424 raise util.Abort(_("--base is incompatible with specifiying "
425 425 "a destination"))
426 426 base = [repo.lookup(rev) for rev in base]
427 427 # create the right base
428 428 # XXX: nodesbetween / changegroup* should be "fixed" instead
429 429 o = []
430 430 has = {nullid: None}
431 431 for n in base:
432 432 has.update(repo.changelog.reachable(n))
433 433 if revs:
434 434 visit = list(revs)
435 435 else:
436 436 visit = repo.changelog.heads()
437 437 seen = {}
438 438 while visit:
439 439 n = visit.pop(0)
440 440 parents = [p for p in repo.changelog.parents(n) if p not in has]
441 441 if len(parents) == 0:
442 442 o.insert(0, n)
443 443 else:
444 444 for p in parents:
445 445 if p not in seen:
446 446 seen[p] = 1
447 447 visit.append(p)
448 448 else:
449 449 cmdutil.setremoteconfig(ui, opts)
450 450 dest, revs, checkout = hg.parseurl(
451 451 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
452 452 other = hg.repository(ui, dest)
453 453 o = repo.findoutgoing(other, force=opts['force'])
454 454
455 455 if revs:
456 456 cg = repo.changegroupsubset(o, revs, 'bundle')
457 457 else:
458 458 cg = repo.changegroup(o, 'bundle')
459 459 changegroup.writebundle(cg, fname, "HG10BZ")
460 460
461 461 def cat(ui, repo, file1, *pats, **opts):
462 462 """output the current or given revision of files
463 463
464 464 Print the specified files as they were at the given revision.
465 465 If no revision is given, the parent of the working directory is used,
466 466 or tip if no revision is checked out.
467 467
468 468 Output may be to a file, in which case the name of the file is
469 469 given using a format string. The formatting rules are the same as
470 470 for the export command, with the following additions:
471 471
472 472 %s basename of file being printed
473 473 %d dirname of file being printed, or '.' if in repo root
474 474 %p root-relative path name of file being printed
475 475 """
476 476 ctx = repo.changectx(opts['rev'])
477 477 err = 1
478 478 for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
479 479 ctx.node()):
480 480 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
481 481 data = ctx.filectx(abs).data()
482 482 if opts.get('decode'):
483 483 data = repo.wwritedata(abs, data)
484 484 fp.write(data)
485 485 err = 0
486 486 return err
487 487
488 488 def clone(ui, source, dest=None, **opts):
489 489 """make a copy of an existing repository
490 490
491 491 Create a copy of an existing repository in a new directory.
492 492
493 493 If no destination directory name is specified, it defaults to the
494 494 basename of the source.
495 495
496 496 The location of the source is added to the new repository's
497 497 .hg/hgrc file, as the default to be used for future pulls.
498 498
499 499 For efficiency, hardlinks are used for cloning whenever the source
500 500 and destination are on the same filesystem (note this applies only
501 501 to the repository data, not to the checked out files). Some
502 502 filesystems, such as AFS, implement hardlinking incorrectly, but
503 503 do not report errors. In these cases, use the --pull option to
504 504 avoid hardlinking.
505 505
506 506 You can safely clone repositories and checked out files using full
507 507 hardlinks with
508 508
509 509 $ cp -al REPO REPOCLONE
510 510
511 511 which is the fastest way to clone. However, the operation is not
512 512 atomic (making sure REPO is not modified during the operation is
513 513 up to you) and you have to make sure your editor breaks hardlinks
514 514 (Emacs and most Linux Kernel tools do so).
515 515
516 516 If you use the -r option to clone up to a specific revision, no
517 517 subsequent revisions will be present in the cloned repository.
518 518 This option implies --pull, even on local repositories.
519 519
520 520 If the -U option is used, the new clone will contain only a repository
521 521 (.hg) and no working copy (the working copy parent is the null revision).
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 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 2081 or changeset to push. If -r is used, the named changeset and all its
2082 2082 ancestors will be pushed to the remote repository.
2083 2083
2084 2084 Look at the help text for the pull command for important details
2085 2085 about ssh:// URLs.
2086 2086
2087 2087 Pushing to http:// and https:// URLs is only possible, if this
2088 2088 feature is explicitly enabled on the remote Mercurial server.
2089 2089 """
2090 2090 dest, revs, checkout = hg.parseurl(
2091 2091 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2092 2092 cmdutil.setremoteconfig(ui, opts)
2093 2093
2094 2094 other = hg.repository(ui, dest)
2095 2095 ui.status('pushing to %s\n' % util.hidepassword(dest))
2096 2096 if revs:
2097 2097 revs = [repo.lookup(rev) for rev in revs]
2098 2098 r = repo.push(other, opts['force'], revs=revs)
2099 2099 return r == 0
2100 2100
2101 2101 def rawcommit(ui, repo, *pats, **opts):
2102 2102 """raw commit interface (DEPRECATED)
2103 2103
2104 2104 (DEPRECATED)
2105 2105 Lowlevel commit, for use in helper scripts.
2106 2106
2107 2107 This command is not intended to be used by normal users, as it is
2108 2108 primarily useful for importing from other SCMs.
2109 2109
2110 2110 This command is now deprecated and will be removed in a future
2111 2111 release, please use debugsetparents and commit instead.
2112 2112 """
2113 2113
2114 2114 ui.warn(_("(the rawcommit command is deprecated)\n"))
2115 2115
2116 2116 message = cmdutil.logmessage(opts)
2117 2117
2118 2118 files, match, anypats = cmdutil.matchpats(repo, pats, opts)
2119 2119 if opts['files']:
2120 2120 files += open(opts['files']).read().splitlines()
2121 2121
2122 2122 parents = [repo.lookup(p) for p in opts['parent']]
2123 2123
2124 2124 try:
2125 2125 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2126 2126 except ValueError, inst:
2127 2127 raise util.Abort(str(inst))
2128 2128
2129 2129 def recover(ui, repo):
2130 2130 """roll back an interrupted transaction
2131 2131
2132 2132 Recover from an interrupted commit or pull.
2133 2133
2134 2134 This command tries to fix the repository status after an interrupted
2135 2135 operation. It should only be necessary when Mercurial suggests it.
2136 2136 """
2137 2137 if repo.recover():
2138 2138 return hg.verify(repo)
2139 2139 return 1
2140 2140
2141 2141 def remove(ui, repo, *pats, **opts):
2142 2142 """remove the specified files on the next commit
2143 2143
2144 2144 Schedule the indicated files for removal from the repository.
2145 2145
2146 2146 This only removes files from the current branch, not from the entire
2147 2147 project history. -A can be used to remove only files that have already
2148 2148 been deleted, -f can be used to force deletion, and -Af can be used
2149 2149 to remove files from the next revision without deleting them.
2150 2150
2151 2151 The following table details the behavior of remove for different file
2152 2152 states (columns) and option combinations (rows). The file states are
2153 2153 Added, Clean, Modified and Missing (as reported by hg status). The
2154 2154 actions are Warn, Remove (from branch) and Delete (from disk).
2155 2155
2156 2156 A C M !
2157 2157 none W RD W R
2158 2158 -f R RD RD R
2159 2159 -A W W W R
2160 2160 -Af R R R R
2161 2161
2162 2162 This command schedules the files to be removed at the next commit.
2163 2163 To undo a remove before that, see hg revert.
2164 2164 """
2165 2165
2166 2166 after, force = opts.get('after'), opts.get('force')
2167 2167 if not pats and not after:
2168 2168 raise util.Abort(_('no files specified'))
2169 2169
2170 2170 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2171 2171 mardu = map(dict.fromkeys, repo.status(files=files, match=matchfn))[:5]
2172 2172 modified, added, removed, deleted, unknown = mardu
2173 2173
2174 2174 remove, forget = [], []
2175 2175 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts):
2176 2176
2177 2177 reason = None
2178 2178 if abs in removed or abs in unknown:
2179 2179 continue
2180 2180
2181 2181 # last column
2182 2182 elif abs in deleted:
2183 2183 remove.append(abs)
2184 2184
2185 2185 # rest of the third row
2186 2186 elif after and not force:
2187 2187 reason = _('still exists (use -f to force removal)')
2188 2188
2189 2189 # rest of the first column
2190 2190 elif abs in added:
2191 2191 if not force:
2192 2192 reason = _('has been marked for add (use -f to force removal)')
2193 2193 else:
2194 2194 forget.append(abs)
2195 2195
2196 2196 # rest of the third column
2197 2197 elif abs in modified:
2198 2198 if not force:
2199 2199 reason = _('is modified (use -f to force removal)')
2200 2200 else:
2201 2201 remove.append(abs)
2202 2202
2203 2203 # rest of the second column
2204 2204 elif not reason:
2205 2205 remove.append(abs)
2206 2206
2207 2207 if reason:
2208 2208 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2209 2209 elif ui.verbose or not exact:
2210 2210 ui.status(_('removing %s\n') % rel)
2211 2211
2212 2212 repo.forget(forget)
2213 2213 repo.remove(remove, unlink=not after)
2214 2214
2215 2215 def rename(ui, repo, *pats, **opts):
2216 2216 """rename files; equivalent of copy + remove
2217 2217
2218 2218 Mark dest as copies of sources; mark sources for deletion. If
2219 2219 dest is a directory, copies are put in that directory. If dest is
2220 2220 a file, there can only be one source.
2221 2221
2222 2222 By default, this command copies the contents of files as they
2223 2223 stand in the working directory. If invoked with --after, the
2224 2224 operation is recorded, but no copying is performed.
2225 2225
2226 2226 This command takes effect in the next commit. To undo a rename
2227 2227 before that, see hg revert.
2228 2228 """
2229 2229 wlock = repo.wlock(False)
2230 2230 try:
2231 2231 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2232 2232 finally:
2233 2233 del wlock
2234 2234
2235 2235 def revert(ui, repo, *pats, **opts):
2236 2236 """restore individual files or dirs to an earlier state
2237 2237
2238 2238 (use update -r to check out earlier revisions, revert does not
2239 2239 change the working dir parents)
2240 2240
2241 2241 With no revision specified, revert the named files or directories
2242 2242 to the contents they had in the parent of the working directory.
2243 2243 This restores the contents of the affected files to an unmodified
2244 2244 state and unschedules adds, removes, copies, and renames. If the
2245 2245 working directory has two parents, you must explicitly specify the
2246 2246 revision to revert to.
2247 2247
2248 2248 Using the -r option, revert the given files or directories to their
2249 2249 contents as of a specific revision. This can be helpful to "roll
2250 2250 back" some or all of an earlier change.
2251 2251 See 'hg help dates' for a list of formats valid for -d/--date.
2252 2252
2253 2253 Revert modifies the working directory. It does not commit any
2254 2254 changes, or change the parent of the working directory. If you
2255 2255 revert to a revision other than the parent of the working
2256 2256 directory, the reverted files will thus appear modified
2257 2257 afterwards.
2258 2258
2259 2259 If a file has been deleted, it is restored. If the executable
2260 2260 mode of a file was changed, it is reset.
2261 2261
2262 2262 If names are given, all files matching the names are reverted.
2263 2263 If no arguments are given, no files are reverted.
2264 2264
2265 2265 Modified files are saved with a .orig suffix before reverting.
2266 2266 To disable these backups, use --no-backup.
2267 2267 """
2268 2268
2269 2269 if opts["date"]:
2270 2270 if opts["rev"]:
2271 2271 raise util.Abort(_("you can't specify a revision and a date"))
2272 2272 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2273 2273
2274 2274 if not pats and not opts['all']:
2275 2275 raise util.Abort(_('no files or directories specified; '
2276 2276 'use --all to revert the whole repo'))
2277 2277
2278 2278 parent, p2 = repo.dirstate.parents()
2279 2279 if not opts['rev'] and p2 != nullid:
2280 2280 raise util.Abort(_('uncommitted merge - please provide a '
2281 2281 'specific revision'))
2282 2282 ctx = repo.changectx(opts['rev'])
2283 2283 node = ctx.node()
2284 2284 mf = ctx.manifest()
2285 2285 if node == parent:
2286 2286 pmf = mf
2287 2287 else:
2288 2288 pmf = None
2289 2289
2290 2290 # need all matching names in dirstate and manifest of target rev,
2291 2291 # so have to walk both. do not print errors if files exist in one
2292 2292 # but not other.
2293 2293
2294 2294 names = {}
2295 2295
2296 2296 wlock = repo.wlock()
2297 2297 try:
2298 2298 # walk dirstate.
2299 2299 files = []
2300 2300 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
2301 2301 badmatch=mf.has_key):
2302 2302 names[abs] = (rel, exact)
2303 2303 if src != 'b':
2304 2304 files.append(abs)
2305 2305
2306 2306 # walk target manifest.
2307 2307
2308 2308 def badmatch(path):
2309 2309 if path in names:
2310 2310 return True
2311 2311 path_ = path + '/'
2312 2312 for f in names:
2313 2313 if f.startswith(path_):
2314 2314 return True
2315 2315 return False
2316 2316
2317 2317 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
2318 2318 badmatch=badmatch):
2319 2319 if abs in names or src == 'b':
2320 2320 continue
2321 2321 names[abs] = (rel, exact)
2322 2322
2323 2323 changes = repo.status(files=files, match=names.has_key)[:4]
2324 2324 modified, added, removed, deleted = map(dict.fromkeys, changes)
2325 2325
2326 2326 # if f is a rename, also revert the source
2327 2327 cwd = repo.getcwd()
2328 2328 for f in added:
2329 2329 src = repo.dirstate.copied(f)
2330 2330 if src and src not in names and repo.dirstate[src] == 'r':
2331 2331 removed[src] = None
2332 2332 names[src] = (repo.pathto(src, cwd), True)
2333 2333
2334 2334 def removeforget(abs):
2335 2335 if repo.dirstate[abs] == 'a':
2336 2336 return _('forgetting %s\n')
2337 2337 return _('removing %s\n')
2338 2338
2339 2339 revert = ([], _('reverting %s\n'))
2340 2340 add = ([], _('adding %s\n'))
2341 2341 remove = ([], removeforget)
2342 2342 undelete = ([], _('undeleting %s\n'))
2343 2343
2344 2344 disptable = (
2345 2345 # dispatch table:
2346 2346 # file state
2347 2347 # action if in target manifest
2348 2348 # action if not in target manifest
2349 2349 # make backup if in target manifest
2350 2350 # make backup if not in target manifest
2351 2351 (modified, revert, remove, True, True),
2352 2352 (added, revert, remove, True, False),
2353 2353 (removed, undelete, None, False, False),
2354 2354 (deleted, revert, remove, False, False),
2355 2355 )
2356 2356
2357 2357 entries = names.items()
2358 2358 entries.sort()
2359 2359
2360 2360 for abs, (rel, exact) in entries:
2361 2361 mfentry = mf.get(abs)
2362 2362 target = repo.wjoin(abs)
2363 2363 def handle(xlist, dobackup):
2364 2364 xlist[0].append(abs)
2365 2365 if dobackup and not opts['no_backup'] and util.lexists(target):
2366 2366 bakname = "%s.orig" % rel
2367 2367 ui.note(_('saving current version of %s as %s\n') %
2368 2368 (rel, bakname))
2369 2369 if not opts.get('dry_run'):
2370 2370 util.copyfile(target, bakname)
2371 2371 if ui.verbose or not exact:
2372 2372 msg = xlist[1]
2373 2373 if not isinstance(msg, basestring):
2374 2374 msg = msg(abs)
2375 2375 ui.status(msg % rel)
2376 2376 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2377 2377 if abs not in table: continue
2378 2378 # file has changed in dirstate
2379 2379 if mfentry:
2380 2380 handle(hitlist, backuphit)
2381 2381 elif misslist is not None:
2382 2382 handle(misslist, backupmiss)
2383 2383 break
2384 2384 else:
2385 2385 if abs not in repo.dirstate:
2386 2386 if mfentry:
2387 2387 handle(add, True)
2388 2388 elif exact:
2389 2389 ui.warn(_('file not managed: %s\n') % rel)
2390 2390 continue
2391 2391 # file has not changed in dirstate
2392 2392 if node == parent:
2393 2393 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2394 2394 continue
2395 2395 if pmf is None:
2396 2396 # only need parent manifest in this unlikely case,
2397 2397 # so do not read by default
2398 2398 pmf = repo.changectx(parent).manifest()
2399 2399 if abs in pmf:
2400 2400 if mfentry:
2401 2401 # if version of file is same in parent and target
2402 2402 # manifests, do nothing
2403 2403 if (pmf[abs] != mfentry or
2404 2404 pmf.flags(abs) != mf.flags(abs)):
2405 2405 handle(revert, False)
2406 2406 else:
2407 2407 handle(remove, False)
2408 2408
2409 2409 if not opts.get('dry_run'):
2410 2410 def checkout(f):
2411 2411 fc = ctx[f]
2412 2412 repo.wwrite(f, fc.data(), fc.fileflags())
2413 2413
2414 2414 audit_path = util.path_auditor(repo.root)
2415 2415 for f in remove[0]:
2416 2416 if repo.dirstate[f] == 'a':
2417 2417 repo.dirstate.forget(f)
2418 2418 continue
2419 2419 audit_path(f)
2420 2420 try:
2421 2421 util.unlink(repo.wjoin(f))
2422 2422 except OSError:
2423 2423 pass
2424 2424 repo.dirstate.remove(f)
2425 2425
2426 2426 normal = None
2427 2427 if node == parent:
2428 2428 # We're reverting to our parent. If possible, we'd like status
2429 2429 # to report the file as clean. We have to use normallookup for
2430 2430 # merges to avoid losing information about merged/dirty files.
2431 2431 if p2 != nullid:
2432 2432 normal = repo.dirstate.normallookup
2433 2433 else:
2434 2434 normal = repo.dirstate.normal
2435 2435 for f in revert[0]:
2436 2436 checkout(f)
2437 2437 if normal:
2438 2438 normal(f)
2439 2439
2440 2440 for f in add[0]:
2441 2441 checkout(f)
2442 2442 repo.dirstate.add(f)
2443 2443
2444 2444 normal = repo.dirstate.normallookup
2445 2445 if node == parent and p2 == nullid:
2446 2446 normal = repo.dirstate.normal
2447 2447 for f in undelete[0]:
2448 2448 checkout(f)
2449 2449 normal(f)
2450 2450
2451 2451 finally:
2452 2452 del wlock
2453 2453
2454 2454 def rollback(ui, repo):
2455 2455 """roll back the last transaction
2456 2456
2457 2457 This command should be used with care. There is only one level of
2458 2458 rollback, and there is no way to undo a rollback. It will also
2459 2459 restore the dirstate at the time of the last transaction, losing
2460 2460 any dirstate changes since that time.
2461 2461
2462 2462 Transactions are used to encapsulate the effects of all commands
2463 2463 that create new changesets or propagate existing changesets into a
2464 2464 repository. For example, the following commands are transactional,
2465 2465 and their effects can be rolled back:
2466 2466
2467 2467 commit
2468 2468 import
2469 2469 pull
2470 2470 push (with this repository as destination)
2471 2471 unbundle
2472 2472
2473 2473 This command is not intended for use on public repositories. Once
2474 2474 changes are visible for pull by other users, rolling a transaction
2475 2475 back locally is ineffective (someone else may already have pulled
2476 2476 the changes). Furthermore, a race is possible with readers of the
2477 2477 repository; for example an in-progress pull from the repository
2478 2478 may fail if a rollback is performed.
2479 2479 """
2480 2480 repo.rollback()
2481 2481
2482 2482 def root(ui, repo):
2483 2483 """print the root (top) of the current working dir
2484 2484
2485 2485 Print the root directory of the current repository.
2486 2486 """
2487 2487 ui.write(repo.root + "\n")
2488 2488
2489 2489 def serve(ui, repo, **opts):
2490 2490 """export the repository via HTTP
2491 2491
2492 2492 Start a local HTTP repository browser and pull server.
2493 2493
2494 2494 By default, the server logs accesses to stdout and errors to
2495 2495 stderr. Use the "-A" and "-E" options to log to files.
2496 2496 """
2497 2497
2498 2498 if opts["stdio"]:
2499 2499 if repo is None:
2500 2500 raise RepoError(_("There is no Mercurial repository here"
2501 2501 " (.hg not found)"))
2502 2502 s = sshserver.sshserver(ui, repo)
2503 2503 s.serve_forever()
2504 2504
2505 2505 parentui = ui.parentui or ui
2506 2506 optlist = ("name templates style address port prefix ipv6"
2507 2507 " accesslog errorlog webdir_conf certificate")
2508 2508 for o in optlist.split():
2509 2509 if opts[o]:
2510 2510 parentui.setconfig("web", o, str(opts[o]))
2511 2511 if (repo is not None) and (repo.ui != parentui):
2512 2512 repo.ui.setconfig("web", o, str(opts[o]))
2513 2513
2514 2514 if repo is None and not ui.config("web", "webdir_conf"):
2515 2515 raise RepoError(_("There is no Mercurial repository here"
2516 2516 " (.hg not found)"))
2517 2517
2518 2518 class service:
2519 2519 def init(self):
2520 2520 util.set_signal_handler()
2521 2521 self.httpd = hgweb.server.create_server(parentui, repo)
2522 2522
2523 2523 if not ui.verbose: return
2524 2524
2525 2525 if self.httpd.prefix:
2526 2526 prefix = self.httpd.prefix.strip('/') + '/'
2527 2527 else:
2528 2528 prefix = ''
2529 2529
2530 2530 port = ':%d' % self.httpd.port
2531 2531 if port == ':80':
2532 2532 port = ''
2533 2533
2534 2534 ui.status(_('listening at http://%s%s/%s (%s:%d)\n') %
2535 2535 (self.httpd.fqaddr, port, prefix, self.httpd.addr, self.httpd.port))
2536 2536
2537 2537 def run(self):
2538 2538 self.httpd.serve_forever()
2539 2539
2540 2540 service = service()
2541 2541
2542 2542 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2543 2543
2544 2544 def status(ui, repo, *pats, **opts):
2545 2545 """show changed files in the working directory
2546 2546
2547 2547 Show status of files in the repository. If names are given, only
2548 2548 files that match are shown. Files that are clean or ignored or
2549 2549 source of a copy/move operation, are not listed unless -c (clean),
2550 2550 -i (ignored), -C (copies) or -A is given. Unless options described
2551 2551 with "show only ..." are given, the options -mardu are used.
2552 2552
2553 2553 Option -q/--quiet hides untracked (unknown and ignored) files
2554 2554 unless explicitly requested with -u/--unknown or -i/-ignored.
2555 2555
2556 2556 NOTE: status may appear to disagree with diff if permissions have
2557 2557 changed or a merge has occurred. The standard diff format does not
2558 2558 report permission changes and diff only reports changes relative
2559 2559 to one merge parent.
2560 2560
2561 2561 If one revision is given, it is used as the base revision.
2562 2562 If two revisions are given, the difference between them is shown.
2563 2563
2564 2564 The codes used to show the status of files are:
2565 2565 M = modified
2566 2566 A = added
2567 2567 R = removed
2568 2568 C = clean
2569 2569 ! = deleted, but still tracked
2570 2570 ? = not tracked
2571 2571 I = ignored
2572 2572 = the previous added file was copied from here
2573 2573 """
2574 2574
2575 2575 all = opts['all']
2576 2576 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2577 2577
2578 2578 files, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)
2579 2579 cwd = (pats and repo.getcwd()) or ''
2580 2580 modified, added, removed, deleted, unknown, ignored, clean = [
2581 2581 n for n in repo.status(node1=node1, node2=node2, files=files,
2582 2582 match=matchfn,
2583 2583 list_ignored=opts['ignored']
2584 2584 or all and not ui.quiet,
2585 2585 list_clean=opts['clean'] or all,
2586 2586 list_unknown=opts['unknown']
2587 2587 or not (ui.quiet or
2588 2588 opts['modified'] or
2589 2589 opts['added'] or
2590 2590 opts['removed'] or
2591 2591 opts['deleted'] or
2592 2592 opts['ignored']))]
2593 2593
2594 2594 changetypes = (('modified', 'M', modified),
2595 2595 ('added', 'A', added),
2596 2596 ('removed', 'R', removed),
2597 2597 ('deleted', '!', deleted),
2598 2598 ('unknown', '?', unknown),
2599 2599 ('ignored', 'I', ignored))
2600 2600
2601 2601 explicit_changetypes = changetypes + (('clean', 'C', clean),)
2602 2602
2603 2603 copy = {}
2604 2604 showcopy = {}
2605 2605 if ((all or opts.get('copies')) and not opts.get('no_status')):
2606 2606 if opts.get('rev') == []:
2607 2607 # fast path, more correct with merge parents
2608 2608 showcopy = copy = repo.dirstate.copies().copy()
2609 2609 else:
2610 2610 ctxn = repo.changectx(nullid)
2611 2611 ctx1 = repo.changectx(node1)
2612 2612 ctx2 = repo.changectx(node2)
2613 2613 if node2 is None:
2614 2614 ctx2 = repo.workingctx()
2615 2615 copy, diverge = copies.copies(repo, ctx1, ctx2, ctxn)
2616 2616 for k, v in copy.items():
2617 2617 copy[v] = k
2618 2618
2619 2619 end = opts['print0'] and '\0' or '\n'
2620 2620
2621 2621 for opt, char, changes in ([ct for ct in explicit_changetypes
2622 2622 if all or opts[ct[0]]]
2623 2623 or changetypes):
2624 2624
2625 2625 if opts['no_status']:
2626 2626 format = "%%s%s" % end
2627 2627 else:
2628 2628 format = "%s %%s%s" % (char, end)
2629 2629
2630 2630 for f in changes:
2631 2631 ui.write(format % repo.pathto(f, cwd))
2632 2632 if f in copy and (f in added or f in showcopy):
2633 2633 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2634 2634
2635 2635 def tag(ui, repo, name1, *names, **opts):
2636 2636 """add one or more tags for the current or given revision
2637 2637
2638 2638 Name a particular revision using <name>.
2639 2639
2640 2640 Tags are used to name particular revisions of the repository and are
2641 2641 very useful to compare different revisions, to go back to significant
2642 2642 earlier versions or to mark branch points as releases, etc.
2643 2643
2644 2644 If no revision is given, the parent of the working directory is used,
2645 2645 or tip if no revision is checked out.
2646 2646
2647 2647 To facilitate version control, distribution, and merging of tags,
2648 2648 they are stored as a file named ".hgtags" which is managed
2649 2649 similarly to other project files and can be hand-edited if
2650 2650 necessary. The file '.hg/localtags' is used for local tags (not
2651 2651 shared among repositories).
2652 2652
2653 2653 See 'hg help dates' for a list of formats valid for -d/--date.
2654 2654 """
2655 2655
2656 2656 rev_ = None
2657 2657 names = (name1,) + names
2658 2658 if len(names) != len(dict.fromkeys(names)):
2659 2659 raise util.Abort(_('tag names must be unique'))
2660 2660 for n in names:
2661 2661 if n in ['tip', '.', 'null']:
2662 2662 raise util.Abort(_('the name \'%s\' is reserved') % n)
2663 2663 if opts['rev'] and opts['remove']:
2664 2664 raise util.Abort(_("--rev and --remove are incompatible"))
2665 2665 if opts['rev']:
2666 2666 rev_ = opts['rev']
2667 2667 message = opts['message']
2668 2668 if opts['remove']:
2669 2669 expectedtype = opts['local'] and 'local' or 'global'
2670 2670 for n in names:
2671 2671 if not repo.tagtype(n):
2672 2672 raise util.Abort(_('tag \'%s\' does not exist') % n)
2673 2673 if repo.tagtype(n) != expectedtype:
2674 2674 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2675 2675 (n, expectedtype))
2676 2676 rev_ = nullid
2677 2677 if not message:
2678 2678 message = _('Removed tag %s') % ', '.join(names)
2679 2679 elif not opts['force']:
2680 2680 for n in names:
2681 2681 if n in repo.tags():
2682 2682 raise util.Abort(_('tag \'%s\' already exists '
2683 2683 '(use -f to force)') % n)
2684 2684 if not rev_ and repo.dirstate.parents()[1] != nullid:
2685 2685 raise util.Abort(_('uncommitted merge - please provide a '
2686 2686 'specific revision'))
2687 2687 r = repo.changectx(rev_).node()
2688 2688
2689 2689 if not message:
2690 2690 message = (_('Added tag %s for changeset %s') %
2691 2691 (', '.join(names), short(r)))
2692 2692
2693 2693 date = opts.get('date')
2694 2694 if date:
2695 2695 date = util.parsedate(date)
2696 2696
2697 2697 repo.tag(names, r, message, opts['local'], opts['user'], date)
2698 2698
2699 2699 def tags(ui, repo):
2700 2700 """list repository tags
2701 2701
2702 2702 List the repository tags.
2703 2703
2704 2704 This lists both regular and local tags. When the -v/--verbose switch
2705 2705 is used, a third column "local" is printed for local tags.
2706 2706 """
2707 2707
2708 2708 l = repo.tagslist()
2709 2709 l.reverse()
2710 2710 hexfunc = ui.debugflag and hex or short
2711 2711 tagtype = ""
2712 2712
2713 2713 for t, n in l:
2714 2714 if ui.quiet:
2715 2715 ui.write("%s\n" % t)
2716 2716 continue
2717 2717
2718 2718 try:
2719 2719 hn = hexfunc(n)
2720 2720 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2721 2721 except revlog.LookupError:
2722 2722 r = " ?:%s" % hn
2723 2723 else:
2724 2724 spaces = " " * (30 - util.locallen(t))
2725 2725 if ui.verbose:
2726 2726 if repo.tagtype(t) == 'local':
2727 2727 tagtype = " local"
2728 2728 else:
2729 2729 tagtype = ""
2730 2730 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2731 2731
2732 2732 def tip(ui, repo, **opts):
2733 2733 """show the tip revision
2734 2734
2735 2735 The tip revision (usually just called the tip) is the most
2736 2736 recently added changeset in the repository, the most recently
2737 2737 changed head.
2738 2738
2739 2739 If you have just made a commit, that commit will be the tip. If
2740 2740 you have just pulled changes from another repository, the tip of
2741 2741 that repository becomes the current tip. The "tip" tag is special
2742 2742 and cannot be renamed or assigned to a different changeset.
2743 2743 """
2744 2744 cmdutil.show_changeset(ui, repo, opts).show(nullrev+repo.changelog.count())
2745 2745
2746 2746 def unbundle(ui, repo, fname1, *fnames, **opts):
2747 2747 """apply one or more changegroup files
2748 2748
2749 2749 Apply one or more compressed changegroup files generated by the
2750 2750 bundle command.
2751 2751 """
2752 2752 fnames = (fname1,) + fnames
2753 2753
2754 2754 lock = None
2755 2755 try:
2756 2756 lock = repo.lock()
2757 2757 for fname in fnames:
2758 2758 if os.path.exists(fname):
2759 2759 f = open(fname, "rb")
2760 2760 else:
2761 2761 f = urllib.urlopen(fname)
2762 2762 gen = changegroup.readbundle(f, fname)
2763 2763 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2764 2764 finally:
2765 2765 del lock
2766 2766
2767 2767 return postincoming(ui, repo, modheads, opts['update'], None)
2768 2768
2769 2769 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2770 2770 """update working directory
2771 2771
2772 2772 Update the working directory to the specified revision, or the
2773 2773 tip of the current branch if none is specified.
2774 2774
2775 2775 If the requested revision is a descendant of the working
2776 2776 directory, any outstanding changes in the working directory will
2777 2777 be merged into the result. If it is not directly descended but is
2778 2778 on the same named branch, update aborts with a suggestion to use
2779 2779 merge or update -C instead.
2780 2780
2781 2781 If the requested revision is on a different named branch and the
2782 2782 working directory is clean, update quietly switches branches.
2783 2783
2784 If you want to update just one file to an older revision, use revert.
2785
2784 2786 See 'hg help dates' for a list of formats valid for --date.
2785 2787 """
2786 2788 if rev and node:
2787 2789 raise util.Abort(_("please specify just one revision"))
2788 2790
2789 2791 if not rev:
2790 2792 rev = node
2791 2793
2792 2794 if date:
2793 2795 if rev:
2794 2796 raise util.Abort(_("you can't specify a revision and a date"))
2795 2797 rev = cmdutil.finddate(ui, repo, date)
2796 2798
2797 2799 if clean:
2798 2800 return hg.clean(repo, rev)
2799 2801 else:
2800 2802 return hg.update(repo, rev)
2801 2803
2802 2804 def verify(ui, repo):
2803 2805 """verify the integrity of the repository
2804 2806
2805 2807 Verify the integrity of the current repository.
2806 2808
2807 2809 This will perform an extensive check of the repository's
2808 2810 integrity, validating the hashes and checksums of each entry in
2809 2811 the changelog, manifest, and tracked files, as well as the
2810 2812 integrity of their crosslinks and indices.
2811 2813 """
2812 2814 return hg.verify(repo)
2813 2815
2814 2816 def version_(ui):
2815 2817 """output version and copyright information"""
2816 2818 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2817 2819 % version.get_version())
2818 2820 ui.status(_(
2819 2821 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2820 2822 "This is free software; see the source for copying conditions. "
2821 2823 "There is NO\nwarranty; "
2822 2824 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2823 2825 ))
2824 2826
2825 2827 # Command options and aliases are listed here, alphabetically
2826 2828
2827 2829 globalopts = [
2828 2830 ('R', 'repository', '',
2829 2831 _('repository root directory or symbolic path name')),
2830 2832 ('', 'cwd', '', _('change working directory')),
2831 2833 ('y', 'noninteractive', None,
2832 2834 _('do not prompt, assume \'yes\' for any required answers')),
2833 2835 ('q', 'quiet', None, _('suppress output')),
2834 2836 ('v', 'verbose', None, _('enable additional output')),
2835 2837 ('', 'config', [], _('set/override config option')),
2836 2838 ('', 'debug', None, _('enable debugging output')),
2837 2839 ('', 'debugger', None, _('start debugger')),
2838 2840 ('', 'encoding', util._encoding, _('set the charset encoding')),
2839 2841 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2840 2842 ('', 'lsprof', None, _('print improved command execution profile')),
2841 2843 ('', 'traceback', None, _('print traceback on exception')),
2842 2844 ('', 'time', None, _('time how long the command takes')),
2843 2845 ('', 'profile', None, _('print command execution profile')),
2844 2846 ('', 'version', None, _('output version information and exit')),
2845 2847 ('h', 'help', None, _('display help and exit')),
2846 2848 ]
2847 2849
2848 2850 dryrunopts = [('n', 'dry-run', None,
2849 2851 _('do not perform actions, just print output'))]
2850 2852
2851 2853 remoteopts = [
2852 2854 ('e', 'ssh', '', _('specify ssh command to use')),
2853 2855 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2854 2856 ]
2855 2857
2856 2858 walkopts = [
2857 2859 ('I', 'include', [], _('include names matching the given patterns')),
2858 2860 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2859 2861 ]
2860 2862
2861 2863 commitopts = [
2862 2864 ('m', 'message', '', _('use <text> as commit message')),
2863 2865 ('l', 'logfile', '', _('read commit message from <file>')),
2864 2866 ]
2865 2867
2866 2868 commitopts2 = [
2867 2869 ('d', 'date', '', _('record datecode as commit date')),
2868 2870 ('u', 'user', '', _('record user as committer')),
2869 2871 ]
2870 2872
2871 2873 templateopts = [
2872 2874 ('', 'style', '', _('display using template map file')),
2873 2875 ('', 'template', '', _('display with template')),
2874 2876 ]
2875 2877
2876 2878 logopts = [
2877 2879 ('p', 'patch', None, _('show patch')),
2878 2880 ('l', 'limit', '', _('limit number of changes displayed')),
2879 2881 ('M', 'no-merges', None, _('do not show merges')),
2880 2882 ] + templateopts
2881 2883
2882 2884 table = {
2883 2885 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2884 2886 "addremove":
2885 2887 (addremove,
2886 2888 [('s', 'similarity', '',
2887 2889 _('guess renamed files by similarity (0<=s<=100)')),
2888 2890 ] + walkopts + dryrunopts,
2889 2891 _('hg addremove [OPTION]... [FILE]...')),
2890 2892 "^annotate|blame":
2891 2893 (annotate,
2892 2894 [('r', 'rev', '', _('annotate the specified revision')),
2893 2895 ('f', 'follow', None, _('follow file copies and renames')),
2894 2896 ('a', 'text', None, _('treat all files as text')),
2895 2897 ('u', 'user', None, _('list the author (long with -v)')),
2896 2898 ('d', 'date', None, _('list the date (short with -q)')),
2897 2899 ('n', 'number', None, _('list the revision number (default)')),
2898 2900 ('c', 'changeset', None, _('list the changeset')),
2899 2901 ('l', 'line-number', None,
2900 2902 _('show line number at the first appearance'))
2901 2903 ] + walkopts,
2902 2904 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2903 2905 "archive":
2904 2906 (archive,
2905 2907 [('', 'no-decode', None, _('do not pass files through decoders')),
2906 2908 ('p', 'prefix', '', _('directory prefix for files in archive')),
2907 2909 ('r', 'rev', '', _('revision to distribute')),
2908 2910 ('t', 'type', '', _('type of distribution to create')),
2909 2911 ] + walkopts,
2910 2912 _('hg archive [OPTION]... DEST')),
2911 2913 "backout":
2912 2914 (backout,
2913 2915 [('', 'merge', None,
2914 2916 _('merge with old dirstate parent after backout')),
2915 2917 ('', 'parent', '', _('parent to choose when backing out merge')),
2916 2918 ('r', 'rev', '', _('revision to backout')),
2917 2919 ] + walkopts + commitopts + commitopts2,
2918 2920 _('hg backout [OPTION]... [-r] REV')),
2919 2921 "bisect":
2920 2922 (bisect,
2921 2923 [('r', 'reset', False, _('reset bisect state')),
2922 2924 ('g', 'good', False, _('mark changeset good')),
2923 2925 ('b', 'bad', False, _('mark changeset bad')),
2924 2926 ('s', 'skip', False, _('skip testing changeset')),
2925 2927 ('U', 'noupdate', False, _('do not update to target'))],
2926 2928 _("hg bisect [-gbsr] [REV]")),
2927 2929 "branch":
2928 2930 (branch,
2929 2931 [('f', 'force', None,
2930 2932 _('set branch name even if it shadows an existing branch'))],
2931 2933 _('hg branch [-f] [NAME]')),
2932 2934 "branches":
2933 2935 (branches,
2934 2936 [('a', 'active', False,
2935 2937 _('show only branches that have unmerged heads'))],
2936 2938 _('hg branches [-a]')),
2937 2939 "bundle":
2938 2940 (bundle,
2939 2941 [('f', 'force', None,
2940 2942 _('run even when remote repository is unrelated')),
2941 2943 ('r', 'rev', [],
2942 2944 _('a changeset up to which you would like to bundle')),
2943 2945 ('', 'base', [],
2944 2946 _('a base changeset to specify instead of a destination')),
2945 2947 ('a', 'all', None,
2946 2948 _('bundle all changesets in the repository')),
2947 2949 ] + remoteopts,
2948 2950 _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
2949 2951 "cat":
2950 2952 (cat,
2951 2953 [('o', 'output', '', _('print output to file with formatted name')),
2952 2954 ('r', 'rev', '', _('print the given revision')),
2953 2955 ('', 'decode', None, _('apply any matching decode filter')),
2954 2956 ] + walkopts,
2955 2957 _('hg cat [OPTION]... FILE...')),
2956 2958 "^clone":
2957 2959 (clone,
2958 2960 [('U', 'noupdate', None,
2959 2961 _('the clone will only contain a repository (no working copy)')),
2960 2962 ('r', 'rev', [],
2961 2963 _('a changeset you would like to have after cloning')),
2962 2964 ('', 'pull', None, _('use pull protocol to copy metadata')),
2963 2965 ('', 'uncompressed', None,
2964 2966 _('use uncompressed transfer (fast over LAN)')),
2965 2967 ] + remoteopts,
2966 2968 _('hg clone [OPTION]... SOURCE [DEST]')),
2967 2969 "^commit|ci":
2968 2970 (commit,
2969 2971 [('A', 'addremove', None,
2970 2972 _('mark new/missing files as added/removed before committing')),
2971 2973 ] + walkopts + commitopts + commitopts2,
2972 2974 _('hg commit [OPTION]... [FILE]...')),
2973 2975 "copy|cp":
2974 2976 (copy,
2975 2977 [('A', 'after', None, _('record a copy that has already occurred')),
2976 2978 ('f', 'force', None,
2977 2979 _('forcibly copy over an existing managed file')),
2978 2980 ] + walkopts + dryrunopts,
2979 2981 _('hg copy [OPTION]... [SOURCE]... DEST')),
2980 2982 "debugancestor": (debugancestor, [],
2981 2983 _('hg debugancestor [INDEX] REV1 REV2')),
2982 2984 "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
2983 2985 "debugcomplete":
2984 2986 (debugcomplete,
2985 2987 [('o', 'options', None, _('show the command options'))],
2986 2988 _('hg debugcomplete [-o] CMD')),
2987 2989 "debugdate":
2988 2990 (debugdate,
2989 2991 [('e', 'extended', None, _('try extended date formats'))],
2990 2992 _('hg debugdate [-e] DATE [RANGE]')),
2991 2993 "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
2992 2994 "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
2993 2995 "debugindex": (debugindex, [], _('hg debugindex FILE')),
2994 2996 "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
2995 2997 "debuginstall": (debuginstall, [], _('hg debuginstall')),
2996 2998 "debugrawcommit|rawcommit":
2997 2999 (rawcommit,
2998 3000 [('p', 'parent', [], _('parent')),
2999 3001 ('F', 'files', '', _('file list'))
3000 3002 ] + commitopts + commitopts2,
3001 3003 _('hg debugrawcommit [OPTION]... [FILE]...')),
3002 3004 "debugrebuildstate":
3003 3005 (debugrebuildstate,
3004 3006 [('r', 'rev', '', _('revision to rebuild to'))],
3005 3007 _('hg debugrebuildstate [-r REV] [REV]')),
3006 3008 "debugrename":
3007 3009 (debugrename,
3008 3010 [('r', 'rev', '', _('revision to debug'))],
3009 3011 _('hg debugrename [-r REV] FILE')),
3010 3012 "debugsetparents":
3011 3013 (debugsetparents,
3012 3014 [],
3013 3015 _('hg debugsetparents REV1 [REV2]')),
3014 3016 "debugstate":
3015 3017 (debugstate,
3016 3018 [('', 'nodates', None, _('do not display the saved mtime'))],
3017 3019 _('hg debugstate [OPTS]')),
3018 3020 "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
3019 3021 "^diff":
3020 3022 (diff,
3021 3023 [('r', 'rev', [], _('revision')),
3022 3024 ('a', 'text', None, _('treat all files as text')),
3023 3025 ('p', 'show-function', None,
3024 3026 _('show which function each change is in')),
3025 3027 ('g', 'git', None, _('use git extended diff format')),
3026 3028 ('', 'nodates', None, _("don't include dates in diff headers")),
3027 3029 ('w', 'ignore-all-space', None,
3028 3030 _('ignore white space when comparing lines')),
3029 3031 ('b', 'ignore-space-change', None,
3030 3032 _('ignore changes in the amount of white space')),
3031 3033 ('B', 'ignore-blank-lines', None,
3032 3034 _('ignore changes whose lines are all blank')),
3033 3035 ('U', 'unified', '',
3034 3036 _('number of lines of context to show'))
3035 3037 ] + walkopts,
3036 3038 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3037 3039 "^export":
3038 3040 (export,
3039 3041 [('o', 'output', '', _('print output to file with formatted name')),
3040 3042 ('a', 'text', None, _('treat all files as text')),
3041 3043 ('g', 'git', None, _('use git extended diff format')),
3042 3044 ('', 'nodates', None, _("don't include dates in diff headers")),
3043 3045 ('', 'switch-parent', None, _('diff against the second parent'))],
3044 3046 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
3045 3047 "grep":
3046 3048 (grep,
3047 3049 [('0', 'print0', None, _('end fields with NUL')),
3048 3050 ('', 'all', None, _('print all revisions that match')),
3049 3051 ('f', 'follow', None,
3050 3052 _('follow changeset history, or file history across copies and renames')),
3051 3053 ('i', 'ignore-case', None, _('ignore case when matching')),
3052 3054 ('l', 'files-with-matches', None,
3053 3055 _('print only filenames and revs that match')),
3054 3056 ('n', 'line-number', None, _('print matching line numbers')),
3055 3057 ('r', 'rev', [], _('search in given revision range')),
3056 3058 ('u', 'user', None, _('list the author (long with -v)')),
3057 3059 ('d', 'date', None, _('list the date (short with -q)')),
3058 3060 ] + walkopts,
3059 3061 _('hg grep [OPTION]... PATTERN [FILE]...')),
3060 3062 "heads":
3061 3063 (heads,
3062 3064 [('r', 'rev', '', _('show only heads which are descendants of rev')),
3063 3065 ] + templateopts,
3064 3066 _('hg heads [-r REV] [REV]...')),
3065 3067 "help": (help_, [], _('hg help [COMMAND]')),
3066 3068 "identify|id":
3067 3069 (identify,
3068 3070 [('r', 'rev', '', _('identify the specified rev')),
3069 3071 ('n', 'num', None, _('show local revision number')),
3070 3072 ('i', 'id', None, _('show global revision id')),
3071 3073 ('b', 'branch', None, _('show branch')),
3072 3074 ('t', 'tags', None, _('show tags'))],
3073 3075 _('hg identify [-nibt] [-r REV] [SOURCE]')),
3074 3076 "import|patch":
3075 3077 (import_,
3076 3078 [('p', 'strip', 1,
3077 3079 _('directory strip option for patch. This has the same\n'
3078 3080 'meaning as the corresponding patch option')),
3079 3081 ('b', 'base', '', _('base path')),
3080 3082 ('f', 'force', None,
3081 3083 _('skip check for outstanding uncommitted changes')),
3082 3084 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3083 3085 ('', 'exact', None,
3084 3086 _('apply patch to the nodes from which it was generated')),
3085 3087 ('', 'import-branch', None,
3086 3088 _('Use any branch information in patch (implied by --exact)'))] +
3087 3089 commitopts + commitopts2,
3088 3090 _('hg import [OPTION]... PATCH...')),
3089 3091 "incoming|in":
3090 3092 (incoming,
3091 3093 [('f', 'force', None,
3092 3094 _('run even when remote repository is unrelated')),
3093 3095 ('n', 'newest-first', None, _('show newest record first')),
3094 3096 ('', 'bundle', '', _('file to store the bundles into')),
3095 3097 ('r', 'rev', [],
3096 3098 _('a specific revision up to which you would like to pull')),
3097 3099 ] + logopts + remoteopts,
3098 3100 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
3099 3101 ' [--bundle FILENAME] [SOURCE]')),
3100 3102 "^init":
3101 3103 (init,
3102 3104 remoteopts,
3103 3105 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
3104 3106 "locate":
3105 3107 (locate,
3106 3108 [('r', 'rev', '', _('search the repository as it stood at rev')),
3107 3109 ('0', 'print0', None,
3108 3110 _('end filenames with NUL, for use with xargs')),
3109 3111 ('f', 'fullpath', None,
3110 3112 _('print complete paths from the filesystem root')),
3111 3113 ] + walkopts,
3112 3114 _('hg locate [OPTION]... [PATTERN]...')),
3113 3115 "^log|history":
3114 3116 (log,
3115 3117 [('f', 'follow', None,
3116 3118 _('follow changeset history, or file history across copies and renames')),
3117 3119 ('', 'follow-first', None,
3118 3120 _('only follow the first parent of merge changesets')),
3119 3121 ('d', 'date', '', _('show revs matching date spec')),
3120 3122 ('C', 'copies', None, _('show copied files')),
3121 3123 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3122 3124 ('r', 'rev', [], _('show the specified revision or range')),
3123 3125 ('', 'removed', None, _('include revs where files were removed')),
3124 3126 ('m', 'only-merges', None, _('show only merges')),
3125 3127 ('b', 'only-branch', [],
3126 3128 _('show only changesets within the given named branch')),
3127 3129 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3128 3130 ] + logopts + walkopts,
3129 3131 _('hg log [OPTION]... [FILE]')),
3130 3132 "manifest":
3131 3133 (manifest,
3132 3134 [('r', 'rev', '', _('revision to display'))],
3133 3135 _('hg manifest [-r REV]')),
3134 3136 "^merge":
3135 3137 (merge,
3136 3138 [('f', 'force', None, _('force a merge with outstanding changes')),
3137 3139 ('r', 'rev', '', _('revision to merge')),
3138 3140 ],
3139 3141 _('hg merge [-f] [[-r] REV]')),
3140 3142 "outgoing|out":
3141 3143 (outgoing,
3142 3144 [('f', 'force', None,
3143 3145 _('run even when remote repository is unrelated')),
3144 3146 ('r', 'rev', [],
3145 3147 _('a specific revision up to which you would like to push')),
3146 3148 ('n', 'newest-first', None, _('show newest record first')),
3147 3149 ] + logopts + remoteopts,
3148 3150 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3149 3151 "^parents":
3150 3152 (parents,
3151 3153 [('r', 'rev', '', _('show parents from the specified rev')),
3152 3154 ] + templateopts,
3153 3155 _('hg parents [-r REV] [FILE]')),
3154 3156 "paths": (paths, [], _('hg paths [NAME]')),
3155 3157 "^pull":
3156 3158 (pull,
3157 3159 [('u', 'update', None,
3158 3160 _('update to new tip if changesets were pulled')),
3159 3161 ('f', 'force', None,
3160 3162 _('run even when remote repository is unrelated')),
3161 3163 ('r', 'rev', [],
3162 3164 _('a specific revision up to which you would like to pull')),
3163 3165 ] + remoteopts,
3164 3166 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3165 3167 "^push":
3166 3168 (push,
3167 3169 [('f', 'force', None, _('force push')),
3168 3170 ('r', 'rev', [],
3169 3171 _('a specific revision up to which you would like to push')),
3170 3172 ] + remoteopts,
3171 3173 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3172 3174 "recover": (recover, [], _('hg recover')),
3173 3175 "^remove|rm":
3174 3176 (remove,
3175 3177 [('A', 'after', None, _('record delete for missing files')),
3176 3178 ('f', 'force', None,
3177 3179 _('remove (and delete) file even if added or modified')),
3178 3180 ] + walkopts,
3179 3181 _('hg remove [OPTION]... FILE...')),
3180 3182 "rename|mv":
3181 3183 (rename,
3182 3184 [('A', 'after', None, _('record a rename that has already occurred')),
3183 3185 ('f', 'force', None,
3184 3186 _('forcibly copy over an existing managed file')),
3185 3187 ] + walkopts + dryrunopts,
3186 3188 _('hg rename [OPTION]... SOURCE... DEST')),
3187 3189 "revert":
3188 3190 (revert,
3189 3191 [('a', 'all', None, _('revert all changes when no arguments given')),
3190 3192 ('d', 'date', '', _('tipmost revision matching date')),
3191 3193 ('r', 'rev', '', _('revision to revert to')),
3192 3194 ('', 'no-backup', None, _('do not save backup copies of files')),
3193 3195 ] + walkopts + dryrunopts,
3194 3196 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3195 3197 "rollback": (rollback, [], _('hg rollback')),
3196 3198 "root": (root, [], _('hg root')),
3197 3199 "^serve":
3198 3200 (serve,
3199 3201 [('A', 'accesslog', '', _('name of access log file to write to')),
3200 3202 ('d', 'daemon', None, _('run server in background')),
3201 3203 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3202 3204 ('E', 'errorlog', '', _('name of error log file to write to')),
3203 3205 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3204 3206 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3205 3207 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3206 3208 ('n', 'name', '',
3207 3209 _('name to show in web pages (default: working dir)')),
3208 3210 ('', 'webdir-conf', '', _('name of the webdir config file'
3209 3211 ' (serve more than one repo)')),
3210 3212 ('', 'pid-file', '', _('name of file to write process ID to')),
3211 3213 ('', 'stdio', None, _('for remote clients')),
3212 3214 ('t', 'templates', '', _('web templates to use')),
3213 3215 ('', 'style', '', _('template style to use')),
3214 3216 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3215 3217 ('', 'certificate', '', _('SSL certificate file'))],
3216 3218 _('hg serve [OPTION]...')),
3217 3219 "showconfig|debugconfig":
3218 3220 (showconfig,
3219 3221 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3220 3222 _('hg showconfig [-u] [NAME]...')),
3221 3223 "^status|st":
3222 3224 (status,
3223 3225 [('A', 'all', None, _('show status of all files')),
3224 3226 ('m', 'modified', None, _('show only modified files')),
3225 3227 ('a', 'added', None, _('show only added files')),
3226 3228 ('r', 'removed', None, _('show only removed files')),
3227 3229 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3228 3230 ('c', 'clean', None, _('show only files without changes')),
3229 3231 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3230 3232 ('i', 'ignored', None, _('show only ignored files')),
3231 3233 ('n', 'no-status', None, _('hide status prefix')),
3232 3234 ('C', 'copies', None, _('show source of copied files')),
3233 3235 ('0', 'print0', None,
3234 3236 _('end filenames with NUL, for use with xargs')),
3235 3237 ('', 'rev', [], _('show difference from revision')),
3236 3238 ] + walkopts,
3237 3239 _('hg status [OPTION]... [FILE]...')),
3238 3240 "tag":
3239 3241 (tag,
3240 3242 [('f', 'force', None, _('replace existing tag')),
3241 3243 ('l', 'local', None, _('make the tag local')),
3242 3244 ('r', 'rev', '', _('revision to tag')),
3243 3245 ('', 'remove', None, _('remove a tag')),
3244 3246 # -l/--local is already there, commitopts cannot be used
3245 3247 ('m', 'message', '', _('use <text> as commit message')),
3246 3248 ] + commitopts2,
3247 3249 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3248 3250 "tags": (tags, [], _('hg tags')),
3249 3251 "tip":
3250 3252 (tip,
3251 3253 [('p', 'patch', None, _('show patch')),
3252 3254 ] + templateopts,
3253 3255 _('hg tip [-p]')),
3254 3256 "unbundle":
3255 3257 (unbundle,
3256 3258 [('u', 'update', None,
3257 3259 _('update to new tip if changesets were unbundled'))],
3258 3260 _('hg unbundle [-u] FILE...')),
3259 3261 "^update|up|checkout|co":
3260 3262 (update,
3261 3263 [('C', 'clean', None, _('overwrite locally modified files')),
3262 3264 ('d', 'date', '', _('tipmost revision matching date')),
3263 3265 ('r', 'rev', '', _('revision'))],
3264 3266 _('hg update [-C] [-d DATE] [[-r] REV]')),
3265 3267 "verify": (verify, [], _('hg verify')),
3266 3268 "version": (version_, [], _('hg version')),
3267 3269 }
3268 3270
3269 3271 norepo = ("clone init version help debugcomplete debugdata"
3270 3272 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3271 3273 optionalrepo = ("identify paths serve showconfig debugancestor")
General Comments 0
You need to be logged in to leave comments. Login now