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