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