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