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