mercurial/commands.py
changeset 5775 2dd202a6e15b
parent 5764 8a5d8fb59ed2
child 5776 35ec669cdd43
equal deleted inserted replaced
5774:c850a8640981 5775:2dd202a6e15b
     9 from i18n import _
     9 from i18n import _
    10 import os, re, sys, urllib
    10 import os, re, sys, urllib
    11 import hg, util, revlog, bundlerepo, extensions
    11 import hg, util, revlog, bundlerepo, extensions
    12 import difflib, patch, time, help, mdiff, tempfile
    12 import difflib, patch, time, help, mdiff, tempfile
    13 import errno, version, socket
    13 import errno, version, socket
    14 import archival, changegroup, cmdutil, hgweb.server, sshserver
    14 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
    15 
    15 
    16 # Commands start here, listed alphabetically
    16 # Commands start here, listed alphabetically
    17 
    17 
    18 def add(ui, repo, *pats, **opts):
    18 def add(ui, repo, *pats, **opts):
    19     """add the specified files on the next commit
    19     """add the specified files on the next commit
   243         else:
   243         else:
   244             ui.status(_('the backout changeset is a new head - '
   244             ui.status(_('the backout changeset is a new head - '
   245                         'do not forget to merge\n'))
   245                         'do not forget to merge\n'))
   246             ui.status(_('(use "backout --merge" '
   246             ui.status(_('(use "backout --merge" '
   247                         'if you want to auto-merge)\n'))
   247                         'if you want to auto-merge)\n'))
       
   248 
       
   249 def bisect(ui, repo, rev=None, extra=None,
       
   250                reset=None, good=None, bad=None, skip=None, noupdate=None):
       
   251     """subdivision search of changesets
       
   252 
       
   253     This command helps to find changesets which introduce problems.
       
   254     To use, mark the earliest changeset you know exhibits the problem
       
   255     as bad, then mark the latest changeset which is free from the
       
   256     problem as good. Bisect will update your working directory to a
       
   257     revision for testing. Once you have performed tests, mark the
       
   258     working directory as bad or good and bisect will either update to
       
   259     another candidate changeset or announce that it has found the bad
       
   260     revision.
       
   261 
       
   262     Note: bisect expects bad revisions to be descendants of good
       
   263     revisions. If you are looking for the point at which a problem was
       
   264     fixed, then make the problem-free state \"bad\" and the
       
   265     problematic state \"good.\"
       
   266     """
       
   267     # backward compatibility
       
   268     if rev in "good bad reset init".split():
       
   269         ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
       
   270         cmd, rev, extra = rev, extra, None
       
   271         if cmd == "good":
       
   272             good = True
       
   273         elif cmd == "bad":
       
   274             bad = True
       
   275         else:
       
   276             reset = True
       
   277     elif extra or good + bad + skip + reset > 1:
       
   278         raise util.Abort("Incompatible arguments")
       
   279 
       
   280     if reset:
       
   281         p = repo.join("bisect.state")
       
   282         if os.path.exists(p):
       
   283             os.unlink(p)
       
   284         return
       
   285 
       
   286     # load state
       
   287     state = {'good': [], 'bad': [], 'skip': []}
       
   288     if os.path.exists(repo.join("bisect.state")):
       
   289         for l in repo.opener("bisect.state"):
       
   290             kind, node = l[:-1].split()
       
   291             node = repo.lookup(node)
       
   292             if kind not in state:
       
   293                 raise util.Abort(_("unknown bisect kind %s") % kind)
       
   294             state[kind].append(node)
       
   295 
       
   296     # update state
       
   297     node = repo.lookup(rev or '.')
       
   298     if good:
       
   299         state['good'].append(node)
       
   300     elif bad:
       
   301         state['bad'].append(node)
       
   302     elif skip:
       
   303         state['skip'].append(node)
       
   304 
       
   305     # save state
       
   306     f = repo.opener("bisect.state", "w", atomictemp=True)
       
   307     wlock = repo.wlock()
       
   308     try:
       
   309         for kind in state:
       
   310             for node in state[kind]:
       
   311                 f.write("%s %s\n" % (kind, hg.hex(node)))
       
   312         f.rename()
       
   313     finally:
       
   314         del wlock
       
   315 
       
   316     if not state['good'] or not state['bad']:
       
   317         return
       
   318 
       
   319     # actually bisect
       
   320     node, changesets = hbisect.bisect(repo.changelog, state)
       
   321     if changesets == 0:
       
   322         ui.write(_("The first bad revision is:\n"))
       
   323         displayer = cmdutil.show_changeset(ui, repo, {})
       
   324         displayer.show(changenode=node)
       
   325     elif node is not None:
       
   326         # compute the approximate number of remaining tests
       
   327         tests, size = 0, 2
       
   328         while size <= changesets:
       
   329             tests, size = tests + 1, size * 2
       
   330         rev = repo.changelog.rev(node)
       
   331         ui.write(_("Testing changeset %s:%s "
       
   332                    "(%s changesets remaining, ~%s tests)\n")
       
   333                  % (rev, hg.short(node), changesets, tests))
       
   334         if not noupdate:
       
   335             cmdutil.bail_if_changed(repo)
       
   336             return hg.clean(repo, node)
   248 
   337 
   249 def branch(ui, repo, label=None, **opts):
   338 def branch(ui, repo, label=None, **opts):
   250     """set or show the current branch name
   339     """set or show the current branch name
   251 
   340 
   252     With no argument, show the current branch name. With one argument,
   341     With no argument, show the current branch name. With one argument,
  2656            _('merge with old dirstate parent after backout')),
  2745            _('merge with old dirstate parent after backout')),
  2657           ('', 'parent', '', _('parent to choose when backing out merge')),
  2746           ('', 'parent', '', _('parent to choose when backing out merge')),
  2658           ('r', 'rev', '', _('revision to backout')),
  2747           ('r', 'rev', '', _('revision to backout')),
  2659          ] + walkopts + commitopts + commitopts2,
  2748          ] + walkopts + commitopts + commitopts2,
  2660          _('hg backout [OPTION]... [-r] REV')),
  2749          _('hg backout [OPTION]... [-r] REV')),
       
  2750     "bisect": (bisect,
       
  2751                [('r', 'reset', False, _('reset bisect state')),
       
  2752                 ('g', 'good', False, _('mark changeset good')),
       
  2753                 ('b', 'bad', False, _('mark changeset bad')),
       
  2754                 ('s', 'skip', False, _('skip testing changeset')),
       
  2755                 ('U', 'noupdate', False, _('do not update to target'))],
       
  2756                _("hg bisect [-gbsr] [REV]")),
  2661     "branch":
  2757     "branch":
  2662         (branch,
  2758         (branch,
  2663          [('f', 'force', None,
  2759          [('f', 'force', None,
  2664            _('set branch name even if it shadows an existing branch'))],
  2760            _('set branch name even if it shadows an existing branch'))],
  2665          _('hg branch [NAME]')),
  2761          _('hg branch [NAME]')),