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