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