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