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