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