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