##// END OF EJS Templates
tag: add -e/--edit option for modifying the commit message
Steve Losh -
r11185:6d7cf824 default
parent child Browse files
Show More
@@ -1,4069 +1,4073 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 of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from node import hex, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, sys, difflib, time, tempfile
12 12 import hg, util, revlog, bundlerepo, extensions, copies, error
13 13 import patch, help, mdiff, url, encoding, templatekw
14 14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 15 import merge as mergemod
16 16 import minirst
17 17
18 18 # Commands start here, listed alphabetically
19 19
20 20 def add(ui, repo, *pats, **opts):
21 21 """add the specified files on the next commit
22 22
23 23 Schedule files to be version controlled and added to the
24 24 repository.
25 25
26 26 The files will be added to the repository at the next commit. To
27 27 undo an add before that, see hg forget.
28 28
29 29 If no names are given, add all files to the repository.
30 30
31 31 .. container:: verbose
32 32
33 33 An example showing how new (unknown) files are added
34 34 automatically by :hg:`add`::
35 35
36 36 $ ls
37 37 foo.c
38 38 $ hg status
39 39 ? foo.c
40 40 $ hg add
41 41 adding foo.c
42 42 $ hg status
43 43 A foo.c
44 44 """
45 45
46 46 bad = []
47 47 names = []
48 48 m = cmdutil.match(repo, pats, opts)
49 49 oldbad = m.bad
50 50 m.bad = lambda x, y: bad.append(x) or oldbad(x, y)
51 51
52 52 for f in repo.walk(m):
53 53 exact = m.exact(f)
54 54 if exact or f not in repo.dirstate:
55 55 names.append(f)
56 56 if ui.verbose or not exact:
57 57 ui.status(_('adding %s\n') % m.rel(f))
58 58 if not opts.get('dry_run'):
59 59 bad += [f for f in repo.add(names) if f in m.files()]
60 60 return bad and 1 or 0
61 61
62 62 def addremove(ui, repo, *pats, **opts):
63 63 """add all new files, delete all missing files
64 64
65 65 Add all new files and remove all missing files from the
66 66 repository.
67 67
68 68 New files are ignored if they match any of the patterns in
69 69 .hgignore. As with add, these changes take effect at the next
70 70 commit.
71 71
72 72 Use the -s/--similarity option to detect renamed files. With a
73 73 parameter greater than 0, this compares every removed file with
74 74 every added file and records those similar enough as renames. This
75 75 option takes a percentage between 0 (disabled) and 100 (files must
76 76 be identical) as its parameter. Detecting renamed files this way
77 77 can be expensive.
78 78
79 79 Returns 0 if all files are successfully added.
80 80 """
81 81 try:
82 82 sim = float(opts.get('similarity') or 0)
83 83 except ValueError:
84 84 raise util.Abort(_('similarity must be a number'))
85 85 if sim < 0 or sim > 100:
86 86 raise util.Abort(_('similarity must be between 0 and 100'))
87 87 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
88 88
89 89 def annotate(ui, repo, *pats, **opts):
90 90 """show changeset information by line for each file
91 91
92 92 List changes in files, showing the revision id responsible for
93 93 each line
94 94
95 95 This command is useful for discovering when a change was made and
96 96 by whom.
97 97
98 98 Without the -a/--text option, annotate will avoid processing files
99 99 it detects as binary. With -a, annotate will annotate the file
100 100 anyway, although the results will probably be neither useful
101 101 nor desirable.
102 102
103 103 Returns 0 on success.
104 104 """
105 105 if opts.get('follow'):
106 106 # --follow is deprecated and now just an alias for -f/--file
107 107 # to mimic the behavior of Mercurial before version 1.5
108 108 opts['file'] = 1
109 109
110 110 datefunc = ui.quiet and util.shortdate or util.datestr
111 111 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
112 112
113 113 if not pats:
114 114 raise util.Abort(_('at least one filename or pattern is required'))
115 115
116 116 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
117 117 ('number', lambda x: str(x[0].rev())),
118 118 ('changeset', lambda x: short(x[0].node())),
119 119 ('date', getdate),
120 120 ('file', lambda x: x[0].path()),
121 121 ]
122 122
123 123 if (not opts.get('user') and not opts.get('changeset')
124 124 and not opts.get('date') and not opts.get('file')):
125 125 opts['number'] = 1
126 126
127 127 linenumber = opts.get('line_number') is not None
128 128 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
129 129 raise util.Abort(_('at least one of -n/-c is required for -l'))
130 130
131 131 funcmap = [func for op, func in opmap if opts.get(op)]
132 132 if linenumber:
133 133 lastfunc = funcmap[-1]
134 134 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
135 135
136 136 ctx = repo[opts.get('rev')]
137 137 m = cmdutil.match(repo, pats, opts)
138 138 follow = not opts.get('no_follow')
139 139 for abs in ctx.walk(m):
140 140 fctx = ctx[abs]
141 141 if not opts.get('text') and util.binary(fctx.data()):
142 142 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
143 143 continue
144 144
145 145 lines = fctx.annotate(follow=follow, linenumber=linenumber)
146 146 pieces = []
147 147
148 148 for f in funcmap:
149 149 l = [f(n) for n, dummy in lines]
150 150 if l:
151 151 ml = max(map(len, l))
152 152 pieces.append(["%*s" % (ml, x) for x in l])
153 153
154 154 if pieces:
155 155 for p, l in zip(zip(*pieces), lines):
156 156 ui.write("%s: %s" % (" ".join(p), l[1]))
157 157
158 158 def archive(ui, repo, dest, **opts):
159 159 '''create an unversioned archive of a repository revision
160 160
161 161 By default, the revision used is the parent of the working
162 162 directory; use -r/--rev to specify a different revision.
163 163
164 164 The archive type is automatically detected based on file
165 165 extension (or override using -t/--type).
166 166
167 167 Valid types are:
168 168
169 169 :``files``: a directory full of files (default)
170 170 :``tar``: tar archive, uncompressed
171 171 :``tbz2``: tar archive, compressed using bzip2
172 172 :``tgz``: tar archive, compressed using gzip
173 173 :``uzip``: zip archive, uncompressed
174 174 :``zip``: zip archive, compressed using deflate
175 175
176 176 The exact name of the destination archive or directory is given
177 177 using a format string; see :hg:`help export` for details.
178 178
179 179 Each member added to an archive file has a directory prefix
180 180 prepended. Use -p/--prefix to specify a format string for the
181 181 prefix. The default is the basename of the archive, with suffixes
182 182 removed.
183 183
184 184 Returns 0 on success.
185 185 '''
186 186
187 187 ctx = repo[opts.get('rev')]
188 188 if not ctx:
189 189 raise util.Abort(_('no working directory: please specify a revision'))
190 190 node = ctx.node()
191 191 dest = cmdutil.make_filename(repo, dest, node)
192 192 if os.path.realpath(dest) == repo.root:
193 193 raise util.Abort(_('repository root cannot be destination'))
194 194
195 195 def guess_type():
196 196 exttypes = {
197 197 'tar': ['.tar'],
198 198 'tbz2': ['.tbz2', '.tar.bz2'],
199 199 'tgz': ['.tgz', '.tar.gz'],
200 200 'zip': ['.zip'],
201 201 }
202 202
203 203 for type, extensions in exttypes.items():
204 204 if util.any(dest.endswith(ext) for ext in extensions):
205 205 return type
206 206 return None
207 207
208 208 kind = opts.get('type') or guess_type() or 'files'
209 209 prefix = opts.get('prefix')
210 210
211 211 if dest == '-':
212 212 if kind == 'files':
213 213 raise util.Abort(_('cannot archive plain files to stdout'))
214 214 dest = sys.stdout
215 215 if not prefix:
216 216 prefix = os.path.basename(repo.root) + '-%h'
217 217
218 218 prefix = cmdutil.make_filename(repo, prefix, node)
219 219 matchfn = cmdutil.match(repo, [], opts)
220 220 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
221 221 matchfn, prefix)
222 222
223 223 def backout(ui, repo, node=None, rev=None, **opts):
224 224 '''reverse effect of earlier changeset
225 225
226 226 Commit the backed out changes as a new changeset. The new
227 227 changeset is a child of the backed out changeset.
228 228
229 229 If you backout a changeset other than the tip, a new head is
230 230 created. This head will be the new tip and you should merge this
231 231 backout changeset with another head.
232 232
233 233 The --merge option remembers the parent of the working directory
234 234 before starting the backout, then merges the new head with that
235 235 changeset afterwards. This saves you from doing the merge by hand.
236 236 The result of this merge is not committed, as with a normal merge.
237 237
238 238 See :hg:`help dates` for a list of formats valid for -d/--date.
239 239
240 240 Returns 0 on success.
241 241 '''
242 242 if rev and node:
243 243 raise util.Abort(_("please specify just one revision"))
244 244
245 245 if not rev:
246 246 rev = node
247 247
248 248 if not rev:
249 249 raise util.Abort(_("please specify a revision to backout"))
250 250
251 251 date = opts.get('date')
252 252 if date:
253 253 opts['date'] = util.parsedate(date)
254 254
255 255 cmdutil.bail_if_changed(repo)
256 256 node = repo.lookup(rev)
257 257
258 258 op1, op2 = repo.dirstate.parents()
259 259 a = repo.changelog.ancestor(op1, node)
260 260 if a != node:
261 261 raise util.Abort(_('cannot backout change on a different branch'))
262 262
263 263 p1, p2 = repo.changelog.parents(node)
264 264 if p1 == nullid:
265 265 raise util.Abort(_('cannot backout a change with no parents'))
266 266 if p2 != nullid:
267 267 if not opts.get('parent'):
268 268 raise util.Abort(_('cannot backout a merge changeset without '
269 269 '--parent'))
270 270 p = repo.lookup(opts['parent'])
271 271 if p not in (p1, p2):
272 272 raise util.Abort(_('%s is not a parent of %s') %
273 273 (short(p), short(node)))
274 274 parent = p
275 275 else:
276 276 if opts.get('parent'):
277 277 raise util.Abort(_('cannot use --parent on non-merge changeset'))
278 278 parent = p1
279 279
280 280 # the backout should appear on the same branch
281 281 branch = repo.dirstate.branch()
282 282 hg.clean(repo, node, show_stats=False)
283 283 repo.dirstate.setbranch(branch)
284 284 revert_opts = opts.copy()
285 285 revert_opts['date'] = None
286 286 revert_opts['all'] = True
287 287 revert_opts['rev'] = hex(parent)
288 288 revert_opts['no_backup'] = None
289 289 revert(ui, repo, **revert_opts)
290 290 commit_opts = opts.copy()
291 291 commit_opts['addremove'] = False
292 292 if not commit_opts['message'] and not commit_opts['logfile']:
293 293 # we don't translate commit messages
294 294 commit_opts['message'] = "Backed out changeset %s" % short(node)
295 295 commit_opts['force_editor'] = True
296 296 commit(ui, repo, **commit_opts)
297 297 def nice(node):
298 298 return '%d:%s' % (repo.changelog.rev(node), short(node))
299 299 ui.status(_('changeset %s backs out changeset %s\n') %
300 300 (nice(repo.changelog.tip()), nice(node)))
301 301 if op1 != node:
302 302 hg.clean(repo, op1, show_stats=False)
303 303 if opts.get('merge'):
304 304 ui.status(_('merging with changeset %s\n')
305 305 % nice(repo.changelog.tip()))
306 306 hg.merge(repo, hex(repo.changelog.tip()))
307 307 else:
308 308 ui.status(_('the backout changeset is a new head - '
309 309 'do not forget to merge\n'))
310 310 ui.status(_('(use "backout --merge" '
311 311 'if you want to auto-merge)\n'))
312 312
313 313 def bisect(ui, repo, rev=None, extra=None, command=None,
314 314 reset=None, good=None, bad=None, skip=None, noupdate=None):
315 315 """subdivision search of changesets
316 316
317 317 This command helps to find changesets which introduce problems. To
318 318 use, mark the earliest changeset you know exhibits the problem as
319 319 bad, then mark the latest changeset which is free from the problem
320 320 as good. Bisect will update your working directory to a revision
321 321 for testing (unless the -U/--noupdate option is specified). Once
322 322 you have performed tests, mark the working directory as good or
323 323 bad, and bisect will either update to another candidate changeset
324 324 or announce that it has found the bad revision.
325 325
326 326 As a shortcut, you can also use the revision argument to mark a
327 327 revision as good or bad without checking it out first.
328 328
329 329 If you supply a command, it will be used for automatic bisection.
330 330 Its exit status will be used to mark revisions as good or bad:
331 331 status 0 means good, 125 means to skip the revision, 127
332 332 (command not found) will abort the bisection, and any other
333 333 non-zero exit status means the revision is bad.
334 334
335 335 Returns 0 on success.
336 336 """
337 337 def print_result(nodes, good):
338 338 displayer = cmdutil.show_changeset(ui, repo, {})
339 339 if len(nodes) == 1:
340 340 # narrowed it down to a single revision
341 341 if good:
342 342 ui.write(_("The first good revision is:\n"))
343 343 else:
344 344 ui.write(_("The first bad revision is:\n"))
345 345 displayer.show(repo[nodes[0]])
346 346 else:
347 347 # multiple possible revisions
348 348 if good:
349 349 ui.write(_("Due to skipped revisions, the first "
350 350 "good revision could be any of:\n"))
351 351 else:
352 352 ui.write(_("Due to skipped revisions, the first "
353 353 "bad revision could be any of:\n"))
354 354 for n in nodes:
355 355 displayer.show(repo[n])
356 356 displayer.close()
357 357
358 358 def check_state(state, interactive=True):
359 359 if not state['good'] or not state['bad']:
360 360 if (good or bad or skip or reset) and interactive:
361 361 return
362 362 if not state['good']:
363 363 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 364 else:
365 365 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 366 return True
367 367
368 368 # backward compatibility
369 369 if rev in "good bad reset init".split():
370 370 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 371 cmd, rev, extra = rev, extra, None
372 372 if cmd == "good":
373 373 good = True
374 374 elif cmd == "bad":
375 375 bad = True
376 376 else:
377 377 reset = True
378 378 elif extra or good + bad + skip + reset + bool(command) > 1:
379 379 raise util.Abort(_('incompatible arguments'))
380 380
381 381 if reset:
382 382 p = repo.join("bisect.state")
383 383 if os.path.exists(p):
384 384 os.unlink(p)
385 385 return
386 386
387 387 state = hbisect.load_state(repo)
388 388
389 389 if command:
390 390 changesets = 1
391 391 try:
392 392 while changesets:
393 393 # update state
394 394 status = util.system(command)
395 395 if status == 125:
396 396 transition = "skip"
397 397 elif status == 0:
398 398 transition = "good"
399 399 # status < 0 means process was killed
400 400 elif status == 127:
401 401 raise util.Abort(_("failed to execute %s") % command)
402 402 elif status < 0:
403 403 raise util.Abort(_("%s killed") % command)
404 404 else:
405 405 transition = "bad"
406 406 ctx = repo[rev or '.']
407 407 state[transition].append(ctx.node())
408 408 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
409 409 check_state(state, interactive=False)
410 410 # bisect
411 411 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
412 412 # update to next check
413 413 cmdutil.bail_if_changed(repo)
414 414 hg.clean(repo, nodes[0], show_stats=False)
415 415 finally:
416 416 hbisect.save_state(repo, state)
417 417 print_result(nodes, good)
418 418 return
419 419
420 420 # update state
421 421 node = repo.lookup(rev or '.')
422 422 if good or bad or skip:
423 423 if good:
424 424 state['good'].append(node)
425 425 elif bad:
426 426 state['bad'].append(node)
427 427 elif skip:
428 428 state['skip'].append(node)
429 429 hbisect.save_state(repo, state)
430 430
431 431 if not check_state(state):
432 432 return
433 433
434 434 # actually bisect
435 435 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
436 436 if changesets == 0:
437 437 print_result(nodes, good)
438 438 else:
439 439 assert len(nodes) == 1 # only a single node can be tested next
440 440 node = nodes[0]
441 441 # compute the approximate number of remaining tests
442 442 tests, size = 0, 2
443 443 while size <= changesets:
444 444 tests, size = tests + 1, size * 2
445 445 rev = repo.changelog.rev(node)
446 446 ui.write(_("Testing changeset %d:%s "
447 447 "(%d changesets remaining, ~%d tests)\n")
448 448 % (rev, short(node), changesets, tests))
449 449 if not noupdate:
450 450 cmdutil.bail_if_changed(repo)
451 451 return hg.clean(repo, node)
452 452
453 453 def branch(ui, repo, label=None, **opts):
454 454 """set or show the current branch name
455 455
456 456 With no argument, show the current branch name. With one argument,
457 457 set the working directory branch name (the branch will not exist
458 458 in the repository until the next commit). Standard practice
459 459 recommends that primary development take place on the 'default'
460 460 branch.
461 461
462 462 Unless -f/--force is specified, branch will not let you set a
463 463 branch name that already exists, even if it's inactive.
464 464
465 465 Use -C/--clean to reset the working directory branch to that of
466 466 the parent of the working directory, negating a previous branch
467 467 change.
468 468
469 469 Use the command :hg:`update` to switch to an existing branch. Use
470 470 :hg:`commit --close-branch` to mark this branch as closed.
471 471
472 472 Returns 0 on success.
473 473 """
474 474
475 475 if opts.get('clean'):
476 476 label = repo[None].parents()[0].branch()
477 477 repo.dirstate.setbranch(label)
478 478 ui.status(_('reset working directory to branch %s\n') % label)
479 479 elif label:
480 480 utflabel = encoding.fromlocal(label)
481 481 if not opts.get('force') and utflabel in repo.branchtags():
482 482 if label not in [p.branch() for p in repo.parents()]:
483 483 raise util.Abort(_('a branch of the same name already exists'
484 484 " (use 'hg update' to switch to it)"))
485 485 repo.dirstate.setbranch(utflabel)
486 486 ui.status(_('marked working directory as branch %s\n') % label)
487 487 else:
488 488 ui.write("%s\n" % encoding.tolocal(repo.dirstate.branch()))
489 489
490 490 def branches(ui, repo, active=False, closed=False):
491 491 """list repository named branches
492 492
493 493 List the repository's named branches, indicating which ones are
494 494 inactive. If -c/--closed is specified, also list branches which have
495 495 been marked closed (see hg commit --close-branch).
496 496
497 497 If -a/--active is specified, only show active branches. A branch
498 498 is considered active if it contains repository heads.
499 499
500 500 Use the command :hg:`update` to switch to an existing branch.
501 501
502 502 Returns 0.
503 503 """
504 504
505 505 hexfunc = ui.debugflag and hex or short
506 506 activebranches = [repo[n].branch() for n in repo.heads()]
507 507 def testactive(tag, node):
508 508 realhead = tag in activebranches
509 509 open = node in repo.branchheads(tag, closed=False)
510 510 return realhead and open
511 511 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
512 512 for tag, node in repo.branchtags().items()],
513 513 reverse=True)
514 514
515 515 for isactive, node, tag in branches:
516 516 if (not active) or isactive:
517 517 encodedtag = encoding.tolocal(tag)
518 518 if ui.quiet:
519 519 ui.write("%s\n" % encodedtag)
520 520 else:
521 521 hn = repo.lookup(node)
522 522 if isactive:
523 523 notice = ''
524 524 elif hn not in repo.branchheads(tag, closed=False):
525 525 if not closed:
526 526 continue
527 527 notice = _(' (closed)')
528 528 else:
529 529 notice = _(' (inactive)')
530 530 rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
531 531 data = encodedtag, rev, hexfunc(hn), notice
532 532 ui.write("%s %s:%s%s\n" % data)
533 533
534 534 def bundle(ui, repo, fname, dest=None, **opts):
535 535 """create a changegroup file
536 536
537 537 Generate a compressed changegroup file collecting changesets not
538 538 known to be in another repository.
539 539
540 540 If you omit the destination repository, then hg assumes the
541 541 destination will have all the nodes you specify with --base
542 542 parameters. To create a bundle containing all changesets, use
543 543 -a/--all (or --base null).
544 544
545 545 You can change compression method with the -t/--type option.
546 546 The available compression methods are: none, bzip2, and
547 547 gzip (by default, bundles are compressed using bzip2).
548 548
549 549 The bundle file can then be transferred using conventional means
550 550 and applied to another repository with the unbundle or pull
551 551 command. This is useful when direct push and pull are not
552 552 available or when exporting an entire repository is undesirable.
553 553
554 554 Applying bundles preserves all changeset contents including
555 555 permissions, copy/rename information, and revision history.
556 556
557 557 Returns 0 on success, 1 if no changes found.
558 558 """
559 559 revs = opts.get('rev') or None
560 560 if revs:
561 561 revs = [repo.lookup(rev) for rev in revs]
562 562 if opts.get('all'):
563 563 base = ['null']
564 564 else:
565 565 base = opts.get('base')
566 566 if base:
567 567 if dest:
568 568 raise util.Abort(_("--base is incompatible with specifying "
569 569 "a destination"))
570 570 base = [repo.lookup(rev) for rev in base]
571 571 # create the right base
572 572 # XXX: nodesbetween / changegroup* should be "fixed" instead
573 573 o = []
574 574 has = set((nullid,))
575 575 for n in base:
576 576 has.update(repo.changelog.reachable(n))
577 577 if revs:
578 578 visit = list(revs)
579 579 has.difference_update(revs)
580 580 else:
581 581 visit = repo.changelog.heads()
582 582 seen = {}
583 583 while visit:
584 584 n = visit.pop(0)
585 585 parents = [p for p in repo.changelog.parents(n) if p not in has]
586 586 if len(parents) == 0:
587 587 if n not in has:
588 588 o.append(n)
589 589 else:
590 590 for p in parents:
591 591 if p not in seen:
592 592 seen[p] = 1
593 593 visit.append(p)
594 594 else:
595 595 dest = ui.expandpath(dest or 'default-push', dest or 'default')
596 596 dest, branches = hg.parseurl(dest, opts.get('branch'))
597 597 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
598 598 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
599 599 o = repo.findoutgoing(other, force=opts.get('force'))
600 600
601 601 if not o:
602 602 ui.status(_("no changes found\n"))
603 603 return 1
604 604
605 605 if revs:
606 606 cg = repo.changegroupsubset(o, revs, 'bundle')
607 607 else:
608 608 cg = repo.changegroup(o, 'bundle')
609 609
610 610 bundletype = opts.get('type', 'bzip2').lower()
611 611 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
612 612 bundletype = btypes.get(bundletype)
613 613 if bundletype not in changegroup.bundletypes:
614 614 raise util.Abort(_('unknown bundle type specified with --type'))
615 615
616 616 changegroup.writebundle(cg, fname, bundletype)
617 617
618 618 def cat(ui, repo, file1, *pats, **opts):
619 619 """output the current or given revision of files
620 620
621 621 Print the specified files as they were at the given revision. If
622 622 no revision is given, the parent of the working directory is used,
623 623 or tip if no revision is checked out.
624 624
625 625 Output may be to a file, in which case the name of the file is
626 626 given using a format string. The formatting rules are the same as
627 627 for the export command, with the following additions:
628 628
629 629 :``%s``: basename of file being printed
630 630 :``%d``: dirname of file being printed, or '.' if in repository root
631 631 :``%p``: root-relative path name of file being printed
632 632
633 633 Returns 0 on success.
634 634 """
635 635 ctx = repo[opts.get('rev')]
636 636 err = 1
637 637 m = cmdutil.match(repo, (file1,) + pats, opts)
638 638 for abs in ctx.walk(m):
639 639 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
640 640 data = ctx[abs].data()
641 641 if opts.get('decode'):
642 642 data = repo.wwritedata(abs, data)
643 643 fp.write(data)
644 644 err = 0
645 645 return err
646 646
647 647 def clone(ui, source, dest=None, **opts):
648 648 """make a copy of an existing repository
649 649
650 650 Create a copy of an existing repository in a new directory.
651 651
652 652 If no destination directory name is specified, it defaults to the
653 653 basename of the source.
654 654
655 655 The location of the source is added to the new repository's
656 656 .hg/hgrc file, as the default to be used for future pulls.
657 657
658 658 See :hg:`help urls` for valid source format details.
659 659
660 660 It is possible to specify an ``ssh://`` URL as the destination, but no
661 661 .hg/hgrc and working directory will be created on the remote side.
662 662 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
663 663
664 664 A set of changesets (tags, or branch names) to pull may be specified
665 665 by listing each changeset (tag, or branch name) with -r/--rev.
666 666 If -r/--rev is used, the cloned repository will contain only a subset
667 667 of the changesets of the source repository. Only the set of changesets
668 668 defined by all -r/--rev options (including all their ancestors)
669 669 will be pulled into the destination repository.
670 670 No subsequent changesets (including subsequent tags) will be present
671 671 in the destination.
672 672
673 673 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
674 674 local source repositories.
675 675
676 676 For efficiency, hardlinks are used for cloning whenever the source
677 677 and destination are on the same filesystem (note this applies only
678 678 to the repository data, not to the working directory). Some
679 679 filesystems, such as AFS, implement hardlinking incorrectly, but
680 680 do not report errors. In these cases, use the --pull option to
681 681 avoid hardlinking.
682 682
683 683 In some cases, you can clone repositories and the working directory
684 684 using full hardlinks with ::
685 685
686 686 $ cp -al REPO REPOCLONE
687 687
688 688 This is the fastest way to clone, but it is not always safe. The
689 689 operation is not atomic (making sure REPO is not modified during
690 690 the operation is up to you) and you have to make sure your editor
691 691 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
692 692 this is not compatible with certain extensions that place their
693 693 metadata under the .hg directory, such as mq.
694 694
695 695 Mercurial will update the working directory to the first applicable
696 696 revision from this list:
697 697
698 698 a) null if -U or the source repository has no changesets
699 699 b) if -u . and the source repository is local, the first parent of
700 700 the source repository's working directory
701 701 c) the changeset specified with -u (if a branch name, this means the
702 702 latest head of that branch)
703 703 d) the changeset specified with -r
704 704 e) the tipmost head specified with -b
705 705 f) the tipmost head specified with the url#branch source syntax
706 706 g) the tipmost head of the default branch
707 707 h) tip
708 708
709 709 Returns 0 on success.
710 710 """
711 711 if opts.get('noupdate') and opts.get('updaterev'):
712 712 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
713 713
714 714 r = hg.clone(cmdutil.remoteui(ui, opts), source, dest,
715 715 pull=opts.get('pull'),
716 716 stream=opts.get('uncompressed'),
717 717 rev=opts.get('rev'),
718 718 update=opts.get('updaterev') or not opts.get('noupdate'),
719 719 branch=opts.get('branch'))
720 720
721 721 return r is None
722 722
723 723 def commit(ui, repo, *pats, **opts):
724 724 """commit the specified files or all outstanding changes
725 725
726 726 Commit changes to the given files into the repository. Unlike a
727 727 centralized RCS, this operation is a local operation. See hg push
728 728 for a way to actively distribute your changes.
729 729
730 730 If a list of files is omitted, all changes reported by :hg:`status`
731 731 will be committed.
732 732
733 733 If you are committing the result of a merge, do not provide any
734 734 filenames or -I/-X filters.
735 735
736 736 If no commit message is specified, the configured editor is
737 737 started to prompt you for a message.
738 738
739 739 See :hg:`help dates` for a list of formats valid for -d/--date.
740 740
741 741 Returns 0 on success, 1 if nothing changed.
742 742 """
743 743 extra = {}
744 744 if opts.get('close_branch'):
745 745 if repo['.'].node() not in repo.branchheads():
746 746 # The topo heads set is included in the branch heads set of the
747 747 # current branch, so it's sufficient to test branchheads
748 748 raise util.Abort(_('can only close branch heads'))
749 749 extra['close'] = 1
750 750 e = cmdutil.commiteditor
751 751 if opts.get('force_editor'):
752 752 e = cmdutil.commitforceeditor
753 753
754 754 def commitfunc(ui, repo, message, match, opts):
755 755 return repo.commit(message, opts.get('user'), opts.get('date'), match,
756 756 editor=e, extra=extra)
757 757
758 758 branch = repo[None].branch()
759 759 bheads = repo.branchheads(branch)
760 760
761 761 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
762 762 if not node:
763 763 ui.status(_("nothing changed\n"))
764 764 return 1
765 765
766 766 ctx = repo[node]
767 767 parents = ctx.parents()
768 768
769 769 if bheads and [x for x in parents
770 770 if x.node() not in bheads and x.branch() == branch]:
771 771 ui.status(_('created new head\n'))
772 772
773 773 if not opts.get('close_branch'):
774 774 for r in parents:
775 775 if r.extra().get('close'):
776 776 ui.status(_('reopening closed branch head %d\n') % r)
777 777
778 778 if ui.debugflag:
779 779 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
780 780 elif ui.verbose:
781 781 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
782 782
783 783 def copy(ui, repo, *pats, **opts):
784 784 """mark files as copied for the next commit
785 785
786 786 Mark dest as having copies of source files. If dest is a
787 787 directory, copies are put in that directory. If dest is a file,
788 788 the source must be a single file.
789 789
790 790 By default, this command copies the contents of files as they
791 791 exist in the working directory. If invoked with -A/--after, the
792 792 operation is recorded, but no copying is performed.
793 793
794 794 This command takes effect with the next commit. To undo a copy
795 795 before that, see hg revert.
796 796
797 797 Returns 0 on success, 1 if errors are encountered.
798 798 """
799 799 wlock = repo.wlock(False)
800 800 try:
801 801 return cmdutil.copy(ui, repo, pats, opts)
802 802 finally:
803 803 wlock.release()
804 804
805 805 def debugancestor(ui, repo, *args):
806 806 """find the ancestor revision of two revisions in a given index"""
807 807 if len(args) == 3:
808 808 index, rev1, rev2 = args
809 809 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
810 810 lookup = r.lookup
811 811 elif len(args) == 2:
812 812 if not repo:
813 813 raise util.Abort(_("There is no Mercurial repository here "
814 814 "(.hg not found)"))
815 815 rev1, rev2 = args
816 816 r = repo.changelog
817 817 lookup = repo.lookup
818 818 else:
819 819 raise util.Abort(_('either two or three arguments required'))
820 820 a = r.ancestor(lookup(rev1), lookup(rev2))
821 821 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
822 822
823 823 def debugcommands(ui, cmd='', *args):
824 824 """list all available commands and options"""
825 825 for cmd, vals in sorted(table.iteritems()):
826 826 cmd = cmd.split('|')[0].strip('^')
827 827 opts = ', '.join([i[1] for i in vals[1]])
828 828 ui.write('%s: %s\n' % (cmd, opts))
829 829
830 830 def debugcomplete(ui, cmd='', **opts):
831 831 """returns the completion list associated with the given command"""
832 832
833 833 if opts.get('options'):
834 834 options = []
835 835 otables = [globalopts]
836 836 if cmd:
837 837 aliases, entry = cmdutil.findcmd(cmd, table, False)
838 838 otables.append(entry[1])
839 839 for t in otables:
840 840 for o in t:
841 841 if "(DEPRECATED)" in o[3]:
842 842 continue
843 843 if o[0]:
844 844 options.append('-%s' % o[0])
845 845 options.append('--%s' % o[1])
846 846 ui.write("%s\n" % "\n".join(options))
847 847 return
848 848
849 849 cmdlist = cmdutil.findpossible(cmd, table)
850 850 if ui.verbose:
851 851 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
852 852 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
853 853
854 854 def debugfsinfo(ui, path = "."):
855 855 """show information detected about current filesystem"""
856 856 open('.debugfsinfo', 'w').write('')
857 857 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
858 858 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
859 859 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
860 860 and 'yes' or 'no'))
861 861 os.unlink('.debugfsinfo')
862 862
863 863 def debugrebuildstate(ui, repo, rev="tip"):
864 864 """rebuild the dirstate as it would look like for the given revision"""
865 865 ctx = repo[rev]
866 866 wlock = repo.wlock()
867 867 try:
868 868 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
869 869 finally:
870 870 wlock.release()
871 871
872 872 def debugcheckstate(ui, repo):
873 873 """validate the correctness of the current dirstate"""
874 874 parent1, parent2 = repo.dirstate.parents()
875 875 m1 = repo[parent1].manifest()
876 876 m2 = repo[parent2].manifest()
877 877 errors = 0
878 878 for f in repo.dirstate:
879 879 state = repo.dirstate[f]
880 880 if state in "nr" and f not in m1:
881 881 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
882 882 errors += 1
883 883 if state in "a" and f in m1:
884 884 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
885 885 errors += 1
886 886 if state in "m" and f not in m1 and f not in m2:
887 887 ui.warn(_("%s in state %s, but not in either manifest\n") %
888 888 (f, state))
889 889 errors += 1
890 890 for f in m1:
891 891 state = repo.dirstate[f]
892 892 if state not in "nrm":
893 893 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
894 894 errors += 1
895 895 if errors:
896 896 error = _(".hg/dirstate inconsistent with current parent's manifest")
897 897 raise util.Abort(error)
898 898
899 899 def showconfig(ui, repo, *values, **opts):
900 900 """show combined config settings from all hgrc files
901 901
902 902 With no arguments, print names and values of all config items.
903 903
904 904 With one argument of the form section.name, print just the value
905 905 of that config item.
906 906
907 907 With multiple arguments, print names and values of all config
908 908 items with matching section names.
909 909
910 910 With --debug, the source (filename and line number) is printed
911 911 for each config item.
912 912
913 913 Returns 0 on success.
914 914 """
915 915
916 916 for f in util.rcpath():
917 917 ui.debug(_('read config from: %s\n') % f)
918 918 untrusted = bool(opts.get('untrusted'))
919 919 if values:
920 920 if len([v for v in values if '.' in v]) > 1:
921 921 raise util.Abort(_('only one config item permitted'))
922 922 for section, name, value in ui.walkconfig(untrusted=untrusted):
923 923 sectname = section + '.' + name
924 924 if values:
925 925 for v in values:
926 926 if v == section:
927 927 ui.debug('%s: ' %
928 928 ui.configsource(section, name, untrusted))
929 929 ui.write('%s=%s\n' % (sectname, value))
930 930 elif v == sectname:
931 931 ui.debug('%s: ' %
932 932 ui.configsource(section, name, untrusted))
933 933 ui.write(value, '\n')
934 934 else:
935 935 ui.debug('%s: ' %
936 936 ui.configsource(section, name, untrusted))
937 937 ui.write('%s=%s\n' % (sectname, value))
938 938
939 939 def debugsetparents(ui, repo, rev1, rev2=None):
940 940 """manually set the parents of the current working directory
941 941
942 942 This is useful for writing repository conversion tools, but should
943 943 be used with care.
944 944
945 945 Returns 0 on success.
946 946 """
947 947
948 948 if not rev2:
949 949 rev2 = hex(nullid)
950 950
951 951 wlock = repo.wlock()
952 952 try:
953 953 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
954 954 finally:
955 955 wlock.release()
956 956
957 957 def debugstate(ui, repo, nodates=None):
958 958 """show the contents of the current dirstate"""
959 959 timestr = ""
960 960 showdate = not nodates
961 961 for file_, ent in sorted(repo.dirstate._map.iteritems()):
962 962 if showdate:
963 963 if ent[3] == -1:
964 964 # Pad or slice to locale representation
965 965 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
966 966 time.localtime(0)))
967 967 timestr = 'unset'
968 968 timestr = (timestr[:locale_len] +
969 969 ' ' * (locale_len - len(timestr)))
970 970 else:
971 971 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
972 972 time.localtime(ent[3]))
973 973 if ent[1] & 020000:
974 974 mode = 'lnk'
975 975 else:
976 976 mode = '%3o' % (ent[1] & 0777)
977 977 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
978 978 for f in repo.dirstate.copies():
979 979 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
980 980
981 981 def debugsub(ui, repo, rev=None):
982 982 if rev == '':
983 983 rev = None
984 984 for k, v in sorted(repo[rev].substate.items()):
985 985 ui.write('path %s\n' % k)
986 986 ui.write(' source %s\n' % v[0])
987 987 ui.write(' revision %s\n' % v[1])
988 988
989 989 def debugdata(ui, file_, rev):
990 990 """dump the contents of a data file revision"""
991 991 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
992 992 try:
993 993 ui.write(r.revision(r.lookup(rev)))
994 994 except KeyError:
995 995 raise util.Abort(_('invalid revision identifier %s') % rev)
996 996
997 997 def debugdate(ui, date, range=None, **opts):
998 998 """parse and display a date"""
999 999 if opts["extended"]:
1000 1000 d = util.parsedate(date, util.extendeddateformats)
1001 1001 else:
1002 1002 d = util.parsedate(date)
1003 1003 ui.write("internal: %s %s\n" % d)
1004 1004 ui.write("standard: %s\n" % util.datestr(d))
1005 1005 if range:
1006 1006 m = util.matchdate(range)
1007 1007 ui.write("match: %s\n" % m(d[0]))
1008 1008
1009 1009 def debugindex(ui, file_):
1010 1010 """dump the contents of an index file"""
1011 1011 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1012 1012 ui.write(" rev offset length base linkrev"
1013 1013 " nodeid p1 p2\n")
1014 1014 for i in r:
1015 1015 node = r.node(i)
1016 1016 try:
1017 1017 pp = r.parents(node)
1018 1018 except:
1019 1019 pp = [nullid, nullid]
1020 1020 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1021 1021 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1022 1022 short(node), short(pp[0]), short(pp[1])))
1023 1023
1024 1024 def debugindexdot(ui, file_):
1025 1025 """dump an index DAG as a graphviz dot file"""
1026 1026 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1027 1027 ui.write("digraph G {\n")
1028 1028 for i in r:
1029 1029 node = r.node(i)
1030 1030 pp = r.parents(node)
1031 1031 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1032 1032 if pp[1] != nullid:
1033 1033 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1034 1034 ui.write("}\n")
1035 1035
1036 1036 def debuginstall(ui):
1037 1037 '''test Mercurial installation
1038 1038
1039 1039 Returns 0 on success.
1040 1040 '''
1041 1041
1042 1042 def writetemp(contents):
1043 1043 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1044 1044 f = os.fdopen(fd, "wb")
1045 1045 f.write(contents)
1046 1046 f.close()
1047 1047 return name
1048 1048
1049 1049 problems = 0
1050 1050
1051 1051 # encoding
1052 1052 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1053 1053 try:
1054 1054 encoding.fromlocal("test")
1055 1055 except util.Abort, inst:
1056 1056 ui.write(" %s\n" % inst)
1057 1057 ui.write(_(" (check that your locale is properly set)\n"))
1058 1058 problems += 1
1059 1059
1060 1060 # compiled modules
1061 1061 ui.status(_("Checking extensions...\n"))
1062 1062 try:
1063 1063 import bdiff, mpatch, base85
1064 1064 except Exception, inst:
1065 1065 ui.write(" %s\n" % inst)
1066 1066 ui.write(_(" One or more extensions could not be found"))
1067 1067 ui.write(_(" (check that you compiled the extensions)\n"))
1068 1068 problems += 1
1069 1069
1070 1070 # templates
1071 1071 ui.status(_("Checking templates...\n"))
1072 1072 try:
1073 1073 import templater
1074 1074 templater.templater(templater.templatepath("map-cmdline.default"))
1075 1075 except Exception, inst:
1076 1076 ui.write(" %s\n" % inst)
1077 1077 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1078 1078 problems += 1
1079 1079
1080 1080 # patch
1081 1081 ui.status(_("Checking patch...\n"))
1082 1082 patchproblems = 0
1083 1083 a = "1\n2\n3\n4\n"
1084 1084 b = "1\n2\n3\ninsert\n4\n"
1085 1085 fa = writetemp(a)
1086 1086 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1087 1087 os.path.basename(fa))
1088 1088 fd = writetemp(d)
1089 1089
1090 1090 files = {}
1091 1091 try:
1092 1092 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1093 1093 except util.Abort, e:
1094 1094 ui.write(_(" patch call failed:\n"))
1095 1095 ui.write(" " + str(e) + "\n")
1096 1096 patchproblems += 1
1097 1097 else:
1098 1098 if list(files) != [os.path.basename(fa)]:
1099 1099 ui.write(_(" unexpected patch output!\n"))
1100 1100 patchproblems += 1
1101 1101 a = open(fa).read()
1102 1102 if a != b:
1103 1103 ui.write(_(" patch test failed!\n"))
1104 1104 patchproblems += 1
1105 1105
1106 1106 if patchproblems:
1107 1107 if ui.config('ui', 'patch'):
1108 1108 ui.write(_(" (Current patch tool may be incompatible with patch,"
1109 1109 " or misconfigured. Please check your .hgrc file)\n"))
1110 1110 else:
1111 1111 ui.write(_(" Internal patcher failure, please report this error"
1112 1112 " to http://mercurial.selenic.com/bts/\n"))
1113 1113 problems += patchproblems
1114 1114
1115 1115 os.unlink(fa)
1116 1116 os.unlink(fd)
1117 1117
1118 1118 # editor
1119 1119 ui.status(_("Checking commit editor...\n"))
1120 1120 editor = ui.geteditor()
1121 1121 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1122 1122 if not cmdpath:
1123 1123 if editor == 'vi':
1124 1124 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1125 1125 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1126 1126 else:
1127 1127 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1128 1128 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
1129 1129 problems += 1
1130 1130
1131 1131 # check username
1132 1132 ui.status(_("Checking username...\n"))
1133 1133 try:
1134 1134 user = ui.username()
1135 1135 except util.Abort, e:
1136 1136 ui.write(" %s\n" % e)
1137 1137 ui.write(_(" (specify a username in your .hgrc file)\n"))
1138 1138 problems += 1
1139 1139
1140 1140 if not problems:
1141 1141 ui.status(_("No problems detected\n"))
1142 1142 else:
1143 1143 ui.write(_("%s problems detected,"
1144 1144 " please check your install!\n") % problems)
1145 1145
1146 1146 return problems
1147 1147
1148 1148 def debugrename(ui, repo, file1, *pats, **opts):
1149 1149 """dump rename information"""
1150 1150
1151 1151 ctx = repo[opts.get('rev')]
1152 1152 m = cmdutil.match(repo, (file1,) + pats, opts)
1153 1153 for abs in ctx.walk(m):
1154 1154 fctx = ctx[abs]
1155 1155 o = fctx.filelog().renamed(fctx.filenode())
1156 1156 rel = m.rel(abs)
1157 1157 if o:
1158 1158 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1159 1159 else:
1160 1160 ui.write(_("%s not renamed\n") % rel)
1161 1161
1162 1162 def debugwalk(ui, repo, *pats, **opts):
1163 1163 """show how files match on given patterns"""
1164 1164 m = cmdutil.match(repo, pats, opts)
1165 1165 items = list(repo.walk(m))
1166 1166 if not items:
1167 1167 return
1168 1168 fmt = 'f %%-%ds %%-%ds %%s' % (
1169 1169 max([len(abs) for abs in items]),
1170 1170 max([len(m.rel(abs)) for abs in items]))
1171 1171 for abs in items:
1172 1172 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1173 1173 ui.write("%s\n" % line.rstrip())
1174 1174
1175 1175 def diff(ui, repo, *pats, **opts):
1176 1176 """diff repository (or selected files)
1177 1177
1178 1178 Show differences between revisions for the specified files.
1179 1179
1180 1180 Differences between files are shown using the unified diff format.
1181 1181
1182 1182 NOTE: diff may generate unexpected results for merges, as it will
1183 1183 default to comparing against the working directory's first parent
1184 1184 changeset if no revisions are specified.
1185 1185
1186 1186 When two revision arguments are given, then changes are shown
1187 1187 between those revisions. If only one revision is specified then
1188 1188 that revision is compared to the working directory, and, when no
1189 1189 revisions are specified, the working directory files are compared
1190 1190 to its parent.
1191 1191
1192 1192 Alternatively you can specify -c/--change with a revision to see
1193 1193 the changes in that changeset relative to its first parent.
1194 1194
1195 1195 Without the -a/--text option, diff will avoid generating diffs of
1196 1196 files it detects as binary. With -a, diff will generate a diff
1197 1197 anyway, probably with undesirable results.
1198 1198
1199 1199 Use the -g/--git option to generate diffs in the git extended diff
1200 1200 format. For more information, read :hg:`help diffs`.
1201 1201
1202 1202 Returns 0 on success.
1203 1203 """
1204 1204
1205 1205 revs = opts.get('rev')
1206 1206 change = opts.get('change')
1207 1207 stat = opts.get('stat')
1208 1208 reverse = opts.get('reverse')
1209 1209
1210 1210 if revs and change:
1211 1211 msg = _('cannot specify --rev and --change at the same time')
1212 1212 raise util.Abort(msg)
1213 1213 elif change:
1214 1214 node2 = repo.lookup(change)
1215 1215 node1 = repo[node2].parents()[0].node()
1216 1216 else:
1217 1217 node1, node2 = cmdutil.revpair(repo, revs)
1218 1218
1219 1219 if reverse:
1220 1220 node1, node2 = node2, node1
1221 1221
1222 1222 diffopts = patch.diffopts(ui, opts)
1223 1223 m = cmdutil.match(repo, pats, opts)
1224 1224 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
1225 1225
1226 1226 def export(ui, repo, *changesets, **opts):
1227 1227 """dump the header and diffs for one or more changesets
1228 1228
1229 1229 Print the changeset header and diffs for one or more revisions.
1230 1230
1231 1231 The information shown in the changeset header is: author, date,
1232 1232 branch name (if non-default), changeset hash, parent(s) and commit
1233 1233 comment.
1234 1234
1235 1235 NOTE: export may generate unexpected diff output for merge
1236 1236 changesets, as it will compare the merge changeset against its
1237 1237 first parent only.
1238 1238
1239 1239 Output may be to a file, in which case the name of the file is
1240 1240 given using a format string. The formatting rules are as follows:
1241 1241
1242 1242 :``%%``: literal "%" character
1243 1243 :``%H``: changeset hash (40 bytes of hexadecimal)
1244 1244 :``%N``: number of patches being generated
1245 1245 :``%R``: changeset revision number
1246 1246 :``%b``: basename of the exporting repository
1247 1247 :``%h``: short-form changeset hash (12 bytes of hexadecimal)
1248 1248 :``%n``: zero-padded sequence number, starting at 1
1249 1249 :``%r``: zero-padded changeset revision number
1250 1250
1251 1251 Without the -a/--text option, export will avoid generating diffs
1252 1252 of files it detects as binary. With -a, export will generate a
1253 1253 diff anyway, probably with undesirable results.
1254 1254
1255 1255 Use the -g/--git option to generate diffs in the git extended diff
1256 1256 format. See :hg:`help diffs` for more information.
1257 1257
1258 1258 With the --switch-parent option, the diff will be against the
1259 1259 second parent. It can be useful to review a merge.
1260 1260
1261 1261 Returns 0 on success.
1262 1262 """
1263 1263 changesets += tuple(opts.get('rev', []))
1264 1264 if not changesets:
1265 1265 raise util.Abort(_("export requires at least one changeset"))
1266 1266 revs = cmdutil.revrange(repo, changesets)
1267 1267 if len(revs) > 1:
1268 1268 ui.note(_('exporting patches:\n'))
1269 1269 else:
1270 1270 ui.note(_('exporting patch:\n'))
1271 1271 cmdutil.export(repo, revs, template=opts.get('output'),
1272 1272 switch_parent=opts.get('switch_parent'),
1273 1273 opts=patch.diffopts(ui, opts))
1274 1274
1275 1275 def forget(ui, repo, *pats, **opts):
1276 1276 """forget the specified files on the next commit
1277 1277
1278 1278 Mark the specified files so they will no longer be tracked
1279 1279 after the next commit.
1280 1280
1281 1281 This only removes files from the current branch, not from the
1282 1282 entire project history, and it does not delete them from the
1283 1283 working directory.
1284 1284
1285 1285 To undo a forget before the next commit, see hg add.
1286 1286
1287 1287 Returns 0 on success.
1288 1288 """
1289 1289
1290 1290 if not pats:
1291 1291 raise util.Abort(_('no files specified'))
1292 1292
1293 1293 m = cmdutil.match(repo, pats, opts)
1294 1294 s = repo.status(match=m, clean=True)
1295 1295 forget = sorted(s[0] + s[1] + s[3] + s[6])
1296 1296 errs = 0
1297 1297
1298 1298 for f in m.files():
1299 1299 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1300 1300 ui.warn(_('not removing %s: file is already untracked\n')
1301 1301 % m.rel(f))
1302 1302 errs = 1
1303 1303
1304 1304 for f in forget:
1305 1305 if ui.verbose or not m.exact(f):
1306 1306 ui.status(_('removing %s\n') % m.rel(f))
1307 1307
1308 1308 repo.remove(forget, unlink=False)
1309 1309 return errs
1310 1310
1311 1311 def grep(ui, repo, pattern, *pats, **opts):
1312 1312 """search for a pattern in specified files and revisions
1313 1313
1314 1314 Search revisions of files for a regular expression.
1315 1315
1316 1316 This command behaves differently than Unix grep. It only accepts
1317 1317 Python/Perl regexps. It searches repository history, not the
1318 1318 working directory. It always prints the revision number in which a
1319 1319 match appears.
1320 1320
1321 1321 By default, grep only prints output for the first revision of a
1322 1322 file in which it finds a match. To get it to print every revision
1323 1323 that contains a change in match status ("-" for a match that
1324 1324 becomes a non-match, or "+" for a non-match that becomes a match),
1325 1325 use the --all flag.
1326 1326
1327 1327 Returns 0 if a match is found, 1 otherwise.
1328 1328 """
1329 1329 reflags = 0
1330 1330 if opts.get('ignore_case'):
1331 1331 reflags |= re.I
1332 1332 try:
1333 1333 regexp = re.compile(pattern, reflags)
1334 1334 except Exception, inst:
1335 1335 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1336 1336 return 1
1337 1337 sep, eol = ':', '\n'
1338 1338 if opts.get('print0'):
1339 1339 sep = eol = '\0'
1340 1340
1341 1341 getfile = util.lrucachefunc(repo.file)
1342 1342
1343 1343 def matchlines(body):
1344 1344 begin = 0
1345 1345 linenum = 0
1346 1346 while True:
1347 1347 match = regexp.search(body, begin)
1348 1348 if not match:
1349 1349 break
1350 1350 mstart, mend = match.span()
1351 1351 linenum += body.count('\n', begin, mstart) + 1
1352 1352 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1353 1353 begin = body.find('\n', mend) + 1 or len(body)
1354 1354 lend = begin - 1
1355 1355 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1356 1356
1357 1357 class linestate(object):
1358 1358 def __init__(self, line, linenum, colstart, colend):
1359 1359 self.line = line
1360 1360 self.linenum = linenum
1361 1361 self.colstart = colstart
1362 1362 self.colend = colend
1363 1363
1364 1364 def __hash__(self):
1365 1365 return hash((self.linenum, self.line))
1366 1366
1367 1367 def __eq__(self, other):
1368 1368 return self.line == other.line
1369 1369
1370 1370 matches = {}
1371 1371 copies = {}
1372 1372 def grepbody(fn, rev, body):
1373 1373 matches[rev].setdefault(fn, [])
1374 1374 m = matches[rev][fn]
1375 1375 for lnum, cstart, cend, line in matchlines(body):
1376 1376 s = linestate(line, lnum, cstart, cend)
1377 1377 m.append(s)
1378 1378
1379 1379 def difflinestates(a, b):
1380 1380 sm = difflib.SequenceMatcher(None, a, b)
1381 1381 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1382 1382 if tag == 'insert':
1383 1383 for i in xrange(blo, bhi):
1384 1384 yield ('+', b[i])
1385 1385 elif tag == 'delete':
1386 1386 for i in xrange(alo, ahi):
1387 1387 yield ('-', a[i])
1388 1388 elif tag == 'replace':
1389 1389 for i in xrange(alo, ahi):
1390 1390 yield ('-', a[i])
1391 1391 for i in xrange(blo, bhi):
1392 1392 yield ('+', b[i])
1393 1393
1394 1394 def display(fn, ctx, pstates, states):
1395 1395 rev = ctx.rev()
1396 1396 datefunc = ui.quiet and util.shortdate or util.datestr
1397 1397 found = False
1398 1398 filerevmatches = {}
1399 1399 if opts.get('all'):
1400 1400 iter = difflinestates(pstates, states)
1401 1401 else:
1402 1402 iter = [('', l) for l in states]
1403 1403 for change, l in iter:
1404 1404 cols = [fn, str(rev)]
1405 1405 before, match, after = None, None, None
1406 1406 if opts.get('line_number'):
1407 1407 cols.append(str(l.linenum))
1408 1408 if opts.get('all'):
1409 1409 cols.append(change)
1410 1410 if opts.get('user'):
1411 1411 cols.append(ui.shortuser(ctx.user()))
1412 1412 if opts.get('date'):
1413 1413 cols.append(datefunc(ctx.date()))
1414 1414 if opts.get('files_with_matches'):
1415 1415 c = (fn, rev)
1416 1416 if c in filerevmatches:
1417 1417 continue
1418 1418 filerevmatches[c] = 1
1419 1419 else:
1420 1420 before = l.line[:l.colstart]
1421 1421 match = l.line[l.colstart:l.colend]
1422 1422 after = l.line[l.colend:]
1423 1423 ui.write(sep.join(cols))
1424 1424 if before is not None:
1425 1425 ui.write(sep + before)
1426 1426 ui.write(match, label='grep.match')
1427 1427 ui.write(after)
1428 1428 ui.write(eol)
1429 1429 found = True
1430 1430 return found
1431 1431
1432 1432 skip = {}
1433 1433 revfiles = {}
1434 1434 matchfn = cmdutil.match(repo, pats, opts)
1435 1435 found = False
1436 1436 follow = opts.get('follow')
1437 1437
1438 1438 def prep(ctx, fns):
1439 1439 rev = ctx.rev()
1440 1440 pctx = ctx.parents()[0]
1441 1441 parent = pctx.rev()
1442 1442 matches.setdefault(rev, {})
1443 1443 matches.setdefault(parent, {})
1444 1444 files = revfiles.setdefault(rev, [])
1445 1445 for fn in fns:
1446 1446 flog = getfile(fn)
1447 1447 try:
1448 1448 fnode = ctx.filenode(fn)
1449 1449 except error.LookupError:
1450 1450 continue
1451 1451
1452 1452 copied = flog.renamed(fnode)
1453 1453 copy = follow and copied and copied[0]
1454 1454 if copy:
1455 1455 copies.setdefault(rev, {})[fn] = copy
1456 1456 if fn in skip:
1457 1457 if copy:
1458 1458 skip[copy] = True
1459 1459 continue
1460 1460 files.append(fn)
1461 1461
1462 1462 if fn not in matches[rev]:
1463 1463 grepbody(fn, rev, flog.read(fnode))
1464 1464
1465 1465 pfn = copy or fn
1466 1466 if pfn not in matches[parent]:
1467 1467 try:
1468 1468 fnode = pctx.filenode(pfn)
1469 1469 grepbody(pfn, parent, flog.read(fnode))
1470 1470 except error.LookupError:
1471 1471 pass
1472 1472
1473 1473 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1474 1474 rev = ctx.rev()
1475 1475 parent = ctx.parents()[0].rev()
1476 1476 for fn in sorted(revfiles.get(rev, [])):
1477 1477 states = matches[rev][fn]
1478 1478 copy = copies.get(rev, {}).get(fn)
1479 1479 if fn in skip:
1480 1480 if copy:
1481 1481 skip[copy] = True
1482 1482 continue
1483 1483 pstates = matches.get(parent, {}).get(copy or fn, [])
1484 1484 if pstates or states:
1485 1485 r = display(fn, ctx, pstates, states)
1486 1486 found = found or r
1487 1487 if r and not opts.get('all'):
1488 1488 skip[fn] = True
1489 1489 if copy:
1490 1490 skip[copy] = True
1491 1491 del matches[rev]
1492 1492 del revfiles[rev]
1493 1493
1494 1494 return not found
1495 1495
1496 1496 def heads(ui, repo, *branchrevs, **opts):
1497 1497 """show current repository heads or show branch heads
1498 1498
1499 1499 With no arguments, show all repository branch heads.
1500 1500
1501 1501 Repository "heads" are changesets with no child changesets. They are
1502 1502 where development generally takes place and are the usual targets
1503 1503 for update and merge operations. Branch heads are changesets that have
1504 1504 no child changeset on the same branch.
1505 1505
1506 1506 If one or more REVs are given, only branch heads on the branches
1507 1507 associated with the specified changesets are shown.
1508 1508
1509 1509 If -c/--closed is specified, also show branch heads marked closed
1510 1510 (see hg commit --close-branch).
1511 1511
1512 1512 If STARTREV is specified, only those heads that are descendants of
1513 1513 STARTREV will be displayed.
1514 1514
1515 1515 If -t/--topo is specified, named branch mechanics will be ignored and only
1516 1516 changesets without children will be shown.
1517 1517
1518 1518 Returns 0 if matching heads are found, 1 if not.
1519 1519 """
1520 1520
1521 1521 if opts.get('rev'):
1522 1522 start = repo.lookup(opts['rev'])
1523 1523 else:
1524 1524 start = None
1525 1525
1526 1526 if opts.get('topo'):
1527 1527 heads = [repo[h] for h in repo.heads(start)]
1528 1528 else:
1529 1529 heads = []
1530 1530 for b, ls in repo.branchmap().iteritems():
1531 1531 if start is None:
1532 1532 heads += [repo[h] for h in ls]
1533 1533 continue
1534 1534 startrev = repo.changelog.rev(start)
1535 1535 descendants = set(repo.changelog.descendants(startrev))
1536 1536 descendants.add(startrev)
1537 1537 rev = repo.changelog.rev
1538 1538 heads += [repo[h] for h in ls if rev(h) in descendants]
1539 1539
1540 1540 if branchrevs:
1541 1541 decode, encode = encoding.fromlocal, encoding.tolocal
1542 1542 branches = set(repo[decode(br)].branch() for br in branchrevs)
1543 1543 heads = [h for h in heads if h.branch() in branches]
1544 1544
1545 1545 if not opts.get('closed'):
1546 1546 heads = [h for h in heads if not h.extra().get('close')]
1547 1547
1548 1548 if opts.get('active') and branchrevs:
1549 1549 dagheads = repo.heads(start)
1550 1550 heads = [h for h in heads if h.node() in dagheads]
1551 1551
1552 1552 if branchrevs:
1553 1553 haveheads = set(h.branch() for h in heads)
1554 1554 if branches - haveheads:
1555 1555 headless = ', '.join(encode(b) for b in branches - haveheads)
1556 1556 msg = _('no open branch heads found on branches %s')
1557 1557 if opts.get('rev'):
1558 1558 msg += _(' (started at %s)' % opts['rev'])
1559 1559 ui.warn((msg + '\n') % headless)
1560 1560
1561 1561 if not heads:
1562 1562 return 1
1563 1563
1564 1564 heads = sorted(heads, key=lambda x: -x.rev())
1565 1565 displayer = cmdutil.show_changeset(ui, repo, opts)
1566 1566 for ctx in heads:
1567 1567 displayer.show(ctx)
1568 1568 displayer.close()
1569 1569
1570 1570 def help_(ui, name=None, with_version=False, unknowncmd=False):
1571 1571 """show help for a given topic or a help overview
1572 1572
1573 1573 With no arguments, print a list of commands with short help messages.
1574 1574
1575 1575 Given a topic, extension, or command name, print help for that
1576 1576 topic.
1577 1577
1578 1578 Returns 0 if successful.
1579 1579 """
1580 1580 option_lists = []
1581 1581 textwidth = util.termwidth() - 2
1582 1582
1583 1583 def addglobalopts(aliases):
1584 1584 if ui.verbose:
1585 1585 option_lists.append((_("global options:"), globalopts))
1586 1586 if name == 'shortlist':
1587 1587 option_lists.append((_('use "hg help" for the full list '
1588 1588 'of commands'), ()))
1589 1589 else:
1590 1590 if name == 'shortlist':
1591 1591 msg = _('use "hg help" for the full list of commands '
1592 1592 'or "hg -v" for details')
1593 1593 elif aliases:
1594 1594 msg = _('use "hg -v help%s" to show aliases and '
1595 1595 'global options') % (name and " " + name or "")
1596 1596 else:
1597 1597 msg = _('use "hg -v help %s" to show global options') % name
1598 1598 option_lists.append((msg, ()))
1599 1599
1600 1600 def helpcmd(name):
1601 1601 if with_version:
1602 1602 version_(ui)
1603 1603 ui.write('\n')
1604 1604
1605 1605 try:
1606 1606 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1607 1607 except error.AmbiguousCommand, inst:
1608 1608 # py3k fix: except vars can't be used outside the scope of the
1609 1609 # except block, nor can be used inside a lambda. python issue4617
1610 1610 prefix = inst.args[0]
1611 1611 select = lambda c: c.lstrip('^').startswith(prefix)
1612 1612 helplist(_('list of commands:\n\n'), select)
1613 1613 return
1614 1614
1615 1615 # check if it's an invalid alias and display its error if it is
1616 1616 if getattr(entry[0], 'badalias', False):
1617 1617 if not unknowncmd:
1618 1618 entry[0](ui)
1619 1619 return
1620 1620
1621 1621 # synopsis
1622 1622 if len(entry) > 2:
1623 1623 if entry[2].startswith('hg'):
1624 1624 ui.write("%s\n" % entry[2])
1625 1625 else:
1626 1626 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1627 1627 else:
1628 1628 ui.write('hg %s\n' % aliases[0])
1629 1629
1630 1630 # aliases
1631 1631 if not ui.quiet and len(aliases) > 1:
1632 1632 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1633 1633
1634 1634 # description
1635 1635 doc = gettext(entry[0].__doc__)
1636 1636 if not doc:
1637 1637 doc = _("(no help text available)")
1638 1638 if hasattr(entry[0], 'definition'): # aliased command
1639 1639 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1640 1640 if ui.quiet:
1641 1641 doc = doc.splitlines()[0]
1642 1642 keep = ui.verbose and ['verbose'] or []
1643 1643 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1644 1644 ui.write("\n%s\n" % formatted)
1645 1645 if pruned:
1646 1646 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1647 1647
1648 1648 if not ui.quiet:
1649 1649 # options
1650 1650 if entry[1]:
1651 1651 option_lists.append((_("options:\n"), entry[1]))
1652 1652
1653 1653 addglobalopts(False)
1654 1654
1655 1655 def helplist(header, select=None):
1656 1656 h = {}
1657 1657 cmds = {}
1658 1658 for c, e in table.iteritems():
1659 1659 f = c.split("|", 1)[0]
1660 1660 if select and not select(f):
1661 1661 continue
1662 1662 if (not select and name != 'shortlist' and
1663 1663 e[0].__module__ != __name__):
1664 1664 continue
1665 1665 if name == "shortlist" and not f.startswith("^"):
1666 1666 continue
1667 1667 f = f.lstrip("^")
1668 1668 if not ui.debugflag and f.startswith("debug"):
1669 1669 continue
1670 1670 doc = e[0].__doc__
1671 1671 if doc and 'DEPRECATED' in doc and not ui.verbose:
1672 1672 continue
1673 1673 doc = gettext(doc)
1674 1674 if not doc:
1675 1675 doc = _("(no help text available)")
1676 1676 h[f] = doc.splitlines()[0].rstrip()
1677 1677 cmds[f] = c.lstrip("^")
1678 1678
1679 1679 if not h:
1680 1680 ui.status(_('no commands defined\n'))
1681 1681 return
1682 1682
1683 1683 ui.status(header)
1684 1684 fns = sorted(h)
1685 1685 m = max(map(len, fns))
1686 1686 for f in fns:
1687 1687 if ui.verbose:
1688 1688 commands = cmds[f].replace("|",", ")
1689 1689 ui.write(" %s:\n %s\n"%(commands, h[f]))
1690 1690 else:
1691 1691 ui.write(' %-*s %s\n' % (m, f, util.wrap(h[f], m + 4)))
1692 1692
1693 1693 if not ui.quiet:
1694 1694 addglobalopts(True)
1695 1695
1696 1696 def helptopic(name):
1697 1697 for names, header, doc in help.helptable:
1698 1698 if name in names:
1699 1699 break
1700 1700 else:
1701 1701 raise error.UnknownCommand(name)
1702 1702
1703 1703 # description
1704 1704 if not doc:
1705 1705 doc = _("(no help text available)")
1706 1706 if hasattr(doc, '__call__'):
1707 1707 doc = doc()
1708 1708
1709 1709 ui.write("%s\n\n" % header)
1710 1710 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
1711 1711
1712 1712 def helpext(name):
1713 1713 try:
1714 1714 mod = extensions.find(name)
1715 1715 doc = gettext(mod.__doc__) or _('no help text available')
1716 1716 except KeyError:
1717 1717 mod = None
1718 1718 doc = extensions.disabledext(name)
1719 1719 if not doc:
1720 1720 raise error.UnknownCommand(name)
1721 1721
1722 1722 if '\n' not in doc:
1723 1723 head, tail = doc, ""
1724 1724 else:
1725 1725 head, tail = doc.split('\n', 1)
1726 1726 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
1727 1727 if tail:
1728 1728 ui.write(minirst.format(tail, textwidth))
1729 1729 ui.status('\n\n')
1730 1730
1731 1731 if mod:
1732 1732 try:
1733 1733 ct = mod.cmdtable
1734 1734 except AttributeError:
1735 1735 ct = {}
1736 1736 modcmds = set([c.split('|', 1)[0] for c in ct])
1737 1737 helplist(_('list of commands:\n\n'), modcmds.__contains__)
1738 1738 else:
1739 1739 ui.write(_('use "hg help extensions" for information on enabling '
1740 1740 'extensions\n'))
1741 1741
1742 1742 def helpextcmd(name):
1743 1743 cmd, ext, mod = extensions.disabledcmd(name, ui.config('ui', 'strict'))
1744 1744 doc = gettext(mod.__doc__).splitlines()[0]
1745 1745
1746 1746 msg = help.listexts(_("'%s' is provided by the following "
1747 1747 "extension:") % cmd, {ext: doc}, len(ext),
1748 1748 indent=4)
1749 1749 ui.write(minirst.format(msg, textwidth))
1750 1750 ui.write('\n\n')
1751 1751 ui.write(_('use "hg help extensions" for information on enabling '
1752 1752 'extensions\n'))
1753 1753
1754 1754 if name and name != 'shortlist':
1755 1755 i = None
1756 1756 if unknowncmd:
1757 1757 queries = (helpextcmd,)
1758 1758 else:
1759 1759 queries = (helptopic, helpcmd, helpext, helpextcmd)
1760 1760 for f in queries:
1761 1761 try:
1762 1762 f(name)
1763 1763 i = None
1764 1764 break
1765 1765 except error.UnknownCommand, inst:
1766 1766 i = inst
1767 1767 if i:
1768 1768 raise i
1769 1769
1770 1770 else:
1771 1771 # program name
1772 1772 if ui.verbose or with_version:
1773 1773 version_(ui)
1774 1774 else:
1775 1775 ui.status(_("Mercurial Distributed SCM\n"))
1776 1776 ui.status('\n')
1777 1777
1778 1778 # list of commands
1779 1779 if name == "shortlist":
1780 1780 header = _('basic commands:\n\n')
1781 1781 else:
1782 1782 header = _('list of commands:\n\n')
1783 1783
1784 1784 helplist(header)
1785 1785 if name != 'shortlist':
1786 1786 exts, maxlength = extensions.enabled()
1787 1787 text = help.listexts(_('enabled extensions:'), exts, maxlength)
1788 1788 if text:
1789 1789 ui.write("\n%s\n" % minirst.format(text, textwidth))
1790 1790
1791 1791 # list all option lists
1792 1792 opt_output = []
1793 1793 for title, options in option_lists:
1794 1794 opt_output.append(("\n%s" % title, None))
1795 1795 for shortopt, longopt, default, desc in options:
1796 1796 if _("DEPRECATED") in desc and not ui.verbose:
1797 1797 continue
1798 1798 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1799 1799 longopt and " --%s" % longopt),
1800 1800 "%s%s" % (desc,
1801 1801 default
1802 1802 and _(" (default: %s)") % default
1803 1803 or "")))
1804 1804
1805 1805 if not name:
1806 1806 ui.write(_("\nadditional help topics:\n\n"))
1807 1807 topics = []
1808 1808 for names, header, doc in help.helptable:
1809 1809 topics.append((sorted(names, key=len, reverse=True)[0], header))
1810 1810 topics_len = max([len(s[0]) for s in topics])
1811 1811 for t, desc in topics:
1812 1812 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1813 1813
1814 1814 if opt_output:
1815 1815 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1816 1816 for first, second in opt_output:
1817 1817 if second:
1818 1818 second = util.wrap(second, opts_len + 3)
1819 1819 ui.write(" %-*s %s\n" % (opts_len, first, second))
1820 1820 else:
1821 1821 ui.write("%s\n" % first)
1822 1822
1823 1823 def identify(ui, repo, source=None,
1824 1824 rev=None, num=None, id=None, branch=None, tags=None):
1825 1825 """identify the working copy or specified revision
1826 1826
1827 1827 With no revision, print a summary of the current state of the
1828 1828 repository.
1829 1829
1830 1830 Specifying a path to a repository root or Mercurial bundle will
1831 1831 cause lookup to operate on that repository/bundle.
1832 1832
1833 1833 This summary identifies the repository state using one or two
1834 1834 parent hash identifiers, followed by a "+" if there are
1835 1835 uncommitted changes in the working directory, a list of tags for
1836 1836 this revision and a branch name for non-default branches.
1837 1837
1838 1838 Returns 0 if successful.
1839 1839 """
1840 1840
1841 1841 if not repo and not source:
1842 1842 raise util.Abort(_("There is no Mercurial repository here "
1843 1843 "(.hg not found)"))
1844 1844
1845 1845 hexfunc = ui.debugflag and hex or short
1846 1846 default = not (num or id or branch or tags)
1847 1847 output = []
1848 1848
1849 1849 revs = []
1850 1850 if source:
1851 1851 source, branches = hg.parseurl(ui.expandpath(source))
1852 1852 repo = hg.repository(ui, source)
1853 1853 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
1854 1854
1855 1855 if not repo.local():
1856 1856 if not rev and revs:
1857 1857 rev = revs[0]
1858 1858 if not rev:
1859 1859 rev = "tip"
1860 1860 if num or branch or tags:
1861 1861 raise util.Abort(
1862 1862 "can't query remote revision number, branch, or tags")
1863 1863 output = [hexfunc(repo.lookup(rev))]
1864 1864 elif not rev:
1865 1865 ctx = repo[None]
1866 1866 parents = ctx.parents()
1867 1867 changed = False
1868 1868 if default or id or num:
1869 1869 changed = util.any(repo.status())
1870 1870 if default or id:
1871 1871 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1872 1872 (changed) and "+" or "")]
1873 1873 if num:
1874 1874 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1875 1875 (changed) and "+" or ""))
1876 1876 else:
1877 1877 ctx = repo[rev]
1878 1878 if default or id:
1879 1879 output = [hexfunc(ctx.node())]
1880 1880 if num:
1881 1881 output.append(str(ctx.rev()))
1882 1882
1883 1883 if repo.local() and default and not ui.quiet:
1884 1884 b = encoding.tolocal(ctx.branch())
1885 1885 if b != 'default':
1886 1886 output.append("(%s)" % b)
1887 1887
1888 1888 # multiple tags for a single parent separated by '/'
1889 1889 t = "/".join(ctx.tags())
1890 1890 if t:
1891 1891 output.append(t)
1892 1892
1893 1893 if branch:
1894 1894 output.append(encoding.tolocal(ctx.branch()))
1895 1895
1896 1896 if tags:
1897 1897 output.extend(ctx.tags())
1898 1898
1899 1899 ui.write("%s\n" % ' '.join(output))
1900 1900
1901 1901 def import_(ui, repo, patch1, *patches, **opts):
1902 1902 """import an ordered set of patches
1903 1903
1904 1904 Import a list of patches and commit them individually (unless
1905 1905 --no-commit is specified).
1906 1906
1907 1907 If there are outstanding changes in the working directory, import
1908 1908 will abort unless given the -f/--force flag.
1909 1909
1910 1910 You can import a patch straight from a mail message. Even patches
1911 1911 as attachments work (to use the body part, it must have type
1912 1912 text/plain or text/x-patch). From and Subject headers of email
1913 1913 message are used as default committer and commit message. All
1914 1914 text/plain body parts before first diff are added to commit
1915 1915 message.
1916 1916
1917 1917 If the imported patch was generated by hg export, user and
1918 1918 description from patch override values from message headers and
1919 1919 body. Values given on command line with -m/--message and -u/--user
1920 1920 override these.
1921 1921
1922 1922 If --exact is specified, import will set the working directory to
1923 1923 the parent of each patch before applying it, and will abort if the
1924 1924 resulting changeset has a different ID than the one recorded in
1925 1925 the patch. This may happen due to character set problems or other
1926 1926 deficiencies in the text patch format.
1927 1927
1928 1928 With -s/--similarity, hg will attempt to discover renames and
1929 1929 copies in the patch in the same way as 'addremove'.
1930 1930
1931 1931 To read a patch from standard input, use "-" as the patch name. If
1932 1932 a URL is specified, the patch will be downloaded from it.
1933 1933 See :hg:`help dates` for a list of formats valid for -d/--date.
1934 1934
1935 1935 Returns 0 on success.
1936 1936 """
1937 1937 patches = (patch1,) + patches
1938 1938
1939 1939 date = opts.get('date')
1940 1940 if date:
1941 1941 opts['date'] = util.parsedate(date)
1942 1942
1943 1943 try:
1944 1944 sim = float(opts.get('similarity') or 0)
1945 1945 except ValueError:
1946 1946 raise util.Abort(_('similarity must be a number'))
1947 1947 if sim < 0 or sim > 100:
1948 1948 raise util.Abort(_('similarity must be between 0 and 100'))
1949 1949
1950 1950 if opts.get('exact') or not opts.get('force'):
1951 1951 cmdutil.bail_if_changed(repo)
1952 1952
1953 1953 d = opts["base"]
1954 1954 strip = opts["strip"]
1955 1955 wlock = lock = None
1956 1956
1957 1957 def tryone(ui, hunk):
1958 1958 tmpname, message, user, date, branch, nodeid, p1, p2 = \
1959 1959 patch.extract(ui, hunk)
1960 1960
1961 1961 if not tmpname:
1962 1962 return None
1963 1963 commitid = _('to working directory')
1964 1964
1965 1965 try:
1966 1966 cmdline_message = cmdutil.logmessage(opts)
1967 1967 if cmdline_message:
1968 1968 # pickup the cmdline msg
1969 1969 message = cmdline_message
1970 1970 elif message:
1971 1971 # pickup the patch msg
1972 1972 message = message.strip()
1973 1973 else:
1974 1974 # launch the editor
1975 1975 message = None
1976 1976 ui.debug('message:\n%s\n' % message)
1977 1977
1978 1978 wp = repo.parents()
1979 1979 if opts.get('exact'):
1980 1980 if not nodeid or not p1:
1981 1981 raise util.Abort(_('not a Mercurial patch'))
1982 1982 p1 = repo.lookup(p1)
1983 1983 p2 = repo.lookup(p2 or hex(nullid))
1984 1984
1985 1985 if p1 != wp[0].node():
1986 1986 hg.clean(repo, p1)
1987 1987 repo.dirstate.setparents(p1, p2)
1988 1988 elif p2:
1989 1989 try:
1990 1990 p1 = repo.lookup(p1)
1991 1991 p2 = repo.lookup(p2)
1992 1992 if p1 == wp[0].node():
1993 1993 repo.dirstate.setparents(p1, p2)
1994 1994 except error.RepoError:
1995 1995 pass
1996 1996 if opts.get('exact') or opts.get('import_branch'):
1997 1997 repo.dirstate.setbranch(branch or 'default')
1998 1998
1999 1999 files = {}
2000 2000 try:
2001 2001 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2002 2002 files=files, eolmode=None)
2003 2003 finally:
2004 2004 files = patch.updatedir(ui, repo, files,
2005 2005 similarity=sim / 100.0)
2006 2006 if not opts.get('no_commit'):
2007 2007 if opts.get('exact'):
2008 2008 m = None
2009 2009 else:
2010 2010 m = cmdutil.matchfiles(repo, files or [])
2011 2011 n = repo.commit(message, opts.get('user') or user,
2012 2012 opts.get('date') or date, match=m,
2013 2013 editor=cmdutil.commiteditor)
2014 2014 if opts.get('exact'):
2015 2015 if hex(n) != nodeid:
2016 2016 repo.rollback()
2017 2017 raise util.Abort(_('patch is damaged'
2018 2018 ' or loses information'))
2019 2019 # Force a dirstate write so that the next transaction
2020 2020 # backups an up-do-date file.
2021 2021 repo.dirstate.write()
2022 2022 if n:
2023 2023 commitid = short(n)
2024 2024
2025 2025 return commitid
2026 2026 finally:
2027 2027 os.unlink(tmpname)
2028 2028
2029 2029 try:
2030 2030 wlock = repo.wlock()
2031 2031 lock = repo.lock()
2032 2032 lastcommit = None
2033 2033 for p in patches:
2034 2034 pf = os.path.join(d, p)
2035 2035
2036 2036 if pf == '-':
2037 2037 ui.status(_("applying patch from stdin\n"))
2038 2038 pf = sys.stdin
2039 2039 else:
2040 2040 ui.status(_("applying %s\n") % p)
2041 2041 pf = url.open(ui, pf)
2042 2042
2043 2043 haspatch = False
2044 2044 for hunk in patch.split(pf):
2045 2045 commitid = tryone(ui, hunk)
2046 2046 if commitid:
2047 2047 haspatch = True
2048 2048 if lastcommit:
2049 2049 ui.status(_('applied %s\n') % lastcommit)
2050 2050 lastcommit = commitid
2051 2051
2052 2052 if not haspatch:
2053 2053 raise util.Abort(_('no diffs found'))
2054 2054
2055 2055 finally:
2056 2056 release(lock, wlock)
2057 2057
2058 2058 def incoming(ui, repo, source="default", **opts):
2059 2059 """show new changesets found in source
2060 2060
2061 2061 Show new changesets found in the specified path/URL or the default
2062 2062 pull location. These are the changesets that would have been pulled
2063 2063 if a pull at the time you issued this command.
2064 2064
2065 2065 For remote repository, using --bundle avoids downloading the
2066 2066 changesets twice if the incoming is followed by a pull.
2067 2067
2068 2068 See pull for valid source format details.
2069 2069
2070 2070 Returns 0 if there are incoming changes, 1 otherwise.
2071 2071 """
2072 2072 limit = cmdutil.loglimit(opts)
2073 2073 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2074 2074 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2075 2075 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2076 2076 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2077 2077 if revs:
2078 2078 revs = [other.lookup(rev) for rev in revs]
2079 2079 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
2080 2080 force=opts["force"])
2081 2081 if not incoming:
2082 2082 try:
2083 2083 os.unlink(opts["bundle"])
2084 2084 except:
2085 2085 pass
2086 2086 ui.status(_("no changes found\n"))
2087 2087 return 1
2088 2088
2089 2089 cleanup = None
2090 2090 try:
2091 2091 fname = opts["bundle"]
2092 2092 if fname or not other.local():
2093 2093 # create a bundle (uncompressed if other repo is not local)
2094 2094
2095 2095 if revs is None and other.capable('changegroupsubset'):
2096 2096 revs = rheads
2097 2097
2098 2098 if revs is None:
2099 2099 cg = other.changegroup(incoming, "incoming")
2100 2100 else:
2101 2101 cg = other.changegroupsubset(incoming, revs, 'incoming')
2102 2102 bundletype = other.local() and "HG10BZ" or "HG10UN"
2103 2103 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
2104 2104 # keep written bundle?
2105 2105 if opts["bundle"]:
2106 2106 cleanup = None
2107 2107 if not other.local():
2108 2108 # use the created uncompressed bundlerepo
2109 2109 other = bundlerepo.bundlerepository(ui, repo.root, fname)
2110 2110
2111 2111 o = other.changelog.nodesbetween(incoming, revs)[0]
2112 2112 if opts.get('newest_first'):
2113 2113 o.reverse()
2114 2114 displayer = cmdutil.show_changeset(ui, other, opts)
2115 2115 count = 0
2116 2116 for n in o:
2117 2117 if limit is not None and count >= limit:
2118 2118 break
2119 2119 parents = [p for p in other.changelog.parents(n) if p != nullid]
2120 2120 if opts.get('no_merges') and len(parents) == 2:
2121 2121 continue
2122 2122 count += 1
2123 2123 displayer.show(other[n])
2124 2124 displayer.close()
2125 2125 finally:
2126 2126 if hasattr(other, 'close'):
2127 2127 other.close()
2128 2128 if cleanup:
2129 2129 os.unlink(cleanup)
2130 2130
2131 2131 def init(ui, dest=".", **opts):
2132 2132 """create a new repository in the given directory
2133 2133
2134 2134 Initialize a new repository in the given directory. If the given
2135 2135 directory does not exist, it will be created.
2136 2136
2137 2137 If no directory is given, the current directory is used.
2138 2138
2139 2139 It is possible to specify an ``ssh://`` URL as the destination.
2140 2140 See :hg:`help urls` for more information.
2141 2141
2142 2142 Returns 0 on success.
2143 2143 """
2144 2144 hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
2145 2145
2146 2146 def locate(ui, repo, *pats, **opts):
2147 2147 """locate files matching specific patterns
2148 2148
2149 2149 Print files under Mercurial control in the working directory whose
2150 2150 names match the given patterns.
2151 2151
2152 2152 By default, this command searches all directories in the working
2153 2153 directory. To search just the current directory and its
2154 2154 subdirectories, use "--include .".
2155 2155
2156 2156 If no patterns are given to match, this command prints the names
2157 2157 of all files under Mercurial control in the working directory.
2158 2158
2159 2159 If you want to feed the output of this command into the "xargs"
2160 2160 command, use the -0 option to both this command and "xargs". This
2161 2161 will avoid the problem of "xargs" treating single filenames that
2162 2162 contain whitespace as multiple filenames.
2163 2163
2164 2164 Returns 0 if a match is found, 1 otherwise.
2165 2165 """
2166 2166 end = opts.get('print0') and '\0' or '\n'
2167 2167 rev = opts.get('rev') or None
2168 2168
2169 2169 ret = 1
2170 2170 m = cmdutil.match(repo, pats, opts, default='relglob')
2171 2171 m.bad = lambda x, y: False
2172 2172 for abs in repo[rev].walk(m):
2173 2173 if not rev and abs not in repo.dirstate:
2174 2174 continue
2175 2175 if opts.get('fullpath'):
2176 2176 ui.write(repo.wjoin(abs), end)
2177 2177 else:
2178 2178 ui.write(((pats and m.rel(abs)) or abs), end)
2179 2179 ret = 0
2180 2180
2181 2181 return ret
2182 2182
2183 2183 def log(ui, repo, *pats, **opts):
2184 2184 """show revision history of entire repository or files
2185 2185
2186 2186 Print the revision history of the specified files or the entire
2187 2187 project.
2188 2188
2189 2189 File history is shown without following rename or copy history of
2190 2190 files. Use -f/--follow with a filename to follow history across
2191 2191 renames and copies. --follow without a filename will only show
2192 2192 ancestors or descendants of the starting revision. --follow-first
2193 2193 only follows the first parent of merge revisions.
2194 2194
2195 2195 If no revision range is specified, the default is tip:0 unless
2196 2196 --follow is set, in which case the working directory parent is
2197 2197 used as the starting revision.
2198 2198
2199 2199 See :hg:`help dates` for a list of formats valid for -d/--date.
2200 2200
2201 2201 By default this command prints revision number and changeset id,
2202 2202 tags, non-trivial parents, user, date and time, and a summary for
2203 2203 each commit. When the -v/--verbose switch is used, the list of
2204 2204 changed files and full commit message are shown.
2205 2205
2206 2206 NOTE: log -p/--patch may generate unexpected diff output for merge
2207 2207 changesets, as it will only compare the merge changeset against
2208 2208 its first parent. Also, only files different from BOTH parents
2209 2209 will appear in files:.
2210 2210
2211 2211 Returns 0 on success.
2212 2212 """
2213 2213
2214 2214 matchfn = cmdutil.match(repo, pats, opts)
2215 2215 limit = cmdutil.loglimit(opts)
2216 2216 count = 0
2217 2217
2218 2218 endrev = None
2219 2219 if opts.get('copies') and opts.get('rev'):
2220 2220 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2221 2221
2222 2222 df = False
2223 2223 if opts["date"]:
2224 2224 df = util.matchdate(opts["date"])
2225 2225
2226 2226 branches = opts.get('branch', []) + opts.get('only_branch', [])
2227 2227 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2228 2228
2229 2229 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
2230 2230 def prep(ctx, fns):
2231 2231 rev = ctx.rev()
2232 2232 parents = [p for p in repo.changelog.parentrevs(rev)
2233 2233 if p != nullrev]
2234 2234 if opts.get('no_merges') and len(parents) == 2:
2235 2235 return
2236 2236 if opts.get('only_merges') and len(parents) != 2:
2237 2237 return
2238 2238 if opts.get('branch') and ctx.branch() not in opts['branch']:
2239 2239 return
2240 2240 if df and not df(ctx.date()[0]):
2241 2241 return
2242 2242 if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
2243 2243 return
2244 2244 if opts.get('keyword'):
2245 2245 for k in [kw.lower() for kw in opts['keyword']]:
2246 2246 if (k in ctx.user().lower() or
2247 2247 k in ctx.description().lower() or
2248 2248 k in " ".join(ctx.files()).lower()):
2249 2249 break
2250 2250 else:
2251 2251 return
2252 2252
2253 2253 copies = None
2254 2254 if opts.get('copies') and rev:
2255 2255 copies = []
2256 2256 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2257 2257 for fn in ctx.files():
2258 2258 rename = getrenamed(fn, rev)
2259 2259 if rename:
2260 2260 copies.append((fn, rename[0]))
2261 2261
2262 2262 displayer.show(ctx, copies=copies)
2263 2263
2264 2264 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2265 2265 if count == limit:
2266 2266 break
2267 2267 if displayer.flush(ctx.rev()):
2268 2268 count += 1
2269 2269 displayer.close()
2270 2270
2271 2271 def manifest(ui, repo, node=None, rev=None):
2272 2272 """output the current or given revision of the project manifest
2273 2273
2274 2274 Print a list of version controlled files for the given revision.
2275 2275 If no revision is given, the first parent of the working directory
2276 2276 is used, or the null revision if no revision is checked out.
2277 2277
2278 2278 With -v, print file permissions, symlink and executable bits.
2279 2279 With --debug, print file revision hashes.
2280 2280
2281 2281 Returns 0 on success.
2282 2282 """
2283 2283
2284 2284 if rev and node:
2285 2285 raise util.Abort(_("please specify just one revision"))
2286 2286
2287 2287 if not node:
2288 2288 node = rev
2289 2289
2290 2290 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2291 2291 ctx = repo[node]
2292 2292 for f in ctx:
2293 2293 if ui.debugflag:
2294 2294 ui.write("%40s " % hex(ctx.manifest()[f]))
2295 2295 if ui.verbose:
2296 2296 ui.write(decor[ctx.flags(f)])
2297 2297 ui.write("%s\n" % f)
2298 2298
2299 2299 def merge(ui, repo, node=None, **opts):
2300 2300 """merge working directory with another revision
2301 2301
2302 2302 The current working directory is updated with all changes made in
2303 2303 the requested revision since the last common predecessor revision.
2304 2304
2305 2305 Files that changed between either parent are marked as changed for
2306 2306 the next commit and a commit must be performed before any further
2307 2307 updates to the repository are allowed. The next commit will have
2308 2308 two parents.
2309 2309
2310 2310 If no revision is specified, the working directory's parent is a
2311 2311 head revision, and the current branch contains exactly one other
2312 2312 head, the other head is merged with by default. Otherwise, an
2313 2313 explicit revision with which to merge with must be provided.
2314 2314
2315 2315 Returns 0 on success, 1 if there are unresolved files.
2316 2316 """
2317 2317
2318 2318 if opts.get('rev') and node:
2319 2319 raise util.Abort(_("please specify just one revision"))
2320 2320 if not node:
2321 2321 node = opts.get('rev')
2322 2322
2323 2323 if not node:
2324 2324 branch = repo.changectx(None).branch()
2325 2325 bheads = repo.branchheads(branch)
2326 2326 if len(bheads) > 2:
2327 2327 ui.warn(_("abort: branch '%s' has %d heads - "
2328 2328 "please merge with an explicit rev\n")
2329 2329 % (branch, len(bheads)))
2330 2330 ui.status(_("(run 'hg heads .' to see heads)\n"))
2331 2331 return False
2332 2332
2333 2333 parent = repo.dirstate.parents()[0]
2334 2334 if len(bheads) == 1:
2335 2335 if len(repo.heads()) > 1:
2336 2336 ui.warn(_("abort: branch '%s' has one head - "
2337 2337 "please merge with an explicit rev\n" % branch))
2338 2338 ui.status(_("(run 'hg heads' to see all heads)\n"))
2339 2339 return False
2340 2340 msg = _('there is nothing to merge')
2341 2341 if parent != repo.lookup(repo[None].branch()):
2342 2342 msg = _('%s - use "hg update" instead') % msg
2343 2343 raise util.Abort(msg)
2344 2344
2345 2345 if parent not in bheads:
2346 2346 raise util.Abort(_('working dir not at a head rev - '
2347 2347 'use "hg update" or merge with an explicit rev'))
2348 2348 node = parent == bheads[0] and bheads[-1] or bheads[0]
2349 2349
2350 2350 if opts.get('preview'):
2351 2351 # find nodes that are ancestors of p2 but not of p1
2352 2352 p1 = repo.lookup('.')
2353 2353 p2 = repo.lookup(node)
2354 2354 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2355 2355
2356 2356 displayer = cmdutil.show_changeset(ui, repo, opts)
2357 2357 for node in nodes:
2358 2358 displayer.show(repo[node])
2359 2359 displayer.close()
2360 2360 return 0
2361 2361
2362 2362 return hg.merge(repo, node, force=opts.get('force'))
2363 2363
2364 2364 def outgoing(ui, repo, dest=None, **opts):
2365 2365 """show changesets not found in the destination
2366 2366
2367 2367 Show changesets not found in the specified destination repository
2368 2368 or the default push location. These are the changesets that would
2369 2369 be pushed if a push was requested.
2370 2370
2371 2371 See pull for details of valid destination formats.
2372 2372
2373 2373 Returns 0 if there are outgoing changes, 1 otherwise.
2374 2374 """
2375 2375 limit = cmdutil.loglimit(opts)
2376 2376 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2377 2377 dest, branches = hg.parseurl(dest, opts.get('branch'))
2378 2378 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2379 2379 if revs:
2380 2380 revs = [repo.lookup(rev) for rev in revs]
2381 2381
2382 2382 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2383 2383 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2384 2384 o = repo.findoutgoing(other, force=opts.get('force'))
2385 2385 if not o:
2386 2386 ui.status(_("no changes found\n"))
2387 2387 return 1
2388 2388 o = repo.changelog.nodesbetween(o, revs)[0]
2389 2389 if opts.get('newest_first'):
2390 2390 o.reverse()
2391 2391 displayer = cmdutil.show_changeset(ui, repo, opts)
2392 2392 count = 0
2393 2393 for n in o:
2394 2394 if limit is not None and count >= limit:
2395 2395 break
2396 2396 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2397 2397 if opts.get('no_merges') and len(parents) == 2:
2398 2398 continue
2399 2399 count += 1
2400 2400 displayer.show(repo[n])
2401 2401 displayer.close()
2402 2402
2403 2403 def parents(ui, repo, file_=None, **opts):
2404 2404 """show the parents of the working directory or revision
2405 2405
2406 2406 Print the working directory's parent revisions. If a revision is
2407 2407 given via -r/--rev, the parent of that revision will be printed.
2408 2408 If a file argument is given, the revision in which the file was
2409 2409 last changed (before the working directory revision or the
2410 2410 argument to --rev if given) is printed.
2411 2411
2412 2412 Returns 0 on success.
2413 2413 """
2414 2414 rev = opts.get('rev')
2415 2415 if rev:
2416 2416 ctx = repo[rev]
2417 2417 else:
2418 2418 ctx = repo[None]
2419 2419
2420 2420 if file_:
2421 2421 m = cmdutil.match(repo, (file_,), opts)
2422 2422 if m.anypats() or len(m.files()) != 1:
2423 2423 raise util.Abort(_('can only specify an explicit filename'))
2424 2424 file_ = m.files()[0]
2425 2425 filenodes = []
2426 2426 for cp in ctx.parents():
2427 2427 if not cp:
2428 2428 continue
2429 2429 try:
2430 2430 filenodes.append(cp.filenode(file_))
2431 2431 except error.LookupError:
2432 2432 pass
2433 2433 if not filenodes:
2434 2434 raise util.Abort(_("'%s' not found in manifest!") % file_)
2435 2435 fl = repo.file(file_)
2436 2436 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2437 2437 else:
2438 2438 p = [cp.node() for cp in ctx.parents()]
2439 2439
2440 2440 displayer = cmdutil.show_changeset(ui, repo, opts)
2441 2441 for n in p:
2442 2442 if n != nullid:
2443 2443 displayer.show(repo[n])
2444 2444 displayer.close()
2445 2445
2446 2446 def paths(ui, repo, search=None):
2447 2447 """show aliases for remote repositories
2448 2448
2449 2449 Show definition of symbolic path name NAME. If no name is given,
2450 2450 show definition of all available names.
2451 2451
2452 2452 Path names are defined in the [paths] section of
2453 2453 ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
2454 2454 repository, ``.hg/hgrc`` is used, too.
2455 2455
2456 2456 The path names ``default`` and ``default-push`` have a special
2457 2457 meaning. When performing a push or pull operation, they are used
2458 2458 as fallbacks if no location is specified on the command-line.
2459 2459 When ``default-push`` is set, it will be used for push and
2460 2460 ``default`` will be used for pull; otherwise ``default`` is used
2461 2461 as the fallback for both. When cloning a repository, the clone
2462 2462 source is written as ``default`` in ``.hg/hgrc``. Note that
2463 2463 ``default`` and ``default-push`` apply to all inbound (e.g.
2464 2464 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2465 2465 :hg:`bundle`) operations.
2466 2466
2467 2467 See :hg:`help urls` for more information.
2468 2468 """
2469 2469 if search:
2470 2470 for name, path in ui.configitems("paths"):
2471 2471 if name == search:
2472 2472 ui.write("%s\n" % url.hidepassword(path))
2473 2473 return
2474 2474 ui.warn(_("not found!\n"))
2475 2475 return 1
2476 2476 else:
2477 2477 for name, path in ui.configitems("paths"):
2478 2478 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2479 2479
2480 2480 def postincoming(ui, repo, modheads, optupdate, checkout):
2481 2481 if modheads == 0:
2482 2482 return
2483 2483 if optupdate:
2484 2484 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2485 2485 return hg.update(repo, checkout)
2486 2486 else:
2487 2487 ui.status(_("not updating, since new heads added\n"))
2488 2488 if modheads > 1:
2489 2489 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2490 2490 else:
2491 2491 ui.status(_("(run 'hg update' to get a working copy)\n"))
2492 2492
2493 2493 def pull(ui, repo, source="default", **opts):
2494 2494 """pull changes from the specified source
2495 2495
2496 2496 Pull changes from a remote repository to a local one.
2497 2497
2498 2498 This finds all changes from the repository at the specified path
2499 2499 or URL and adds them to a local repository (the current one unless
2500 2500 -R is specified). By default, this does not update the copy of the
2501 2501 project in the working directory.
2502 2502
2503 2503 Use hg incoming if you want to see what would have been added by a
2504 2504 pull at the time you issued this command. If you then decide to
2505 2505 add those changes to the repository, you should use pull -r X
2506 2506 where X is the last changeset listed by hg incoming.
2507 2507
2508 2508 If SOURCE is omitted, the 'default' path will be used.
2509 2509 See :hg:`help urls` for more information.
2510 2510
2511 2511 Returns 0 on success, 1 if an update had unresolved files.
2512 2512 """
2513 2513 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2514 2514 other = hg.repository(cmdutil.remoteui(repo, opts), source)
2515 2515 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2516 2516 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2517 2517 if revs:
2518 2518 try:
2519 2519 revs = [other.lookup(rev) for rev in revs]
2520 2520 except error.CapabilityError:
2521 2521 err = _("Other repository doesn't support revision lookup, "
2522 2522 "so a rev cannot be specified.")
2523 2523 raise util.Abort(err)
2524 2524
2525 2525 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2526 2526 if checkout:
2527 2527 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2528 2528 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2529 2529
2530 2530 def push(ui, repo, dest=None, **opts):
2531 2531 """push changes to the specified destination
2532 2532
2533 2533 Push changes from the local repository to the specified destination.
2534 2534
2535 2535 This is the symmetrical operation for pull. It moves changes from
2536 2536 the current repository to a different one. If the destination is
2537 2537 local this is identical to a pull in that directory from the
2538 2538 current one.
2539 2539
2540 2540 By default, push will refuse to run if it detects the result would
2541 2541 increase the number of remote heads. This generally indicates the
2542 2542 user forgot to pull and merge before pushing.
2543 2543
2544 2544 If -r/--rev is used, the named revision and all its ancestors will
2545 2545 be pushed to the remote repository.
2546 2546
2547 2547 Please see :hg:`help urls` for important details about ``ssh://``
2548 2548 URLs. If DESTINATION is omitted, a default path will be used.
2549 2549
2550 2550 Returns 0 if push was successful, 1 if nothing to push.
2551 2551 """
2552 2552 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2553 2553 dest, branches = hg.parseurl(dest, opts.get('branch'))
2554 2554 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2555 2555 other = hg.repository(cmdutil.remoteui(repo, opts), dest)
2556 2556 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2557 2557 if revs:
2558 2558 revs = [repo.lookup(rev) for rev in revs]
2559 2559
2560 2560 # push subrepos depth-first for coherent ordering
2561 2561 c = repo['']
2562 2562 subs = c.substate # only repos that are committed
2563 2563 for s in sorted(subs):
2564 2564 if not c.sub(s).push(opts.get('force')):
2565 2565 return False
2566 2566
2567 2567 r = repo.push(other, opts.get('force'), revs=revs)
2568 2568 return r == 0
2569 2569
2570 2570 def recover(ui, repo):
2571 2571 """roll back an interrupted transaction
2572 2572
2573 2573 Recover from an interrupted commit or pull.
2574 2574
2575 2575 This command tries to fix the repository status after an
2576 2576 interrupted operation. It should only be necessary when Mercurial
2577 2577 suggests it.
2578 2578
2579 2579 Returns 0 if successful, 1 if nothing to recover or verify fails.
2580 2580 """
2581 2581 if repo.recover():
2582 2582 return hg.verify(repo)
2583 2583 return 1
2584 2584
2585 2585 def remove(ui, repo, *pats, **opts):
2586 2586 """remove the specified files on the next commit
2587 2587
2588 2588 Schedule the indicated files for removal from the repository.
2589 2589
2590 2590 This only removes files from the current branch, not from the
2591 2591 entire project history. -A/--after can be used to remove only
2592 2592 files that have already been deleted, -f/--force can be used to
2593 2593 force deletion, and -Af can be used to remove files from the next
2594 2594 revision without deleting them from the working directory.
2595 2595
2596 2596 The following table details the behavior of remove for different
2597 2597 file states (columns) and option combinations (rows). The file
2598 2598 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2599 2599 reported by hg status). The actions are Warn, Remove (from branch)
2600 2600 and Delete (from disk)::
2601 2601
2602 2602 A C M !
2603 2603 none W RD W R
2604 2604 -f R RD RD R
2605 2605 -A W W W R
2606 2606 -Af R R R R
2607 2607
2608 2608 This command schedules the files to be removed at the next commit.
2609 2609 To undo a remove before that, see hg revert.
2610 2610
2611 2611 Returns 0 on success, 1 if any warnings encountered.
2612 2612 """
2613 2613
2614 2614 ret = 0
2615 2615 after, force = opts.get('after'), opts.get('force')
2616 2616 if not pats and not after:
2617 2617 raise util.Abort(_('no files specified'))
2618 2618
2619 2619 m = cmdutil.match(repo, pats, opts)
2620 2620 s = repo.status(match=m, clean=True)
2621 2621 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2622 2622
2623 2623 for f in m.files():
2624 2624 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2625 2625 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2626 2626 ret = 1
2627 2627
2628 2628 def warn(files, reason):
2629 2629 for f in files:
2630 2630 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2631 2631 % (m.rel(f), reason))
2632 2632 ret = 1
2633 2633
2634 2634 if force:
2635 2635 remove, forget = modified + deleted + clean, added
2636 2636 elif after:
2637 2637 remove, forget = deleted, []
2638 2638 warn(modified + added + clean, _('still exists'))
2639 2639 else:
2640 2640 remove, forget = deleted + clean, []
2641 2641 warn(modified, _('is modified'))
2642 2642 warn(added, _('has been marked for add'))
2643 2643
2644 2644 for f in sorted(remove + forget):
2645 2645 if ui.verbose or not m.exact(f):
2646 2646 ui.status(_('removing %s\n') % m.rel(f))
2647 2647
2648 2648 repo.forget(forget)
2649 2649 repo.remove(remove, unlink=not after)
2650 2650 return ret
2651 2651
2652 2652 def rename(ui, repo, *pats, **opts):
2653 2653 """rename files; equivalent of copy + remove
2654 2654
2655 2655 Mark dest as copies of sources; mark sources for deletion. If dest
2656 2656 is a directory, copies are put in that directory. If dest is a
2657 2657 file, there can only be one source.
2658 2658
2659 2659 By default, this command copies the contents of files as they
2660 2660 exist in the working directory. If invoked with -A/--after, the
2661 2661 operation is recorded, but no copying is performed.
2662 2662
2663 2663 This command takes effect at the next commit. To undo a rename
2664 2664 before that, see hg revert.
2665 2665
2666 2666 Returns 0 on success, 1 if errors are encountered.
2667 2667 """
2668 2668 wlock = repo.wlock(False)
2669 2669 try:
2670 2670 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2671 2671 finally:
2672 2672 wlock.release()
2673 2673
2674 2674 def resolve(ui, repo, *pats, **opts):
2675 2675 """various operations to help finish a merge
2676 2676
2677 2677 This command includes several actions that are often useful while
2678 2678 performing a merge, after running ``merge`` but before running
2679 2679 ``commit``. (It is only meaningful if your working directory has
2680 2680 two parents.) It is most relevant for merges with unresolved
2681 2681 conflicts, which are typically a result of non-interactive merging with
2682 2682 ``internal:merge`` or a command-line merge tool like ``diff3``.
2683 2683
2684 2684 The available actions are:
2685 2685
2686 2686 1) list files that were merged with conflicts (U, for unresolved)
2687 2687 and without conflicts (R, for resolved): ``hg resolve -l``
2688 2688 (this is like ``status`` for merges)
2689 2689 2) record that you have resolved conflicts in certain files:
2690 2690 ``hg resolve -m [file ...]`` (default: mark all unresolved files)
2691 2691 3) forget that you have resolved conflicts in certain files:
2692 2692 ``hg resolve -u [file ...]`` (default: unmark all resolved files)
2693 2693 4) discard your current attempt(s) at resolving conflicts and
2694 2694 restart the merge from scratch: ``hg resolve file...``
2695 2695 (or ``-a`` for all unresolved files)
2696 2696
2697 2697 Note that Mercurial will not let you commit files with unresolved merge
2698 2698 conflicts. You must use ``hg resolve -m ...`` before you can commit
2699 2699 after a conflicting merge.
2700 2700
2701 2701 Returns 0 on success, 1 if any files fail a resolve attempt.
2702 2702 """
2703 2703
2704 2704 all, mark, unmark, show, nostatus = \
2705 2705 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
2706 2706
2707 2707 if (show and (mark or unmark)) or (mark and unmark):
2708 2708 raise util.Abort(_("too many options specified"))
2709 2709 if pats and all:
2710 2710 raise util.Abort(_("can't specify --all and patterns"))
2711 2711 if not (all or pats or show or mark or unmark):
2712 2712 raise util.Abort(_('no files or directories specified; '
2713 2713 'use --all to remerge all files'))
2714 2714
2715 2715 ms = mergemod.mergestate(repo)
2716 2716 m = cmdutil.match(repo, pats, opts)
2717 2717 ret = 0
2718 2718
2719 2719 for f in ms:
2720 2720 if m(f):
2721 2721 if show:
2722 2722 if nostatus:
2723 2723 ui.write("%s\n" % f)
2724 2724 else:
2725 2725 ui.write("%s %s\n" % (ms[f].upper(), f),
2726 2726 label='resolve.' +
2727 2727 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
2728 2728 elif mark:
2729 2729 ms.mark(f, "r")
2730 2730 elif unmark:
2731 2731 ms.mark(f, "u")
2732 2732 else:
2733 2733 wctx = repo[None]
2734 2734 mctx = wctx.parents()[-1]
2735 2735
2736 2736 # backup pre-resolve (merge uses .orig for its own purposes)
2737 2737 a = repo.wjoin(f)
2738 2738 util.copyfile(a, a + ".resolve")
2739 2739
2740 2740 # resolve file
2741 2741 if ms.resolve(f, wctx, mctx):
2742 2742 ret = 1
2743 2743
2744 2744 # replace filemerge's .orig file with our resolve file
2745 2745 util.rename(a + ".resolve", a + ".orig")
2746 2746 return ret
2747 2747
2748 2748 def revert(ui, repo, *pats, **opts):
2749 2749 """restore individual files or directories to an earlier state
2750 2750
2751 2751 (Use update -r to check out earlier revisions, revert does not
2752 2752 change the working directory parents.)
2753 2753
2754 2754 With no revision specified, revert the named files or directories
2755 2755 to the contents they had in the parent of the working directory.
2756 2756 This restores the contents of the affected files to an unmodified
2757 2757 state and unschedules adds, removes, copies, and renames. If the
2758 2758 working directory has two parents, you must explicitly specify a
2759 2759 revision.
2760 2760
2761 2761 Using the -r/--rev option, revert the given files or directories
2762 2762 to their contents as of a specific revision. This can be helpful
2763 2763 to "roll back" some or all of an earlier change. See :hg:`help
2764 2764 dates` for a list of formats valid for -d/--date.
2765 2765
2766 2766 Revert modifies the working directory. It does not commit any
2767 2767 changes, or change the parent of the working directory. If you
2768 2768 revert to a revision other than the parent of the working
2769 2769 directory, the reverted files will thus appear modified
2770 2770 afterwards.
2771 2771
2772 2772 If a file has been deleted, it is restored. If the executable mode
2773 2773 of a file was changed, it is reset.
2774 2774
2775 2775 If names are given, all files matching the names are reverted.
2776 2776 If no arguments are given, no files are reverted.
2777 2777
2778 2778 Modified files are saved with a .orig suffix before reverting.
2779 2779 To disable these backups, use --no-backup.
2780 2780
2781 2781 Returns 0 on success.
2782 2782 """
2783 2783
2784 2784 if opts["date"]:
2785 2785 if opts["rev"]:
2786 2786 raise util.Abort(_("you can't specify a revision and a date"))
2787 2787 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2788 2788
2789 2789 if not pats and not opts.get('all'):
2790 2790 raise util.Abort(_('no files or directories specified; '
2791 2791 'use --all to revert the whole repo'))
2792 2792
2793 2793 parent, p2 = repo.dirstate.parents()
2794 2794 if not opts.get('rev') and p2 != nullid:
2795 2795 raise util.Abort(_('uncommitted merge - please provide a '
2796 2796 'specific revision'))
2797 2797 ctx = repo[opts.get('rev')]
2798 2798 node = ctx.node()
2799 2799 mf = ctx.manifest()
2800 2800 if node == parent:
2801 2801 pmf = mf
2802 2802 else:
2803 2803 pmf = None
2804 2804
2805 2805 # need all matching names in dirstate and manifest of target rev,
2806 2806 # so have to walk both. do not print errors if files exist in one
2807 2807 # but not other.
2808 2808
2809 2809 names = {}
2810 2810
2811 2811 wlock = repo.wlock()
2812 2812 try:
2813 2813 # walk dirstate.
2814 2814
2815 2815 m = cmdutil.match(repo, pats, opts)
2816 2816 m.bad = lambda x, y: False
2817 2817 for abs in repo.walk(m):
2818 2818 names[abs] = m.rel(abs), m.exact(abs)
2819 2819
2820 2820 # walk target manifest.
2821 2821
2822 2822 def badfn(path, msg):
2823 2823 if path in names:
2824 2824 return
2825 2825 path_ = path + '/'
2826 2826 for f in names:
2827 2827 if f.startswith(path_):
2828 2828 return
2829 2829 ui.warn("%s: %s\n" % (m.rel(path), msg))
2830 2830
2831 2831 m = cmdutil.match(repo, pats, opts)
2832 2832 m.bad = badfn
2833 2833 for abs in repo[node].walk(m):
2834 2834 if abs not in names:
2835 2835 names[abs] = m.rel(abs), m.exact(abs)
2836 2836
2837 2837 m = cmdutil.matchfiles(repo, names)
2838 2838 changes = repo.status(match=m)[:4]
2839 2839 modified, added, removed, deleted = map(set, changes)
2840 2840
2841 2841 # if f is a rename, also revert the source
2842 2842 cwd = repo.getcwd()
2843 2843 for f in added:
2844 2844 src = repo.dirstate.copied(f)
2845 2845 if src and src not in names and repo.dirstate[src] == 'r':
2846 2846 removed.add(src)
2847 2847 names[src] = (repo.pathto(src, cwd), True)
2848 2848
2849 2849 def removeforget(abs):
2850 2850 if repo.dirstate[abs] == 'a':
2851 2851 return _('forgetting %s\n')
2852 2852 return _('removing %s\n')
2853 2853
2854 2854 revert = ([], _('reverting %s\n'))
2855 2855 add = ([], _('adding %s\n'))
2856 2856 remove = ([], removeforget)
2857 2857 undelete = ([], _('undeleting %s\n'))
2858 2858
2859 2859 disptable = (
2860 2860 # dispatch table:
2861 2861 # file state
2862 2862 # action if in target manifest
2863 2863 # action if not in target manifest
2864 2864 # make backup if in target manifest
2865 2865 # make backup if not in target manifest
2866 2866 (modified, revert, remove, True, True),
2867 2867 (added, revert, remove, True, False),
2868 2868 (removed, undelete, None, False, False),
2869 2869 (deleted, revert, remove, False, False),
2870 2870 )
2871 2871
2872 2872 for abs, (rel, exact) in sorted(names.items()):
2873 2873 mfentry = mf.get(abs)
2874 2874 target = repo.wjoin(abs)
2875 2875 def handle(xlist, dobackup):
2876 2876 xlist[0].append(abs)
2877 2877 if dobackup and not opts.get('no_backup') and util.lexists(target):
2878 2878 bakname = "%s.orig" % rel
2879 2879 ui.note(_('saving current version of %s as %s\n') %
2880 2880 (rel, bakname))
2881 2881 if not opts.get('dry_run'):
2882 2882 util.copyfile(target, bakname)
2883 2883 if ui.verbose or not exact:
2884 2884 msg = xlist[1]
2885 2885 if not isinstance(msg, basestring):
2886 2886 msg = msg(abs)
2887 2887 ui.status(msg % rel)
2888 2888 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2889 2889 if abs not in table:
2890 2890 continue
2891 2891 # file has changed in dirstate
2892 2892 if mfentry:
2893 2893 handle(hitlist, backuphit)
2894 2894 elif misslist is not None:
2895 2895 handle(misslist, backupmiss)
2896 2896 break
2897 2897 else:
2898 2898 if abs not in repo.dirstate:
2899 2899 if mfentry:
2900 2900 handle(add, True)
2901 2901 elif exact:
2902 2902 ui.warn(_('file not managed: %s\n') % rel)
2903 2903 continue
2904 2904 # file has not changed in dirstate
2905 2905 if node == parent:
2906 2906 if exact:
2907 2907 ui.warn(_('no changes needed to %s\n') % rel)
2908 2908 continue
2909 2909 if pmf is None:
2910 2910 # only need parent manifest in this unlikely case,
2911 2911 # so do not read by default
2912 2912 pmf = repo[parent].manifest()
2913 2913 if abs in pmf:
2914 2914 if mfentry:
2915 2915 # if version of file is same in parent and target
2916 2916 # manifests, do nothing
2917 2917 if (pmf[abs] != mfentry or
2918 2918 pmf.flags(abs) != mf.flags(abs)):
2919 2919 handle(revert, False)
2920 2920 else:
2921 2921 handle(remove, False)
2922 2922
2923 2923 if not opts.get('dry_run'):
2924 2924 def checkout(f):
2925 2925 fc = ctx[f]
2926 2926 repo.wwrite(f, fc.data(), fc.flags())
2927 2927
2928 2928 audit_path = util.path_auditor(repo.root)
2929 2929 for f in remove[0]:
2930 2930 if repo.dirstate[f] == 'a':
2931 2931 repo.dirstate.forget(f)
2932 2932 continue
2933 2933 audit_path(f)
2934 2934 try:
2935 2935 util.unlink(repo.wjoin(f))
2936 2936 except OSError:
2937 2937 pass
2938 2938 repo.dirstate.remove(f)
2939 2939
2940 2940 normal = None
2941 2941 if node == parent:
2942 2942 # We're reverting to our parent. If possible, we'd like status
2943 2943 # to report the file as clean. We have to use normallookup for
2944 2944 # merges to avoid losing information about merged/dirty files.
2945 2945 if p2 != nullid:
2946 2946 normal = repo.dirstate.normallookup
2947 2947 else:
2948 2948 normal = repo.dirstate.normal
2949 2949 for f in revert[0]:
2950 2950 checkout(f)
2951 2951 if normal:
2952 2952 normal(f)
2953 2953
2954 2954 for f in add[0]:
2955 2955 checkout(f)
2956 2956 repo.dirstate.add(f)
2957 2957
2958 2958 normal = repo.dirstate.normallookup
2959 2959 if node == parent and p2 == nullid:
2960 2960 normal = repo.dirstate.normal
2961 2961 for f in undelete[0]:
2962 2962 checkout(f)
2963 2963 normal(f)
2964 2964
2965 2965 finally:
2966 2966 wlock.release()
2967 2967
2968 2968 def rollback(ui, repo, **opts):
2969 2969 """roll back the last transaction (dangerous)
2970 2970
2971 2971 This command should be used with care. There is only one level of
2972 2972 rollback, and there is no way to undo a rollback. It will also
2973 2973 restore the dirstate at the time of the last transaction, losing
2974 2974 any dirstate changes since that time. This command does not alter
2975 2975 the working directory.
2976 2976
2977 2977 Transactions are used to encapsulate the effects of all commands
2978 2978 that create new changesets or propagate existing changesets into a
2979 2979 repository. For example, the following commands are transactional,
2980 2980 and their effects can be rolled back:
2981 2981
2982 2982 - commit
2983 2983 - import
2984 2984 - pull
2985 2985 - push (with this repository as the destination)
2986 2986 - unbundle
2987 2987
2988 2988 This command is not intended for use on public repositories. Once
2989 2989 changes are visible for pull by other users, rolling a transaction
2990 2990 back locally is ineffective (someone else may already have pulled
2991 2991 the changes). Furthermore, a race is possible with readers of the
2992 2992 repository; for example an in-progress pull from the repository
2993 2993 may fail if a rollback is performed.
2994 2994
2995 2995 Returns 0 on success, 1 if no rollback data is available.
2996 2996 """
2997 2997 return repo.rollback(opts.get('dry_run'))
2998 2998
2999 2999 def root(ui, repo):
3000 3000 """print the root (top) of the current working directory
3001 3001
3002 3002 Print the root directory of the current repository.
3003 3003
3004 3004 Returns 0 on success.
3005 3005 """
3006 3006 ui.write(repo.root + "\n")
3007 3007
3008 3008 def serve(ui, repo, **opts):
3009 3009 """start stand-alone webserver
3010 3010
3011 3011 Start a local HTTP repository browser and pull server. You can use
3012 3012 this for ad-hoc sharing and browing of repositories. It is
3013 3013 recommended to use a real web server to serve a repository for
3014 3014 longer periods of time.
3015 3015
3016 3016 Please note that the server does not implement access control.
3017 3017 This means that, by default, anybody can read from the server and
3018 3018 nobody can write to it by default. Set the ``web.allow_push``
3019 3019 option to ``*`` to allow everybody to push to the server. You
3020 3020 should use a real web server if you need to authenticate users.
3021 3021
3022 3022 By default, the server logs accesses to stdout and errors to
3023 3023 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3024 3024 files.
3025 3025
3026 3026 To have the server choose a free port number to listen on, specify
3027 3027 a port number of 0; in this case, the server will print the port
3028 3028 number it uses.
3029 3029
3030 3030 Returns 0 on success.
3031 3031 """
3032 3032
3033 3033 if opts["stdio"]:
3034 3034 if repo is None:
3035 3035 raise error.RepoError(_("There is no Mercurial repository here"
3036 3036 " (.hg not found)"))
3037 3037 s = sshserver.sshserver(ui, repo)
3038 3038 s.serve_forever()
3039 3039
3040 3040 # this way we can check if something was given in the command-line
3041 3041 if opts.get('port'):
3042 3042 opts['port'] = int(opts.get('port'))
3043 3043
3044 3044 baseui = repo and repo.baseui or ui
3045 3045 optlist = ("name templates style address port prefix ipv6"
3046 3046 " accesslog errorlog certificate encoding")
3047 3047 for o in optlist.split():
3048 3048 val = opts.get(o, '')
3049 3049 if val in (None, ''): # should check against default options instead
3050 3050 continue
3051 3051 baseui.setconfig("web", o, val)
3052 3052 if repo and repo.ui != baseui:
3053 3053 repo.ui.setconfig("web", o, val)
3054 3054
3055 3055 o = opts.get('web_conf') or opts.get('webdir_conf')
3056 3056 if not o:
3057 3057 if not repo:
3058 3058 raise error.RepoError(_("There is no Mercurial repository"
3059 3059 " here (.hg not found)"))
3060 3060 o = repo.root
3061 3061
3062 3062 app = hgweb.hgweb(o, baseui=ui)
3063 3063
3064 3064 class service(object):
3065 3065 def init(self):
3066 3066 util.set_signal_handler()
3067 3067 self.httpd = hgweb.server.create_server(ui, app)
3068 3068
3069 3069 if opts['port'] and not ui.verbose:
3070 3070 return
3071 3071
3072 3072 if self.httpd.prefix:
3073 3073 prefix = self.httpd.prefix.strip('/') + '/'
3074 3074 else:
3075 3075 prefix = ''
3076 3076
3077 3077 port = ':%d' % self.httpd.port
3078 3078 if port == ':80':
3079 3079 port = ''
3080 3080
3081 3081 bindaddr = self.httpd.addr
3082 3082 if bindaddr == '0.0.0.0':
3083 3083 bindaddr = '*'
3084 3084 elif ':' in bindaddr: # IPv6
3085 3085 bindaddr = '[%s]' % bindaddr
3086 3086
3087 3087 fqaddr = self.httpd.fqaddr
3088 3088 if ':' in fqaddr:
3089 3089 fqaddr = '[%s]' % fqaddr
3090 3090 if opts['port']:
3091 3091 write = ui.status
3092 3092 else:
3093 3093 write = ui.write
3094 3094 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3095 3095 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3096 3096
3097 3097 def run(self):
3098 3098 self.httpd.serve_forever()
3099 3099
3100 3100 service = service()
3101 3101
3102 3102 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3103 3103
3104 3104 def status(ui, repo, *pats, **opts):
3105 3105 """show changed files in the working directory
3106 3106
3107 3107 Show status of files in the repository. If names are given, only
3108 3108 files that match are shown. Files that are clean or ignored or
3109 3109 the source of a copy/move operation, are not listed unless
3110 3110 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3111 3111 Unless options described with "show only ..." are given, the
3112 3112 options -mardu are used.
3113 3113
3114 3114 Option -q/--quiet hides untracked (unknown and ignored) files
3115 3115 unless explicitly requested with -u/--unknown or -i/--ignored.
3116 3116
3117 3117 NOTE: status may appear to disagree with diff if permissions have
3118 3118 changed or a merge has occurred. The standard diff format does not
3119 3119 report permission changes and diff only reports changes relative
3120 3120 to one merge parent.
3121 3121
3122 3122 If one revision is given, it is used as the base revision.
3123 3123 If two revisions are given, the differences between them are
3124 3124 shown. The --change option can also be used as a shortcut to list
3125 3125 the changed files of a revision from its first parent.
3126 3126
3127 3127 The codes used to show the status of files are::
3128 3128
3129 3129 M = modified
3130 3130 A = added
3131 3131 R = removed
3132 3132 C = clean
3133 3133 ! = missing (deleted by non-hg command, but still tracked)
3134 3134 ? = not tracked
3135 3135 I = ignored
3136 3136 = origin of the previous file listed as A (added)
3137 3137
3138 3138 Returns 0 on success.
3139 3139 """
3140 3140
3141 3141 revs = opts.get('rev')
3142 3142 change = opts.get('change')
3143 3143
3144 3144 if revs and change:
3145 3145 msg = _('cannot specify --rev and --change at the same time')
3146 3146 raise util.Abort(msg)
3147 3147 elif change:
3148 3148 node2 = repo.lookup(change)
3149 3149 node1 = repo[node2].parents()[0].node()
3150 3150 else:
3151 3151 node1, node2 = cmdutil.revpair(repo, revs)
3152 3152
3153 3153 cwd = (pats and repo.getcwd()) or ''
3154 3154 end = opts.get('print0') and '\0' or '\n'
3155 3155 copy = {}
3156 3156 states = 'modified added removed deleted unknown ignored clean'.split()
3157 3157 show = [k for k in states if opts.get(k)]
3158 3158 if opts.get('all'):
3159 3159 show += ui.quiet and (states[:4] + ['clean']) or states
3160 3160 if not show:
3161 3161 show = ui.quiet and states[:4] or states[:5]
3162 3162
3163 3163 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3164 3164 'ignored' in show, 'clean' in show, 'unknown' in show)
3165 3165 changestates = zip(states, 'MAR!?IC', stat)
3166 3166
3167 3167 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3168 3168 ctxn = repo[nullid]
3169 3169 ctx1 = repo[node1]
3170 3170 ctx2 = repo[node2]
3171 3171 added = stat[1]
3172 3172 if node2 is None:
3173 3173 added = stat[0] + stat[1] # merged?
3174 3174
3175 3175 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3176 3176 if k in added:
3177 3177 copy[k] = v
3178 3178 elif v in added:
3179 3179 copy[v] = k
3180 3180
3181 3181 for state, char, files in changestates:
3182 3182 if state in show:
3183 3183 format = "%s %%s%s" % (char, end)
3184 3184 if opts.get('no_status'):
3185 3185 format = "%%s%s" % end
3186 3186
3187 3187 for f in files:
3188 3188 ui.write(format % repo.pathto(f, cwd),
3189 3189 label='status.' + state)
3190 3190 if f in copy:
3191 3191 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3192 3192 label='status.copied')
3193 3193
3194 3194 def summary(ui, repo, **opts):
3195 3195 """summarize working directory state
3196 3196
3197 3197 This generates a brief summary of the working directory state,
3198 3198 including parents, branch, commit status, and available updates.
3199 3199
3200 3200 With the --remote option, this will check the default paths for
3201 3201 incoming and outgoing changes. This can be time-consuming.
3202 3202
3203 3203 Returns 0 on success.
3204 3204 """
3205 3205
3206 3206 ctx = repo[None]
3207 3207 parents = ctx.parents()
3208 3208 pnode = parents[0].node()
3209 3209
3210 3210 for p in parents:
3211 3211 # label with log.changeset (instead of log.parent) since this
3212 3212 # shows a working directory parent *changeset*:
3213 3213 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3214 3214 label='log.changeset')
3215 3215 ui.write(' '.join(p.tags()), label='log.tag')
3216 3216 if p.rev() == -1:
3217 3217 if not len(repo):
3218 3218 ui.write(_(' (empty repository)'))
3219 3219 else:
3220 3220 ui.write(_(' (no revision checked out)'))
3221 3221 ui.write('\n')
3222 3222 if p.description():
3223 3223 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3224 3224 label='log.summary')
3225 3225
3226 3226 branch = ctx.branch()
3227 3227 bheads = repo.branchheads(branch)
3228 3228 m = _('branch: %s\n') % branch
3229 3229 if branch != 'default':
3230 3230 ui.write(m, label='log.branch')
3231 3231 else:
3232 3232 ui.status(m, label='log.branch')
3233 3233
3234 3234 st = list(repo.status(unknown=True))[:6]
3235 3235
3236 3236 ms = mergemod.mergestate(repo)
3237 3237 st.append([f for f in ms if ms[f] == 'u'])
3238 3238
3239 3239 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3240 3240 st.append(subs)
3241 3241
3242 3242 labels = [ui.label(_('%d modified'), 'status.modified'),
3243 3243 ui.label(_('%d added'), 'status.added'),
3244 3244 ui.label(_('%d removed'), 'status.removed'),
3245 3245 ui.label(_('%d deleted'), 'status.deleted'),
3246 3246 ui.label(_('%d unknown'), 'status.unknown'),
3247 3247 ui.label(_('%d ignored'), 'status.ignored'),
3248 3248 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3249 3249 ui.label(_('%d subrepos'), 'status.modified')]
3250 3250 t = []
3251 3251 for s, l in zip(st, labels):
3252 3252 if s:
3253 3253 t.append(l % len(s))
3254 3254
3255 3255 t = ', '.join(t)
3256 3256 cleanworkdir = False
3257 3257
3258 3258 if len(parents) > 1:
3259 3259 t += _(' (merge)')
3260 3260 elif branch != parents[0].branch():
3261 3261 t += _(' (new branch)')
3262 3262 elif (parents[0].extra().get('close') and
3263 3263 pnode in repo.branchheads(branch, closed=True)):
3264 3264 t += _(' (head closed)')
3265 3265 elif (not st[0] and not st[1] and not st[2] and not st[7]):
3266 3266 t += _(' (clean)')
3267 3267 cleanworkdir = True
3268 3268 elif pnode not in bheads:
3269 3269 t += _(' (new branch head)')
3270 3270
3271 3271 if cleanworkdir:
3272 3272 ui.status(_('commit: %s\n') % t.strip())
3273 3273 else:
3274 3274 ui.write(_('commit: %s\n') % t.strip())
3275 3275
3276 3276 # all ancestors of branch heads - all ancestors of parent = new csets
3277 3277 new = [0] * len(repo)
3278 3278 cl = repo.changelog
3279 3279 for a in [cl.rev(n) for n in bheads]:
3280 3280 new[a] = 1
3281 3281 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3282 3282 new[a] = 1
3283 3283 for a in [p.rev() for p in parents]:
3284 3284 if a >= 0:
3285 3285 new[a] = 0
3286 3286 for a in cl.ancestors(*[p.rev() for p in parents]):
3287 3287 new[a] = 0
3288 3288 new = sum(new)
3289 3289
3290 3290 if new == 0:
3291 3291 ui.status(_('update: (current)\n'))
3292 3292 elif pnode not in bheads:
3293 3293 ui.write(_('update: %d new changesets (update)\n') % new)
3294 3294 else:
3295 3295 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3296 3296 (new, len(bheads)))
3297 3297
3298 3298 if opts.get('remote'):
3299 3299 t = []
3300 3300 source, branches = hg.parseurl(ui.expandpath('default'))
3301 3301 other = hg.repository(cmdutil.remoteui(repo, {}), source)
3302 3302 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3303 3303 ui.debug('comparing with %s\n' % url.hidepassword(source))
3304 3304 repo.ui.pushbuffer()
3305 3305 common, incoming, rheads = repo.findcommonincoming(other)
3306 3306 repo.ui.popbuffer()
3307 3307 if incoming:
3308 3308 t.append(_('1 or more incoming'))
3309 3309
3310 3310 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3311 3311 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3312 3312 other = hg.repository(cmdutil.remoteui(repo, {}), dest)
3313 3313 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3314 3314 repo.ui.pushbuffer()
3315 3315 o = repo.findoutgoing(other)
3316 3316 repo.ui.popbuffer()
3317 3317 o = repo.changelog.nodesbetween(o, None)[0]
3318 3318 if o:
3319 3319 t.append(_('%d outgoing') % len(o))
3320 3320
3321 3321 if t:
3322 3322 ui.write(_('remote: %s\n') % (', '.join(t)))
3323 3323 else:
3324 3324 ui.status(_('remote: (synced)\n'))
3325 3325
3326 3326 def tag(ui, repo, name1, *names, **opts):
3327 3327 """add one or more tags for the current or given revision
3328 3328
3329 3329 Name a particular revision using <name>.
3330 3330
3331 3331 Tags are used to name particular revisions of the repository and are
3332 3332 very useful to compare different revisions, to go back to significant
3333 3333 earlier versions or to mark branch points as releases, etc.
3334 3334
3335 3335 If no revision is given, the parent of the working directory is
3336 3336 used, or tip if no revision is checked out.
3337 3337
3338 3338 To facilitate version control, distribution, and merging of tags,
3339 3339 they are stored as a file named ".hgtags" which is managed
3340 3340 similarly to other project files and can be hand-edited if
3341 3341 necessary. The file '.hg/localtags' is used for local tags (not
3342 3342 shared among repositories).
3343 3343
3344 3344 See :hg:`help dates` for a list of formats valid for -d/--date.
3345 3345
3346 3346 Since tag names have priority over branch names during revision
3347 3347 lookup, using an existing branch name as a tag name is discouraged.
3348 3348
3349 3349 Returns 0 on success.
3350 3350 """
3351 3351
3352 3352 rev_ = "."
3353 3353 names = [t.strip() for t in (name1,) + names]
3354 3354 if len(names) != len(set(names)):
3355 3355 raise util.Abort(_('tag names must be unique'))
3356 3356 for n in names:
3357 3357 if n in ['tip', '.', 'null']:
3358 3358 raise util.Abort(_('the name \'%s\' is reserved') % n)
3359 3359 if opts.get('rev') and opts.get('remove'):
3360 3360 raise util.Abort(_("--rev and --remove are incompatible"))
3361 3361 if opts.get('rev'):
3362 3362 rev_ = opts['rev']
3363 3363 message = opts.get('message')
3364 3364 if opts.get('remove'):
3365 3365 expectedtype = opts.get('local') and 'local' or 'global'
3366 3366 for n in names:
3367 3367 if not repo.tagtype(n):
3368 3368 raise util.Abort(_('tag \'%s\' does not exist') % n)
3369 3369 if repo.tagtype(n) != expectedtype:
3370 3370 if expectedtype == 'global':
3371 3371 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3372 3372 else:
3373 3373 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3374 3374 rev_ = nullid
3375 3375 if not message:
3376 3376 # we don't translate commit messages
3377 3377 message = 'Removed tag %s' % ', '.join(names)
3378 3378 elif not opts.get('force'):
3379 3379 for n in names:
3380 3380 if n in repo.tags():
3381 3381 raise util.Abort(_('tag \'%s\' already exists '
3382 3382 '(use -f to force)') % n)
3383 3383 if not rev_ and repo.dirstate.parents()[1] != nullid:
3384 3384 raise util.Abort(_('uncommitted merge - please provide a '
3385 3385 'specific revision'))
3386 3386 r = repo[rev_].node()
3387 3387
3388 3388 if not message:
3389 3389 # we don't translate commit messages
3390 3390 message = ('Added tag %s for changeset %s' %
3391 3391 (', '.join(names), short(r)))
3392 3392
3393 3393 date = opts.get('date')
3394 3394 if date:
3395 3395 date = util.parsedate(date)
3396 3396
3397 if opts.get('edit'):
3398 message = ui.edit(message, ui.username())
3399
3397 3400 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3398 3401
3399 3402 def tags(ui, repo):
3400 3403 """list repository tags
3401 3404
3402 3405 This lists both regular and local tags. When the -v/--verbose
3403 3406 switch is used, a third column "local" is printed for local tags.
3404 3407
3405 3408 Returns 0 on success.
3406 3409 """
3407 3410
3408 3411 hexfunc = ui.debugflag and hex or short
3409 3412 tagtype = ""
3410 3413
3411 3414 for t, n in reversed(repo.tagslist()):
3412 3415 if ui.quiet:
3413 3416 ui.write("%s\n" % t)
3414 3417 continue
3415 3418
3416 3419 try:
3417 3420 hn = hexfunc(n)
3418 3421 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3419 3422 except error.LookupError:
3420 3423 r = " ?:%s" % hn
3421 3424 else:
3422 3425 spaces = " " * (30 - encoding.colwidth(t))
3423 3426 if ui.verbose:
3424 3427 if repo.tagtype(t) == 'local':
3425 3428 tagtype = " local"
3426 3429 else:
3427 3430 tagtype = ""
3428 3431 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3429 3432
3430 3433 def tip(ui, repo, **opts):
3431 3434 """show the tip revision
3432 3435
3433 3436 The tip revision (usually just called the tip) is the changeset
3434 3437 most recently added to the repository (and therefore the most
3435 3438 recently changed head).
3436 3439
3437 3440 If you have just made a commit, that commit will be the tip. If
3438 3441 you have just pulled changes from another repository, the tip of
3439 3442 that repository becomes the current tip. The "tip" tag is special
3440 3443 and cannot be renamed or assigned to a different changeset.
3441 3444
3442 3445 Returns 0 on success.
3443 3446 """
3444 3447 displayer = cmdutil.show_changeset(ui, repo, opts)
3445 3448 displayer.show(repo[len(repo) - 1])
3446 3449 displayer.close()
3447 3450
3448 3451 def unbundle(ui, repo, fname1, *fnames, **opts):
3449 3452 """apply one or more changegroup files
3450 3453
3451 3454 Apply one or more compressed changegroup files generated by the
3452 3455 bundle command.
3453 3456
3454 3457 Returns 0 on success, 1 if an update has unresolved files.
3455 3458 """
3456 3459 fnames = (fname1,) + fnames
3457 3460
3458 3461 lock = repo.lock()
3459 3462 try:
3460 3463 for fname in fnames:
3461 3464 f = url.open(ui, fname)
3462 3465 gen = changegroup.readbundle(f, fname)
3463 3466 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
3464 3467 finally:
3465 3468 lock.release()
3466 3469
3467 3470 return postincoming(ui, repo, modheads, opts.get('update'), None)
3468 3471
3469 3472 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3470 3473 """update working directory (or switch revisions)
3471 3474
3472 3475 Update the repository's working directory to the specified
3473 3476 changeset.
3474 3477
3475 3478 If no changeset is specified, attempt to update to the head of the
3476 3479 current branch. If this head is a descendant of the working
3477 3480 directory's parent, update to it, otherwise abort.
3478 3481
3479 3482 The following rules apply when the working directory contains
3480 3483 uncommitted changes:
3481 3484
3482 3485 1. If neither -c/--check nor -C/--clean is specified, and if
3483 3486 the requested changeset is an ancestor or descendant of
3484 3487 the working directory's parent, the uncommitted changes
3485 3488 are merged into the requested changeset and the merged
3486 3489 result is left uncommitted. If the requested changeset is
3487 3490 not an ancestor or descendant (that is, it is on another
3488 3491 branch), the update is aborted and the uncommitted changes
3489 3492 are preserved.
3490 3493
3491 3494 2. With the -c/--check option, the update is aborted and the
3492 3495 uncommitted changes are preserved.
3493 3496
3494 3497 3. With the -C/--clean option, uncommitted changes are discarded and
3495 3498 the working directory is updated to the requested changeset.
3496 3499
3497 3500 Use null as the changeset to remove the working directory (like
3498 3501 :hg:`clone -U`).
3499 3502
3500 3503 If you want to update just one file to an older changeset, use :hg:`revert`.
3501 3504
3502 3505 See :hg:`help dates` for a list of formats valid for -d/--date.
3503 3506
3504 3507 Returns 0 on success, 1 if there are unresolved files.
3505 3508 """
3506 3509 if rev and node:
3507 3510 raise util.Abort(_("please specify just one revision"))
3508 3511
3509 3512 if not rev:
3510 3513 rev = node
3511 3514
3512 3515 if check and clean:
3513 3516 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3514 3517
3515 3518 if check:
3516 3519 # we could use dirty() but we can ignore merge and branch trivia
3517 3520 c = repo[None]
3518 3521 if c.modified() or c.added() or c.removed():
3519 3522 raise util.Abort(_("uncommitted local changes"))
3520 3523
3521 3524 if date:
3522 3525 if rev:
3523 3526 raise util.Abort(_("you can't specify a revision and a date"))
3524 3527 rev = cmdutil.finddate(ui, repo, date)
3525 3528
3526 3529 if clean or check:
3527 3530 return hg.clean(repo, rev)
3528 3531 else:
3529 3532 return hg.update(repo, rev)
3530 3533
3531 3534 def verify(ui, repo):
3532 3535 """verify the integrity of the repository
3533 3536
3534 3537 Verify the integrity of the current repository.
3535 3538
3536 3539 This will perform an extensive check of the repository's
3537 3540 integrity, validating the hashes and checksums of each entry in
3538 3541 the changelog, manifest, and tracked files, as well as the
3539 3542 integrity of their crosslinks and indices.
3540 3543
3541 3544 Returns 0 on success, 1 if errors are encountered.
3542 3545 """
3543 3546 return hg.verify(repo)
3544 3547
3545 3548 def version_(ui):
3546 3549 """output version and copyright information"""
3547 3550 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3548 3551 % util.version())
3549 3552 ui.status(_(
3550 3553 "\nCopyright (C) 2005-2010 Matt Mackall <mpm@selenic.com> and others\n"
3551 3554 "This is free software; see the source for copying conditions. "
3552 3555 "There is NO\nwarranty; "
3553 3556 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3554 3557 ))
3555 3558
3556 3559 # Command options and aliases are listed here, alphabetically
3557 3560
3558 3561 globalopts = [
3559 3562 ('R', 'repository', '',
3560 3563 _('repository root directory or name of overlay bundle file')),
3561 3564 ('', 'cwd', '', _('change working directory')),
3562 3565 ('y', 'noninteractive', None,
3563 3566 _('do not prompt, assume \'yes\' for any required answers')),
3564 3567 ('q', 'quiet', None, _('suppress output')),
3565 3568 ('v', 'verbose', None, _('enable additional output')),
3566 3569 ('', 'config', [],
3567 3570 _('set/override config option (use \'section.name=value\')')),
3568 3571 ('', 'debug', None, _('enable debugging output')),
3569 3572 ('', 'debugger', None, _('start debugger')),
3570 3573 ('', 'encoding', encoding.encoding, _('set the charset encoding')),
3571 3574 ('', 'encodingmode', encoding.encodingmode,
3572 3575 _('set the charset encoding mode')),
3573 3576 ('', 'traceback', None, _('always print a traceback on exception')),
3574 3577 ('', 'time', None, _('time how long the command takes')),
3575 3578 ('', 'profile', None, _('print command execution profile')),
3576 3579 ('', 'version', None, _('output version information and exit')),
3577 3580 ('h', 'help', None, _('display help and exit')),
3578 3581 ]
3579 3582
3580 3583 dryrunopts = [('n', 'dry-run', None,
3581 3584 _('do not perform actions, just print output'))]
3582 3585
3583 3586 remoteopts = [
3584 3587 ('e', 'ssh', '', _('specify ssh command to use')),
3585 3588 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
3586 3589 ]
3587 3590
3588 3591 walkopts = [
3589 3592 ('I', 'include', [], _('include names matching the given patterns')),
3590 3593 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3591 3594 ]
3592 3595
3593 3596 commitopts = [
3594 3597 ('m', 'message', '', _('use <text> as commit message')),
3595 3598 ('l', 'logfile', '', _('read commit message from <file>')),
3596 3599 ]
3597 3600
3598 3601 commitopts2 = [
3599 3602 ('d', 'date', '', _('record datecode as commit date')),
3600 3603 ('u', 'user', '', _('record the specified user as committer')),
3601 3604 ]
3602 3605
3603 3606 templateopts = [
3604 3607 ('', 'style', '', _('display using template map file')),
3605 3608 ('', 'template', '', _('display with template')),
3606 3609 ]
3607 3610
3608 3611 logopts = [
3609 3612 ('p', 'patch', None, _('show patch')),
3610 3613 ('g', 'git', None, _('use git extended diff format')),
3611 3614 ('l', 'limit', '', _('limit number of changes displayed')),
3612 3615 ('M', 'no-merges', None, _('do not show merges')),
3613 3616 ('', 'stat', None, _('output diffstat-style summary of changes')),
3614 3617 ] + templateopts
3615 3618
3616 3619 diffopts = [
3617 3620 ('a', 'text', None, _('treat all files as text')),
3618 3621 ('g', 'git', None, _('use git extended diff format')),
3619 3622 ('', 'nodates', None, _('omit dates from diff headers'))
3620 3623 ]
3621 3624
3622 3625 diffopts2 = [
3623 3626 ('p', 'show-function', None, _('show which function each change is in')),
3624 3627 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3625 3628 ('w', 'ignore-all-space', None,
3626 3629 _('ignore white space when comparing lines')),
3627 3630 ('b', 'ignore-space-change', None,
3628 3631 _('ignore changes in the amount of white space')),
3629 3632 ('B', 'ignore-blank-lines', None,
3630 3633 _('ignore changes whose lines are all blank')),
3631 3634 ('U', 'unified', '', _('number of lines of context to show')),
3632 3635 ('', 'stat', None, _('output diffstat-style summary of changes')),
3633 3636 ]
3634 3637
3635 3638 similarityopts = [
3636 3639 ('s', 'similarity', '',
3637 3640 _('guess renamed files by similarity (0<=s<=100)'))
3638 3641 ]
3639 3642
3640 3643 table = {
3641 3644 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3642 3645 "addremove":
3643 3646 (addremove, similarityopts + walkopts + dryrunopts,
3644 3647 _('[OPTION]... [FILE]...')),
3645 3648 "^annotate|blame":
3646 3649 (annotate,
3647 3650 [('r', 'rev', '', _('annotate the specified revision')),
3648 3651 ('', 'follow', None,
3649 3652 _('follow copies/renames and list the filename (DEPRECATED)')),
3650 3653 ('', 'no-follow', None, _("don't follow copies and renames")),
3651 3654 ('a', 'text', None, _('treat all files as text')),
3652 3655 ('u', 'user', None, _('list the author (long with -v)')),
3653 3656 ('f', 'file', None, _('list the filename')),
3654 3657 ('d', 'date', None, _('list the date (short with -q)')),
3655 3658 ('n', 'number', None, _('list the revision number (default)')),
3656 3659 ('c', 'changeset', None, _('list the changeset')),
3657 3660 ('l', 'line-number', None,
3658 3661 _('show line number at the first appearance'))
3659 3662 ] + walkopts,
3660 3663 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3661 3664 "archive":
3662 3665 (archive,
3663 3666 [('', 'no-decode', None, _('do not pass files through decoders')),
3664 3667 ('p', 'prefix', '', _('directory prefix for files in archive')),
3665 3668 ('r', 'rev', '', _('revision to distribute')),
3666 3669 ('t', 'type', '', _('type of distribution to create')),
3667 3670 ] + walkopts,
3668 3671 _('[OPTION]... DEST')),
3669 3672 "backout":
3670 3673 (backout,
3671 3674 [('', 'merge', None,
3672 3675 _('merge with old dirstate parent after backout')),
3673 3676 ('', 'parent', '', _('parent to choose when backing out merge')),
3674 3677 ('r', 'rev', '', _('revision to backout')),
3675 3678 ] + walkopts + commitopts + commitopts2,
3676 3679 _('[OPTION]... [-r] REV')),
3677 3680 "bisect":
3678 3681 (bisect,
3679 3682 [('r', 'reset', False, _('reset bisect state')),
3680 3683 ('g', 'good', False, _('mark changeset good')),
3681 3684 ('b', 'bad', False, _('mark changeset bad')),
3682 3685 ('s', 'skip', False, _('skip testing changeset')),
3683 3686 ('c', 'command', '', _('use command to check changeset state')),
3684 3687 ('U', 'noupdate', False, _('do not update to target'))],
3685 3688 _("[-gbsr] [-U] [-c CMD] [REV]")),
3686 3689 "branch":
3687 3690 (branch,
3688 3691 [('f', 'force', None,
3689 3692 _('set branch name even if it shadows an existing branch')),
3690 3693 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3691 3694 _('[-fC] [NAME]')),
3692 3695 "branches":
3693 3696 (branches,
3694 3697 [('a', 'active', False,
3695 3698 _('show only branches that have unmerged heads')),
3696 3699 ('c', 'closed', False,
3697 3700 _('show normal and closed branches'))],
3698 3701 _('[-ac]')),
3699 3702 "bundle":
3700 3703 (bundle,
3701 3704 [('f', 'force', None,
3702 3705 _('run even when the destination is unrelated')),
3703 3706 ('r', 'rev', [],
3704 3707 _('a changeset intended to be added to the destination')),
3705 3708 ('b', 'branch', [],
3706 3709 _('a specific branch you would like to bundle')),
3707 3710 ('', 'base', [],
3708 3711 _('a base changeset assumed to be available at the destination')),
3709 3712 ('a', 'all', None, _('bundle all changesets in the repository')),
3710 3713 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3711 3714 ] + remoteopts,
3712 3715 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3713 3716 "cat":
3714 3717 (cat,
3715 3718 [('o', 'output', '', _('print output to file with formatted name')),
3716 3719 ('r', 'rev', '', _('print the given revision')),
3717 3720 ('', 'decode', None, _('apply any matching decode filter')),
3718 3721 ] + walkopts,
3719 3722 _('[OPTION]... FILE...')),
3720 3723 "^clone":
3721 3724 (clone,
3722 3725 [('U', 'noupdate', None,
3723 3726 _('the clone will include an empty working copy (only a repository)')),
3724 3727 ('u', 'updaterev', '',
3725 3728 _('revision, tag or branch to check out')),
3726 3729 ('r', 'rev', [],
3727 3730 _('include the specified changeset')),
3728 3731 ('b', 'branch', [],
3729 3732 _('clone only the specified branch')),
3730 3733 ('', 'pull', None, _('use pull protocol to copy metadata')),
3731 3734 ('', 'uncompressed', None,
3732 3735 _('use uncompressed transfer (fast over LAN)')),
3733 3736 ] + remoteopts,
3734 3737 _('[OPTION]... SOURCE [DEST]')),
3735 3738 "^commit|ci":
3736 3739 (commit,
3737 3740 [('A', 'addremove', None,
3738 3741 _('mark new/missing files as added/removed before committing')),
3739 3742 ('', 'close-branch', None,
3740 3743 _('mark a branch as closed, hiding it from the branch list')),
3741 3744 ] + walkopts + commitopts + commitopts2,
3742 3745 _('[OPTION]... [FILE]...')),
3743 3746 "copy|cp":
3744 3747 (copy,
3745 3748 [('A', 'after', None, _('record a copy that has already occurred')),
3746 3749 ('f', 'force', None,
3747 3750 _('forcibly copy over an existing managed file')),
3748 3751 ] + walkopts + dryrunopts,
3749 3752 _('[OPTION]... [SOURCE]... DEST')),
3750 3753 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3751 3754 "debugcheckstate": (debugcheckstate, [], ''),
3752 3755 "debugcommands": (debugcommands, [], _('[COMMAND]')),
3753 3756 "debugcomplete":
3754 3757 (debugcomplete,
3755 3758 [('o', 'options', None, _('show the command options'))],
3756 3759 _('[-o] CMD')),
3757 3760 "debugdate":
3758 3761 (debugdate,
3759 3762 [('e', 'extended', None, _('try extended date formats'))],
3760 3763 _('[-e] DATE [RANGE]')),
3761 3764 "debugdata": (debugdata, [], _('FILE REV')),
3762 3765 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3763 3766 "debugindex": (debugindex, [], _('FILE')),
3764 3767 "debugindexdot": (debugindexdot, [], _('FILE')),
3765 3768 "debuginstall": (debuginstall, [], ''),
3766 3769 "debugrebuildstate":
3767 3770 (debugrebuildstate,
3768 3771 [('r', 'rev', '', _('revision to rebuild to'))],
3769 3772 _('[-r REV] [REV]')),
3770 3773 "debugrename":
3771 3774 (debugrename,
3772 3775 [('r', 'rev', '', _('revision to debug'))],
3773 3776 _('[-r REV] FILE')),
3774 3777 "debugsetparents":
3775 3778 (debugsetparents, [], _('REV1 [REV2]')),
3776 3779 "debugstate":
3777 3780 (debugstate,
3778 3781 [('', 'nodates', None, _('do not display the saved mtime'))],
3779 3782 _('[OPTION]...')),
3780 3783 "debugsub":
3781 3784 (debugsub,
3782 3785 [('r', 'rev', '', _('revision to check'))],
3783 3786 _('[-r REV] [REV]')),
3784 3787 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3785 3788 "^diff":
3786 3789 (diff,
3787 3790 [('r', 'rev', [], _('revision')),
3788 3791 ('c', 'change', '', _('change made by revision'))
3789 3792 ] + diffopts + diffopts2 + walkopts,
3790 3793 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
3791 3794 "^export":
3792 3795 (export,
3793 3796 [('o', 'output', '', _('print output to file with formatted name')),
3794 3797 ('', 'switch-parent', None, _('diff against the second parent')),
3795 3798 ('r', 'rev', [], _('revisions to export')),
3796 3799 ] + diffopts,
3797 3800 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3798 3801 "^forget":
3799 3802 (forget,
3800 3803 [] + walkopts,
3801 3804 _('[OPTION]... FILE...')),
3802 3805 "grep":
3803 3806 (grep,
3804 3807 [('0', 'print0', None, _('end fields with NUL')),
3805 3808 ('', 'all', None, _('print all revisions that match')),
3806 3809 ('f', 'follow', None,
3807 3810 _('follow changeset history,'
3808 3811 ' or file history across copies and renames')),
3809 3812 ('i', 'ignore-case', None, _('ignore case when matching')),
3810 3813 ('l', 'files-with-matches', None,
3811 3814 _('print only filenames and revisions that match')),
3812 3815 ('n', 'line-number', None, _('print matching line numbers')),
3813 3816 ('r', 'rev', [], _('only search files changed within revision range')),
3814 3817 ('u', 'user', None, _('list the author (long with -v)')),
3815 3818 ('d', 'date', None, _('list the date (short with -q)')),
3816 3819 ] + walkopts,
3817 3820 _('[OPTION]... PATTERN [FILE]...')),
3818 3821 "heads":
3819 3822 (heads,
3820 3823 [('r', 'rev', '', _('show only heads which are descendants of REV')),
3821 3824 ('t', 'topo', False, _('show topological heads only')),
3822 3825 ('a', 'active', False,
3823 3826 _('show active branchheads only [DEPRECATED]')),
3824 3827 ('c', 'closed', False,
3825 3828 _('show normal and closed branch heads')),
3826 3829 ] + templateopts,
3827 3830 _('[-ac] [-r REV] [REV]...')),
3828 3831 "help": (help_, [], _('[TOPIC]')),
3829 3832 "identify|id":
3830 3833 (identify,
3831 3834 [('r', 'rev', '', _('identify the specified revision')),
3832 3835 ('n', 'num', None, _('show local revision number')),
3833 3836 ('i', 'id', None, _('show global revision id')),
3834 3837 ('b', 'branch', None, _('show branch')),
3835 3838 ('t', 'tags', None, _('show tags'))],
3836 3839 _('[-nibt] [-r REV] [SOURCE]')),
3837 3840 "import|patch":
3838 3841 (import_,
3839 3842 [('p', 'strip', 1,
3840 3843 _('directory strip option for patch. This has the same '
3841 3844 'meaning as the corresponding patch option')),
3842 3845 ('b', 'base', '', _('base path')),
3843 3846 ('f', 'force', None,
3844 3847 _('skip check for outstanding uncommitted changes')),
3845 3848 ('', 'no-commit', None,
3846 3849 _("don't commit, just update the working directory")),
3847 3850 ('', 'exact', None,
3848 3851 _('apply patch to the nodes from which it was generated')),
3849 3852 ('', 'import-branch', None,
3850 3853 _('use any branch information in patch (implied by --exact)'))] +
3851 3854 commitopts + commitopts2 + similarityopts,
3852 3855 _('[OPTION]... PATCH...')),
3853 3856 "incoming|in":
3854 3857 (incoming,
3855 3858 [('f', 'force', None,
3856 3859 _('run even if remote repository is unrelated')),
3857 3860 ('n', 'newest-first', None, _('show newest record first')),
3858 3861 ('', 'bundle', '', _('file to store the bundles into')),
3859 3862 ('r', 'rev', [],
3860 3863 _('a remote changeset intended to be added')),
3861 3864 ('b', 'branch', [],
3862 3865 _('a specific branch you would like to pull')),
3863 3866 ] + logopts + remoteopts,
3864 3867 _('[-p] [-n] [-M] [-f] [-r REV]...'
3865 3868 ' [--bundle FILENAME] [SOURCE]')),
3866 3869 "^init":
3867 3870 (init,
3868 3871 remoteopts,
3869 3872 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3870 3873 "locate":
3871 3874 (locate,
3872 3875 [('r', 'rev', '', _('search the repository as it is in REV')),
3873 3876 ('0', 'print0', None,
3874 3877 _('end filenames with NUL, for use with xargs')),
3875 3878 ('f', 'fullpath', None,
3876 3879 _('print complete paths from the filesystem root')),
3877 3880 ] + walkopts,
3878 3881 _('[OPTION]... [PATTERN]...')),
3879 3882 "^log|history":
3880 3883 (log,
3881 3884 [('f', 'follow', None,
3882 3885 _('follow changeset history,'
3883 3886 ' or file history across copies and renames')),
3884 3887 ('', 'follow-first', None,
3885 3888 _('only follow the first parent of merge changesets')),
3886 3889 ('d', 'date', '', _('show revisions matching date spec')),
3887 3890 ('C', 'copies', None, _('show copied files')),
3888 3891 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3889 3892 ('r', 'rev', [], _('show the specified revision or range')),
3890 3893 ('', 'removed', None, _('include revisions where files were removed')),
3891 3894 ('m', 'only-merges', None, _('show only merges')),
3892 3895 ('u', 'user', [], _('revisions committed by user')),
3893 3896 ('', 'only-branch', [],
3894 3897 _('show only changesets within the given named branch (DEPRECATED)')),
3895 3898 ('b', 'branch', [],
3896 3899 _('show changesets within the given named branch')),
3897 3900 ('P', 'prune', [],
3898 3901 _('do not display revision or any of its ancestors')),
3899 3902 ] + logopts + walkopts,
3900 3903 _('[OPTION]... [FILE]')),
3901 3904 "manifest":
3902 3905 (manifest,
3903 3906 [('r', 'rev', '', _('revision to display'))],
3904 3907 _('[-r REV]')),
3905 3908 "^merge":
3906 3909 (merge,
3907 3910 [('f', 'force', None, _('force a merge with outstanding changes')),
3908 3911 ('r', 'rev', '', _('revision to merge')),
3909 3912 ('P', 'preview', None,
3910 3913 _('review revisions to merge (no merge is performed)'))],
3911 3914 _('[-P] [-f] [[-r] REV]')),
3912 3915 "outgoing|out":
3913 3916 (outgoing,
3914 3917 [('f', 'force', None,
3915 3918 _('run even when the destination is unrelated')),
3916 3919 ('r', 'rev', [],
3917 3920 _('a changeset intended to be included in the destination')),
3918 3921 ('n', 'newest-first', None, _('show newest record first')),
3919 3922 ('b', 'branch', [],
3920 3923 _('a specific branch you would like to push')),
3921 3924 ] + logopts + remoteopts,
3922 3925 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3923 3926 "parents":
3924 3927 (parents,
3925 3928 [('r', 'rev', '', _('show parents of the specified revision')),
3926 3929 ] + templateopts,
3927 3930 _('[-r REV] [FILE]')),
3928 3931 "paths": (paths, [], _('[NAME]')),
3929 3932 "^pull":
3930 3933 (pull,
3931 3934 [('u', 'update', None,
3932 3935 _('update to new branch head if changesets were pulled')),
3933 3936 ('f', 'force', None,
3934 3937 _('run even when remote repository is unrelated')),
3935 3938 ('r', 'rev', [],
3936 3939 _('a remote changeset intended to be added')),
3937 3940 ('b', 'branch', [],
3938 3941 _('a specific branch you would like to pull')),
3939 3942 ] + remoteopts,
3940 3943 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3941 3944 "^push":
3942 3945 (push,
3943 3946 [('f', 'force', None, _('force push')),
3944 3947 ('r', 'rev', [],
3945 3948 _('a changeset intended to be included in the destination')),
3946 3949 ('b', 'branch', [],
3947 3950 _('a specific branch you would like to push')),
3948 3951 ] + remoteopts,
3949 3952 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3950 3953 "recover": (recover, []),
3951 3954 "^remove|rm":
3952 3955 (remove,
3953 3956 [('A', 'after', None, _('record delete for missing files')),
3954 3957 ('f', 'force', None,
3955 3958 _('remove (and delete) file even if added or modified')),
3956 3959 ] + walkopts,
3957 3960 _('[OPTION]... FILE...')),
3958 3961 "rename|mv":
3959 3962 (rename,
3960 3963 [('A', 'after', None, _('record a rename that has already occurred')),
3961 3964 ('f', 'force', None,
3962 3965 _('forcibly copy over an existing managed file')),
3963 3966 ] + walkopts + dryrunopts,
3964 3967 _('[OPTION]... SOURCE... DEST')),
3965 3968 "resolve":
3966 3969 (resolve,
3967 3970 [('a', 'all', None, _('select all unresolved files')),
3968 3971 ('l', 'list', None, _('list state of files needing merge')),
3969 3972 ('m', 'mark', None, _('mark files as resolved')),
3970 3973 ('u', 'unmark', None, _('unmark files as resolved')),
3971 3974 ('n', 'no-status', None, _('hide status prefix'))]
3972 3975 + walkopts,
3973 3976 _('[OPTION]... [FILE]...')),
3974 3977 "revert":
3975 3978 (revert,
3976 3979 [('a', 'all', None, _('revert all changes when no arguments given')),
3977 3980 ('d', 'date', '', _('tipmost revision matching date')),
3978 3981 ('r', 'rev', '', _('revert to the specified revision')),
3979 3982 ('', 'no-backup', None, _('do not save backup copies of files')),
3980 3983 ] + walkopts + dryrunopts,
3981 3984 _('[OPTION]... [-r REV] [NAME]...')),
3982 3985 "rollback": (rollback, dryrunopts),
3983 3986 "root": (root, []),
3984 3987 "^serve":
3985 3988 (serve,
3986 3989 [('A', 'accesslog', '', _('name of access log file to write to')),
3987 3990 ('d', 'daemon', None, _('run server in background')),
3988 3991 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3989 3992 ('E', 'errorlog', '', _('name of error log file to write to')),
3990 3993 # use string type, then we can check if something was passed
3991 3994 ('p', 'port', '', _('port to listen on (default: 8000)')),
3992 3995 ('a', 'address', '',
3993 3996 _('address to listen on (default: all interfaces)')),
3994 3997 ('', 'prefix', '',
3995 3998 _('prefix path to serve from (default: server root)')),
3996 3999 ('n', 'name', '',
3997 4000 _('name to show in web pages (default: working directory)')),
3998 4001 ('', 'web-conf', '', _('name of the hgweb config file'
3999 4002 ' (serve more than one repository)')),
4000 4003 ('', 'webdir-conf', '', _('name of the hgweb config file'
4001 4004 ' (DEPRECATED)')),
4002 4005 ('', 'pid-file', '', _('name of file to write process ID to')),
4003 4006 ('', 'stdio', None, _('for remote clients')),
4004 4007 ('t', 'templates', '', _('web templates to use')),
4005 4008 ('', 'style', '', _('template style to use')),
4006 4009 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4007 4010 ('', 'certificate', '', _('SSL certificate file'))],
4008 4011 _('[OPTION]...')),
4009 4012 "showconfig|debugconfig":
4010 4013 (showconfig,
4011 4014 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4012 4015 _('[-u] [NAME]...')),
4013 4016 "^summary|sum":
4014 4017 (summary,
4015 4018 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4016 4019 "^status|st":
4017 4020 (status,
4018 4021 [('A', 'all', None, _('show status of all files')),
4019 4022 ('m', 'modified', None, _('show only modified files')),
4020 4023 ('a', 'added', None, _('show only added files')),
4021 4024 ('r', 'removed', None, _('show only removed files')),
4022 4025 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4023 4026 ('c', 'clean', None, _('show only files without changes')),
4024 4027 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4025 4028 ('i', 'ignored', None, _('show only ignored files')),
4026 4029 ('n', 'no-status', None, _('hide status prefix')),
4027 4030 ('C', 'copies', None, _('show source of copied files')),
4028 4031 ('0', 'print0', None,
4029 4032 _('end filenames with NUL, for use with xargs')),
4030 4033 ('', 'rev', [], _('show difference from revision')),
4031 4034 ('', 'change', '', _('list the changed files of a revision')),
4032 4035 ] + walkopts,
4033 4036 _('[OPTION]... [FILE]...')),
4034 4037 "tag":
4035 4038 (tag,
4036 4039 [('f', 'force', None, _('replace existing tag')),
4037 4040 ('l', 'local', None, _('make the tag local')),
4038 4041 ('r', 'rev', '', _('revision to tag')),
4039 4042 ('', 'remove', None, _('remove a tag')),
4040 4043 # -l/--local is already there, commitopts cannot be used
4044 ('e', 'edit', None, _('edit commit message')),
4041 4045 ('m', 'message', '', _('use <text> as commit message')),
4042 4046 ] + commitopts2,
4043 4047 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4044 4048 "tags": (tags, [], ''),
4045 4049 "tip":
4046 4050 (tip,
4047 4051 [('p', 'patch', None, _('show patch')),
4048 4052 ('g', 'git', None, _('use git extended diff format')),
4049 4053 ] + templateopts,
4050 4054 _('[-p] [-g]')),
4051 4055 "unbundle":
4052 4056 (unbundle,
4053 4057 [('u', 'update', None,
4054 4058 _('update to new branch head if changesets were unbundled'))],
4055 4059 _('[-u] FILE...')),
4056 4060 "^update|up|checkout|co":
4057 4061 (update,
4058 4062 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4059 4063 ('c', 'check', None, _('check for uncommitted changes')),
4060 4064 ('d', 'date', '', _('tipmost revision matching date')),
4061 4065 ('r', 'rev', '', _('revision'))],
4062 4066 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4063 4067 "verify": (verify, []),
4064 4068 "version": (version_, []),
4065 4069 }
4066 4070
4067 4071 norepo = ("clone init version help debugcommands debugcomplete debugdata"
4068 4072 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
4069 4073 optionalrepo = ("identify paths serve showconfig debugancestor")
@@ -1,231 +1,231 b''
1 1 % Show all commands except debug commands
2 2 add
3 3 addremove
4 4 annotate
5 5 archive
6 6 backout
7 7 bisect
8 8 branch
9 9 branches
10 10 bundle
11 11 cat
12 12 clone
13 13 commit
14 14 copy
15 15 diff
16 16 export
17 17 forget
18 18 grep
19 19 heads
20 20 help
21 21 identify
22 22 import
23 23 incoming
24 24 init
25 25 locate
26 26 log
27 27 manifest
28 28 merge
29 29 outgoing
30 30 parents
31 31 paths
32 32 pull
33 33 push
34 34 recover
35 35 remove
36 36 rename
37 37 resolve
38 38 revert
39 39 rollback
40 40 root
41 41 serve
42 42 showconfig
43 43 status
44 44 summary
45 45 tag
46 46 tags
47 47 tip
48 48 unbundle
49 49 update
50 50 verify
51 51 version
52 52
53 53 % Show all commands that start with "a"
54 54 add
55 55 addremove
56 56 annotate
57 57 archive
58 58
59 59 % Do not show debug commands if there are other candidates
60 60 diff
61 61
62 62 % Show debug commands if there are no other candidates
63 63 debugancestor
64 64 debugcheckstate
65 65 debugcommands
66 66 debugcomplete
67 67 debugconfig
68 68 debugdata
69 69 debugdate
70 70 debugfsinfo
71 71 debugindex
72 72 debugindexdot
73 73 debuginstall
74 74 debugrebuildstate
75 75 debugrename
76 76 debugsetparents
77 77 debugstate
78 78 debugsub
79 79 debugwalk
80 80
81 81 % Do not show the alias of a debug command if there are other candidates
82 82 % (this should hide rawcommit)
83 83 recover
84 84 remove
85 85 rename
86 86 resolve
87 87 revert
88 88 rollback
89 89 root
90 90
91 91 % Show the alias of a debug command if there are no other candidates
92 92
93 93
94 94 % Show the global options
95 95 --config
96 96 --cwd
97 97 --debug
98 98 --debugger
99 99 --encoding
100 100 --encodingmode
101 101 --help
102 102 --noninteractive
103 103 --profile
104 104 --quiet
105 105 --repository
106 106 --time
107 107 --traceback
108 108 --verbose
109 109 --version
110 110 -R
111 111 -h
112 112 -q
113 113 -v
114 114 -y
115 115
116 116 % Show the options for the "serve" command
117 117 --accesslog
118 118 --address
119 119 --certificate
120 120 --config
121 121 --cwd
122 122 --daemon
123 123 --daemon-pipefds
124 124 --debug
125 125 --debugger
126 126 --encoding
127 127 --encodingmode
128 128 --errorlog
129 129 --help
130 130 --ipv6
131 131 --name
132 132 --noninteractive
133 133 --pid-file
134 134 --port
135 135 --prefix
136 136 --profile
137 137 --quiet
138 138 --repository
139 139 --stdio
140 140 --style
141 141 --templates
142 142 --time
143 143 --traceback
144 144 --verbose
145 145 --version
146 146 --web-conf
147 147 -6
148 148 -A
149 149 -E
150 150 -R
151 151 -a
152 152 -d
153 153 -h
154 154 -n
155 155 -p
156 156 -q
157 157 -t
158 158 -v
159 159 -y
160 160
161 161 % Show an error if we use --options with an ambiguous abbreviation
162 162 hg: command 's' is ambiguous:
163 163 serve showconfig status summary
164 164
165 165 % Show all commands + options
166 166 add: include, exclude, dry-run
167 167 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
168 168 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
169 169 commit: addremove, close-branch, include, exclude, message, logfile, date, user
170 170 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
171 171 export: output, switch-parent, rev, text, git, nodates
172 172 forget: include, exclude
173 173 init: ssh, remotecmd
174 174 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
175 175 merge: force, rev, preview
176 176 pull: update, force, rev, branch, ssh, remotecmd
177 177 push: force, rev, branch, ssh, remotecmd
178 178 remove: after, force, include, exclude
179 179 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
180 180 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
181 181 summary: remote
182 182 update: clean, check, date, rev
183 183 addremove: similarity, include, exclude, dry-run
184 184 archive: no-decode, prefix, rev, type, include, exclude
185 185 backout: merge, parent, rev, include, exclude, message, logfile, date, user
186 186 bisect: reset, good, bad, skip, command, noupdate
187 187 branch: force, clean
188 188 branches: active, closed
189 189 bundle: force, rev, branch, base, all, type, ssh, remotecmd
190 190 cat: output, rev, decode, include, exclude
191 191 copy: after, force, include, exclude, dry-run
192 192 debugancestor:
193 193 debugcheckstate:
194 194 debugcommands:
195 195 debugcomplete: options
196 196 debugdata:
197 197 debugdate: extended
198 198 debugfsinfo:
199 199 debugindex:
200 200 debugindexdot:
201 201 debuginstall:
202 202 debugrebuildstate: rev
203 203 debugrename: rev
204 204 debugsetparents:
205 205 debugstate: nodates
206 206 debugsub: rev
207 207 debugwalk: include, exclude
208 208 grep: print0, all, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
209 209 heads: rev, topo, active, closed, style, template
210 210 help:
211 211 identify: rev, num, id, branch, tags
212 212 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
213 213 incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
214 214 locate: rev, print0, fullpath, include, exclude
215 215 manifest: rev
216 216 outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
217 217 parents: rev, style, template
218 218 paths:
219 219 recover:
220 220 rename: after, force, include, exclude, dry-run
221 221 resolve: all, list, mark, unmark, no-status, include, exclude
222 222 revert: all, date, rev, no-backup, include, exclude, dry-run
223 223 rollback: dry-run
224 224 root:
225 225 showconfig: untrusted
226 tag: force, local, rev, remove, message, date, user
226 tag: force, local, rev, remove, edit, message, date, user
227 227 tags:
228 228 tip: patch, git, style, template
229 229 unbundle: update
230 230 verify:
231 231 version:
@@ -1,75 +1,85 b''
1 1 #!/bin/sh
2 2
3 3 hg init test
4 4 cd test
5 5
6 6 echo a > a
7 7 hg add a
8 8 hg commit -m "test" -d "1000000 0"
9 9 hg history
10 10 hg tag -d "1000000 0" "bleah"
11 11 hg history
12 12
13 13 echo foo >> .hgtags
14 14 hg tag -d "1000000 0" "bleah2" || echo "failed"
15 15
16 16 hg revert .hgtags
17 17 hg tag -d "1000000 0" -r 0 x y z y y z || echo "failed"
18 18 hg tag -d "1000000 0" tap nada dot tip null . || echo "failed"
19 19 hg tag -d "1000000 0" "bleah" || echo "failed"
20 20 hg tag -d "1000000 0" "blecch" "bleah" || echo "failed"
21 21
22 22 hg tag -d "1000000 0" --remove "blecch" || echo "failed"
23 23 hg tag -d "1000000 0" --remove "bleah" "blecch" "blough" || echo "failed"
24 24
25 25 hg tag -d "1000000 0" -r 0 "bleah0"
26 26 hg tag -l -d "1000000 0" -r 1 "bleah1"
27 27 hg tag -d "1000000 0" gack gawk gorp
28 28 hg tag -d "1000000 0" -f gack
29 29 hg tag -d "1000000 0" --remove gack gorp
30 30
31 31 cat .hgtags
32 32 cat .hg/localtags
33 33
34 34 hg update 0
35 35 hg tag -d "1000000 0" "foobar"
36 36 cat .hgtags
37 37 cat .hg/localtags
38 38
39 39 hg tag -l 'xx
40 40 newline'
41 41 hg tag -l 'xx:xx'
42 42
43 43 echo % cloning local tags
44 44 cd ..
45 45 hg -R test log -r0:5
46 46 hg clone -q -rbleah1 test test1
47 47 hg -R test1 parents --style=compact
48 48 hg clone -q -r5 test#bleah1 test2
49 49 hg -R test2 parents --style=compact
50 50 hg clone -q -U test#bleah1 test3
51 51 hg -R test3 parents --style=compact
52 52
53 53 cd test
54 54 echo % issue 601
55 55 python << EOF
56 56 f = file('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
57 57 f = file('.hg/localtags', 'w'); f.write(last); f.close()
58 58 EOF
59 59 cat .hg/localtags
60 60 hg tag -l localnewline
61 61 cat .hg/localtags
62 62
63 63 python << EOF
64 64 f = file('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
65 65 f = file('.hgtags', 'w'); f.write(last); f.close()
66 66 EOF
67 67 hg ci -d '1000000 0' -m'broken manual edit of .hgtags'
68 68 cat .hgtags
69 69 hg tag -d '1000000 0' newline
70 70 cat .hgtags
71 71
72 72 echo % tag and branch using same name
73 73 hg branch tag-and-branch-same-name
74 74 hg ci -m"discouraged"
75 75 hg tag tag-and-branch-same-name
76
77 echo '% test custom commit messages'
78 cat > $HGTMP/editor <<'__EOF__'
79 #!/bin/sh
80 echo "custom tag message" > "$1"
81 echo "second line" >> "$1"
82 __EOF__
83 chmod +x "$HGTMP"/editor
84 HGEDITOR="'$HGTMP'"/editor hg tag custom-tag -e
85 hg log -l1 --template "{desc}\n"
@@ -1,99 +1,102 b''
1 1 changeset: 0:0acdaf898367
2 2 tag: tip
3 3 user: test
4 4 date: Mon Jan 12 13:46:40 1970 +0000
5 5 summary: test
6 6
7 7 changeset: 1:3ecf002a1c57
8 8 tag: tip
9 9 user: test
10 10 date: Mon Jan 12 13:46:40 1970 +0000
11 11 summary: Added tag bleah for changeset 0acdaf898367
12 12
13 13 changeset: 0:0acdaf898367
14 14 tag: bleah
15 15 user: test
16 16 date: Mon Jan 12 13:46:40 1970 +0000
17 17 summary: test
18 18
19 19 abort: working copy of .hgtags is changed (please commit .hgtags manually)
20 20 failed
21 21 abort: tag names must be unique
22 22 failed
23 23 abort: the name 'tip' is reserved
24 24 failed
25 25 abort: tag 'bleah' already exists (use -f to force)
26 26 failed
27 27 abort: tag 'bleah' already exists (use -f to force)
28 28 failed
29 29 abort: tag 'blecch' does not exist
30 30 failed
31 31 abort: tag 'blecch' does not exist
32 32 failed
33 33 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
34 34 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
35 35 868cc8fbb43b754ad09fa109885d243fc49adae7 gack
36 36 868cc8fbb43b754ad09fa109885d243fc49adae7 gawk
37 37 868cc8fbb43b754ad09fa109885d243fc49adae7 gorp
38 38 868cc8fbb43b754ad09fa109885d243fc49adae7 gack
39 39 3807bcf62c5614cb6c16436b514d7764ca5f1631 gack
40 40 3807bcf62c5614cb6c16436b514d7764ca5f1631 gack
41 41 0000000000000000000000000000000000000000 gack
42 42 868cc8fbb43b754ad09fa109885d243fc49adae7 gorp
43 43 0000000000000000000000000000000000000000 gorp
44 44 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
45 45 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
46 46 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
47 47 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
48 48 abort: '\n' cannot be used in a tag name
49 49 abort: ':' cannot be used in a tag name
50 50 % cloning local tags
51 51 changeset: 0:0acdaf898367
52 52 tag: bleah
53 53 tag: bleah0
54 54 tag: foobar
55 55 user: test
56 56 date: Mon Jan 12 13:46:40 1970 +0000
57 57 summary: test
58 58
59 59 changeset: 1:3ecf002a1c57
60 60 tag: bleah1
61 61 user: test
62 62 date: Mon Jan 12 13:46:40 1970 +0000
63 63 summary: Added tag bleah for changeset 0acdaf898367
64 64
65 65 changeset: 2:868cc8fbb43b
66 66 tag: gawk
67 67 user: test
68 68 date: Mon Jan 12 13:46:40 1970 +0000
69 69 summary: Added tag bleah0 for changeset 0acdaf898367
70 70
71 71 changeset: 3:3807bcf62c56
72 72 user: test
73 73 date: Mon Jan 12 13:46:40 1970 +0000
74 74 summary: Added tag gack, gawk, gorp for changeset 868cc8fbb43b
75 75
76 76 changeset: 4:140c6e8597b4
77 77 user: test
78 78 date: Mon Jan 12 13:46:40 1970 +0000
79 79 summary: Added tag gack for changeset 3807bcf62c56
80 80
81 81 changeset: 5:470a65fa7cc9
82 82 user: test
83 83 date: Mon Jan 12 13:46:40 1970 +0000
84 84 summary: Removed tag gack, gorp
85 85
86 86 1[tip] 3ecf002a1c57 1970-01-12 13:46 +0000 test
87 87 Added tag bleah for changeset 0acdaf898367
88 88
89 89 5[tip] 470a65fa7cc9 1970-01-12 13:46 +0000 test
90 90 Removed tag gack, gorp
91 91
92 92 % issue 601
93 93 3ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah13ecf002a1c572a2f3bb4e665417e60fca65bbd42 bleah1
94 94 f68b039e72eacbb2e68b0543e1f6e50990aa2bb5 localnewline
95 95 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
96 96 6ae703d793c8b1f097116869275ecd97b2977a2b newline
97 97 % tag and branch using same name
98 98 marked working directory as branch tag-and-branch-same-name
99 99 warning: tag tag-and-branch-same-name conflicts with existing branch name
100 % test custom commit messages
101 custom tag message
102 second line
General Comments 0
You need to be logged in to leave comments. Login now