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