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