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