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