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