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