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