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