changeset 15161:f3edee8dc40c

merge with crew
author Matt Mackall <mpm@selenic.com>
date Wed, 28 Sep 2011 13:57:48 -0500
parents 85322c19c831 (diff) b2d4400398f3 (current diff)
children d67a15b2e608
files
diffstat 14 files changed, 441 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/setup3k.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/contrib/setup3k.py	Wed Sep 28 13:57:48 2011 -0500
@@ -309,7 +309,7 @@
 else:
     extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
 
-if sys.platform == 'linux2' and os.uname()[2] > '2.6':
+if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
     # The inotify extension is only usable with Linux 2.6 kernels.
     # You also need a reasonably recent C library.
     # In any case, if it fails to build the error will be skipped ('optional').
--- a/hgext/inotify/server.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/hgext/inotify/server.py	Wed Sep 28 13:57:48 2011 -0500
@@ -443,7 +443,7 @@
             if err.args[0] != errno.EPIPE:
                 raise
 
-if sys.platform == 'linux2':
+if sys.platform.startswith('linux'):
     import linuxserver as _server
 else:
     raise ImportError
--- a/mercurial/hbisect.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/hbisect.py	Wed Sep 28 13:57:48 2011 -0500
@@ -158,9 +158,10 @@
     """
     Return a list of revision(s) that match the given status:
 
-    - ``good``, ``bad``, ``skip``: as the names imply
-    - ``range``              : all csets taking part in the bisection
-    - ``pruned``             : csets that are good, bad or skipped
+    - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
+    - ``goods``, ``bads``      : csets topologicaly good/bad
+    - ``range``              : csets taking part in the bisection
+    - ``pruned``             : csets that are goods, bads or skipped
     - ``untested``           : csets whose fate is yet unknown
     - ``ignored``            : csets ignored due to DAG topology
     """
@@ -178,16 +179,20 @@
         # that's because the bisection can go either way
         range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
 
-        # 'pruned' is all csets whose fate is already known:
-        #   - a good ancestor and a good ascendant, or
-        #   - a bad ancestor and a bad descendant, or
-        #   - skipped
-        # But in case of irrelevant goods/bads, we also need to
-        # include them.
-        pg = 'bisect(good)::bisect(good)'   # Pruned goods
-        pb = 'bisect(bad)::bisect(bad)'     # Pruned bads
-        ps = 'bisect(skip)'                 # Pruned skipped
-        pruned = '( (%s) | (%s) | (%s) )' % (pg, pb, ps)
+        _t = [c.rev() for c in repo.set('bisect(good)::bisect(bad)')]
+        # The sets of topologically good or bad csets
+        if len(_t) == 0:
+            # Goods are topologically after bads
+            goods = 'bisect(good)::'    # Pruned good csets
+            bads  = '::bisect(bad)'     # Pruned bad csets
+        else:
+            # Goods are topologically before bads
+            goods = '::bisect(good)'    # Pruned good csets
+            bads  = 'bisect(bad)::'     # Pruned bad csets
+
+        # 'pruned' is all csets whose fate is already known: good, bad, skip
+        skips = 'bisect(skip)'                 # Pruned skipped csets
+        pruned = '( (%s) | (%s) | (%s) )' % (goods, bads, skips)
 
         # 'untested' is all cset that are- in 'range', but not in 'pruned'
         untested = '( (%s) - (%s) )' % (range, pruned)
@@ -208,6 +213,39 @@
             return [c.rev() for c in repo.set(untested)]
         elif status == 'ignored':
             return [c.rev() for c in repo.set(ignored)]
+        elif status == "goods":
+            return [c.rev() for c in repo.set(goods)]
+        elif status == "bads":
+            return [c.rev() for c in repo.set(bads)]
 
         else:
             raise error.ParseError(_('invalid bisect state'))
+
+def label(repo, node, short=False):
+    rev = repo.changelog.rev(node)
+
+    # Try explicit sets
+    if rev in get(repo, 'good'):
+        return _('good')
+    if rev in get(repo, 'bad'):
+        return _('bad')
+    if rev in get(repo, 'skip'):
+        return _('skipped')
+    if rev in get(repo, 'untested'):
+        return _('untested')
+    if rev in get(repo, 'ignored'):
+        return _('ignored')
+
+    # Try implicit sets
+    if rev in get(repo, 'goods'):
+        return _('good (implicit)')
+    if rev in get(repo, 'bads'):
+        return _('bad (implicit)')
+
+    return None
+
+def shortlabel(label):
+    if label:
+        return label[0].upper()
+
+    return None
--- a/mercurial/httpconnection.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/httpconnection.py	Wed Sep 28 13:57:48 2011 -0500
@@ -22,8 +22,9 @@
 class httpsendfile(object):
     """This is a wrapper around the objects returned by python's "open".
 
-    Its purpose is to send file-like objects via HTTP and, to do so, it
-    defines a __len__ attribute to feed the Content-Length header.
+    Its purpose is to send file-like objects via HTTP.
+    It do however not define a __len__ attribute because the length
+    might be more than Py_ssize_t can handle.
     """
 
     def __init__(self, ui, *args, **kwargs):
@@ -35,9 +36,9 @@
         self.seek = self._data.seek
         self.close = self._data.close
         self.write = self._data.write
-        self._len = os.fstat(self._data.fileno()).st_size
+        self.length = os.fstat(self._data.fileno()).st_size
         self._pos = 0
-        self._total = self._len / 1024 * 2
+        self._total = self.length / 1024 * 2
 
     def read(self, *args, **kwargs):
         try:
@@ -54,9 +55,6 @@
                          unit=_('kb'), total=self._total)
         return ret
 
-    def __len__(self):
-        return self._len
-
 # moved here from url.py to avoid a cycle
 def readauthforuri(ui, uri, user):
     # Read configuration
--- a/mercurial/httprepo.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/httprepo.py	Wed Sep 28 13:57:48 2011 -0500
@@ -73,9 +73,14 @@
         if cmd == 'pushkey':
             args['data'] = ''
         data = args.pop('data', None)
+        size = 0
+        if util.safehasattr(data, 'length'):
+            size = data.length
+        elif data is not None:
+            size = len(data)
         headers = args.pop('headers', {})
 
-        if data and self.ui.configbool('ui', 'usehttp2', False):
+        if size and self.ui.configbool('ui', 'usehttp2', False):
             headers['Expect'] = '100-Continue'
             headers['X-HgHttp2'] = '1'
 
@@ -104,9 +109,6 @@
         cu = "%s%s" % (self._url, qs)
         req = urllib2.Request(cu, data, headers)
         if data is not None:
-            # len(data) is broken if data doesn't fit into Py_ssize_t
-            # add the header ourself to avoid OverflowError
-            size = data.__len__()
             self.ui.debug("sending %s bytes\n" % size)
             req.add_unredirected_header('Content-Length', '%d' % size)
         try:
--- a/mercurial/patch.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/patch.py	Wed Sep 28 13:57:48 2011 -0500
@@ -188,7 +188,7 @@
                 pend = subject.find(']')
                 if pend >= 0:
                     subject = subject[pend + 1:].lstrip()
-            subject = subject.replace('\n\t', ' ')
+            subject = re.sub(r'\n[ \t]+', ' ', subject)
             ui.debug('Subject: %s\n' % subject)
         if user:
             ui.debug('From: %s\n' % user)
--- a/mercurial/revset.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/revset.py	Wed Sep 28 13:57:48 2011 -0500
@@ -237,13 +237,14 @@
 
 def bisect(repo, subset, x):
     """``bisect(string)``
-    Changesets marked in the specified bisect status (``good``, ``bad``,
-    ``skip``), or any of the meta-status:
+    Changesets marked in the specified bisect status:
 
-    - ``range``      : all csets taking part in the bisection
-    - ``pruned``     : csets that are good, bad or skipped
-    - ``untested``   : csets whose fate is yet unknown
-    - ``ignored``    : csets ignored due to DAG topology
+    - ``good``, ``bad``, ``skip``: csets explicitly marked as good/bad/skip
+    - ``goods``, ``bads``      : csets topologicaly good/bad
+    - ``range``              : csets taking part in the bisection
+    - ``pruned``             : csets that are goods, bads or skipped
+    - ``untested``           : csets whose fate is yet unknown
+    - ``ignored``            : csets ignored due to DAG topology
     """
     status = getstring(x, _("bisect requires a string")).lower()
     return [r for r in subset if r in hbisect.get(repo, status)]
--- a/mercurial/templatefilters.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/templatefilters.py	Wed Sep 28 13:57:48 2011 -0500
@@ -7,6 +7,7 @@
 
 import cgi, re, os, time, urllib
 import encoding, node, util
+import hbisect
 
 def addbreaks(text):
     """:addbreaks: Any text. Add an XHTML "<br />" tag before the end of
@@ -268,6 +269,14 @@
     """
     return text[:12]
 
+def shortbisect(text):
+    """:shortbisect: Any text. Treats `text` as a bisection status, and
+    returns a single-character representing the status (G: good, B: bad,
+    S: skipped, U: untested, I: ignored). Returns single space if `text`
+    is not a valid bisection status.
+    """
+    return hbisect.shortlabel(text) or ' '
+
 def shortdate(text):
     """:shortdate: Date. Returns a date like "2006-09-18"."""
     return util.shortdate(text)
@@ -347,6 +356,7 @@
     "rfc3339date": rfc3339date,
     "rfc822date": rfc822date,
     "short": short,
+    "shortbisect": shortbisect,
     "shortdate": shortdate,
     "stringescape": stringescape,
     "stringify": stringify,
--- a/mercurial/templatekw.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/templatekw.py	Wed Sep 28 13:57:48 2011 -0500
@@ -7,6 +7,7 @@
 
 from node import hex
 import patch, util, error
+import hbisect
 
 def showlist(name, values, plural=None, **args):
     '''expand set of values.
@@ -145,6 +146,10 @@
     """:author: String. The unmodified author of the changeset."""
     return ctx.user()
 
+def showbisect(repo, ctx, templ, **args):
+    """:bisect: String. The changeset bisection status."""
+    return hbisect.label(repo, ctx.node())
+
 def showbranch(**args):
     """:branch: String. The name of the branch on which the changeset was
     committed.
@@ -288,6 +293,7 @@
 # revcache - a cache dictionary for the current revision
 keywords = {
     'author': showauthor,
+    'bisect': showbisect,
     'branch': showbranch,
     'branches': showbranches,
     'bookmarks': showbookmarks,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/templates/map-cmdline.bisect	Wed Sep 28 13:57:48 2011 -0500
@@ -0,0 +1,25 @@
+changeset = 'changeset:   {rev}:{node|short}\nbisect:      {bisect}\n{branches}{bookmarks}{tags}{parents}user:        {author}\ndate:        {date|date}\nsummary:     {desc|firstline}\n\n'
+changeset_quiet = '{bisect|shortbisect} {rev}:{node|short}\n'
+changeset_verbose = 'changeset:   {rev}:{node|short}\nbisect:      {bisect}\n{branches}{bookmarks}{tags}{parents}user:        {author}\ndate:        {date|date}\n{files}{file_copies_switch}description:\n{desc|strip}\n\n\n'
+changeset_debug = 'changeset:   {rev}:{node}\nbisect:      {bisect}\n{branches}{bookmarks}{tags}{parents}{manifest}user:        {author}\ndate:        {date|date}\n{file_mods}{file_adds}{file_dels}{file_copies_switch}{extras}description:\n{desc|strip}\n\n\n'
+start_files = 'files:      '
+file = ' {file}'
+end_files = '\n'
+start_file_mods = 'files:      '
+file_mod = ' {file_mod}'
+end_file_mods = '\n'
+start_file_adds = 'files+:     '
+file_add = ' {file_add}'
+end_file_adds = '\n'
+start_file_dels = 'files-:     '
+file_del = ' {file_del}'
+end_file_dels = '\n'
+start_file_copies = 'copies:     '
+file_copy = ' {name} ({source})'
+end_file_copies = '\n'
+parent = 'parent:      {rev}:{node|formatnode}\n'
+manifest = 'manifest:    {rev}:{node}\n'
+branch = 'branch:      {branch}\n'
+tag = 'tag:         {tag}\n'
+bookmark = 'bookmark:    {bookmark}\n'
+extra = 'extra:       {key}={value|stringescape}\n'
--- a/mercurial/util.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/mercurial/util.py	Wed Sep 28 13:57:48 2011 -0500
@@ -913,7 +913,12 @@
         minutes = abs(tz) // 60
         format = format.replace("%1", "%c%02d" % (sign, minutes // 60))
         format = format.replace("%2", "%02d" % (minutes % 60))
-    s = time.strftime(format, time.gmtime(float(t) - tz))
+    try:
+        t = time.gmtime(float(t) - tz)
+    except ValueError:
+        # time was out of range
+        t = time.gmtime(sys.maxint)
+    s = time.strftime(format, t)
     return s
 
 def shortdate(date=None):
--- a/setup.py	Tue Sep 27 18:51:10 2011 +0200
+++ b/setup.py	Wed Sep 28 13:57:48 2011 -0500
@@ -366,7 +366,7 @@
     extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
                                 extra_link_args=osutil_ldflags))
 
-if sys.platform == 'linux2' and os.uname()[2] > '2.6':
+if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
     # The inotify extension is only usable with Linux 2.6 kernels.
     # You also need a reasonably recent C library.
     # In any case, if it fails to build the error will be skipped ('optional').
--- a/tests/test-bisect2.t	Tue Sep 27 18:51:10 2011 +0200
+++ b/tests/test-bisect2.t	Wed Sep 28 13:57:48 2011 -0500
@@ -322,9 +322,26 @@
   15:857b178a7cf3
   16:609d82a7ebae
   17:228c06deef46
+  18:d42e18c7bc9b
   $ hg log -q -r 'bisect(untested)'
   11:82ca6f06eccd
   12:9f259202bbe7
+  $ hg log -q -r 'bisect(goods)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
+  5:385a529b6670
+  6:a214d5d3811a
+  8:dab8161ac8fc
+  $ hg log -q -r 'bisect(bads)'
+  9:3c77083deb4a
+  10:429fcd26f52d
+  15:857b178a7cf3
+  16:609d82a7ebae
+  17:228c06deef46
+  18:d42e18c7bc9b
 
 complex bisect test 2  # first good rev is 13
 
@@ -337,6 +354,7 @@
   Testing changeset 10:429fcd26f52d (13 changesets remaining, ~3 tests)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
   1:4ca5088da217
   6:a214d5d3811a
   18:d42e18c7bc9b
@@ -344,6 +362,7 @@
   Testing changeset 12:9f259202bbe7 (5 changesets remaining, ~2 tests)
   3 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
   1:4ca5088da217
   2:051e12f87bf1
   3:0950834f0a9c
@@ -396,8 +415,10 @@
   Testing changeset 6:a214d5d3811a (13 changesets remaining, ~3 tests)
   2 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
   1:4ca5088da217
   16:609d82a7ebae
+  17:228c06deef46
   $ hg bisect -g      # -> update to rev 13
   Testing changeset 13:b0a32c86eb31 (8 changesets remaining, ~3 tests)
   3 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -408,6 +429,7 @@
   Testing changeset 12:9f259202bbe7 (8 changesets remaining, ~3 tests)
   3 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
   1:4ca5088da217
   2:051e12f87bf1
   3:0950834f0a9c
@@ -417,6 +439,7 @@
   10:429fcd26f52d
   13:b0a32c86eb31
   16:609d82a7ebae
+  17:228c06deef46
   $ hg bisect -g      # -> update to rev 9
   Testing changeset 9:3c77083deb4a (5 changesets remaining, ~2 tests)
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -484,6 +507,13 @@
   Testing changeset 15:857b178a7cf3 (3 changesets remaining, ~1 tests)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
+  5:385a529b6670
+  6:a214d5d3811a
   8:dab8161ac8fc
   9:3c77083deb4a
   10:429fcd26f52d
@@ -495,6 +525,13 @@
   Testing changeset 16:609d82a7ebae (3 changesets remaining, ~1 tests)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
+  5:385a529b6670
+  6:a214d5d3811a
   8:dab8161ac8fc
   9:3c77083deb4a
   10:429fcd26f52d
@@ -533,6 +570,13 @@
   16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
+  5:385a529b6670
+  6:a214d5d3811a
   8:dab8161ac8fc
   9:3c77083deb4a
   10:429fcd26f52d
@@ -552,6 +596,11 @@
   [255]
   $ hg log -q -r 'bisect(range)'
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
   7:50c76098bbf2
   14:faa450606157
   $ hg bisect --reset
@@ -594,12 +643,16 @@
   16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  8:dab8161ac8fc
   11:82ca6f06eccd
   12:9f259202bbe7
   13:b0a32c86eb31
   15:857b178a7cf3
   16:609d82a7ebae
   17:228c06deef46
+  18:d42e18c7bc9b
   $ hg log -q -r 'bisect(untested)'
   $ hg log -q -r 'bisect(ignored)'
   2:051e12f87bf1
@@ -633,6 +686,18 @@
   4:5c668c22234f
   5:385a529b6670
   6:a214d5d3811a
+  $ hg log -q -r 'bisect(goods)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  8:dab8161ac8fc
+  11:82ca6f06eccd
+  12:9f259202bbe7
+  13:b0a32c86eb31
+  $ hg log -q -r 'bisect(bads)'
+  15:857b178a7cf3
+  16:609d82a7ebae
+  17:228c06deef46
+  18:d42e18c7bc9b
   $ hg bisect -b
   The first bad revision is:
   changeset:   9:3c77083deb4a
@@ -651,6 +716,8 @@
   16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
   8:dab8161ac8fc
   9:3c77083deb4a
   10:429fcd26f52d
@@ -660,6 +727,7 @@
   15:857b178a7cf3
   16:609d82a7ebae
   17:228c06deef46
+  18:d42e18c7bc9b
   $ hg log -q -r 'bisect(untested)'
   $ hg log -q -r 'bisect(ignored)'
   2:051e12f87bf1
@@ -667,6 +735,20 @@
   4:5c668c22234f
   5:385a529b6670
   6:a214d5d3811a
+  $ hg log -q -r 'bisect(goods)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
+  8:dab8161ac8fc
+  11:82ca6f06eccd
+  12:9f259202bbe7
+  13:b0a32c86eb31
+  $ hg log -q -r 'bisect(bads)'
+  9:3c77083deb4a
+  10:429fcd26f52d
+  15:857b178a7cf3
+  16:609d82a7ebae
+  17:228c06deef46
+  18:d42e18c7bc9b
 
 user adds irrelevant but consistent information (here: -g 2) to bisect state
 
@@ -698,9 +780,16 @@
   12:9f259202bbe7
   13:b0a32c86eb31
   $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  1:4ca5088da217
   2:051e12f87bf1
   8:dab8161ac8fc
   11:82ca6f06eccd
   12:9f259202bbe7
   13:b0a32c86eb31
+  14:faa450606157
+  15:857b178a7cf3
+  16:609d82a7ebae
+  17:228c06deef46
+  18:d42e18c7bc9b
   $ hg log -q -r 'bisect(untested)'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-bisect3.t	Wed Sep 28 13:57:48 2011 -0500
@@ -0,0 +1,232 @@
+# Here we create a simple DAG which has just enough of the required
+# topology to test all the bisection status labels:
+#
+#           13--14
+#          /
+#   0--1--2--3---------9--10--11--12
+#       \             /
+#        4--5--6--7--8
+
+
+  $ hg init
+
+  $ echo '0' >a
+  $ hg add a
+  $ hg ci -u test -d '0 0' -m '0'
+  $ echo '1' >a
+  $ hg ci -u test -d '0 1' -m '1'
+
+branch 2-3
+
+  $ echo '2' >b
+  $ hg add b
+  $ hg ci -u test -d '0 2' -m '2'
+  $ echo '3' >b
+  $ hg ci -u test -d '0 3' -m '3'
+
+branch 4-8
+
+  $ hg up -r 1
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo '4' >c
+  $ hg add c
+  $ hg ci -u test -d '0 4' -m '4'
+  created new head
+  $ echo '5' >c
+  $ hg ci -u test -d '0 5' -m '5'
+  $ echo '6' >c
+  $ hg ci -u test -d '0 6' -m '6'
+  $ echo '7' >c
+  $ hg ci -u test -d '0 7' -m '7'
+  $ echo '8' >c
+  $ hg ci -u test -d '0 8' -m '8'
+
+merge
+
+  $ hg merge -r 3
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -u test -d '0 9' -m '9=8+3'
+
+  $ echo '10' >a
+  $ hg ci -u test -d '0 10' -m '10'
+  $ echo '11' >a
+  $ hg ci -u test -d '0 11' -m '11'
+  $ echo '12' >a
+  $ hg ci -u test -d '0 12' -m '12'
+
+unrelated branch
+
+  $ hg up -r 3
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo '13' >d
+  $ hg add d
+  $ hg ci -u test -d '0 13' -m '13'
+  created new head
+  $ echo '14' >d
+  $ hg ci -u test -d '0 14' -m '14'
+
+mark changesets
+
+  $ hg bisect --reset
+  $ hg bisect --good 4
+  $ hg bisect --good 6
+  $ hg bisect --bad 12
+  Testing changeset 9:8bcbdb072033 (6 changesets remaining, ~2 tests)
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg bisect --bad 10
+  Testing changeset 8:3cd112f87d77 (4 changesets remaining, ~2 tests)
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg bisect --skip 7
+  Testing changeset 8:3cd112f87d77 (4 changesets remaining, ~2 tests)
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+test template
+
+  $ hg log --template '{rev}:{node|short} {bisect}\n'
+  14:cecd84203acc 
+  13:86f7c8cdb6df 
+  12:a76089b5f47c bad
+  11:5c3eb122d29c bad (implicit)
+  10:b097cef2be03 bad
+  9:8bcbdb072033 untested
+  8:3cd112f87d77 untested
+  7:577e237a73bd skipped
+  6:e597fa2707c5 good
+  5:b9cea37a76bc good (implicit)
+  4:da6b357259d7 good
+  3:e7f031aee8ca ignored
+  2:b1ad1b6bcc5c ignored
+  1:37f42ae8b45e good (implicit)
+  0:b4e73ffab476 good (implicit)
+  $ hg log --template '{bisect|shortbisect} {rev}:{node|short}\n'
+    14:cecd84203acc
+    13:86f7c8cdb6df
+  B 12:a76089b5f47c
+  B 11:5c3eb122d29c
+  B 10:b097cef2be03
+  U 9:8bcbdb072033
+  U 8:3cd112f87d77
+  S 7:577e237a73bd
+  G 6:e597fa2707c5
+  G 5:b9cea37a76bc
+  G 4:da6b357259d7
+  I 3:e7f031aee8ca
+  I 2:b1ad1b6bcc5c
+  G 1:37f42ae8b45e
+  G 0:b4e73ffab476
+
+test style
+
+  $ hg log --style bisect
+  changeset:   14:cecd84203acc
+  bisect:      
+  tag:         tip
+  user:        test
+  date:        Wed Dec 31 23:59:46 1969 -0000
+  summary:     14
+  
+  changeset:   13:86f7c8cdb6df
+  bisect:      
+  parent:      3:e7f031aee8ca
+  user:        test
+  date:        Wed Dec 31 23:59:47 1969 -0000
+  summary:     13
+  
+  changeset:   12:a76089b5f47c
+  bisect:      bad
+  user:        test
+  date:        Wed Dec 31 23:59:48 1969 -0000
+  summary:     12
+  
+  changeset:   11:5c3eb122d29c
+  bisect:      bad (implicit)
+  user:        test
+  date:        Wed Dec 31 23:59:49 1969 -0000
+  summary:     11
+  
+  changeset:   10:b097cef2be03
+  bisect:      bad
+  user:        test
+  date:        Wed Dec 31 23:59:50 1969 -0000
+  summary:     10
+  
+  changeset:   9:8bcbdb072033
+  bisect:      untested
+  parent:      8:3cd112f87d77
+  parent:      3:e7f031aee8ca
+  user:        test
+  date:        Wed Dec 31 23:59:51 1969 -0000
+  summary:     9=8+3
+  
+  changeset:   8:3cd112f87d77
+  bisect:      untested
+  user:        test
+  date:        Wed Dec 31 23:59:52 1969 -0000
+  summary:     8
+  
+  changeset:   7:577e237a73bd
+  bisect:      skipped
+  user:        test
+  date:        Wed Dec 31 23:59:53 1969 -0000
+  summary:     7
+  
+  changeset:   6:e597fa2707c5
+  bisect:      good
+  user:        test
+  date:        Wed Dec 31 23:59:54 1969 -0000
+  summary:     6
+  
+  changeset:   5:b9cea37a76bc
+  bisect:      good (implicit)
+  user:        test
+  date:        Wed Dec 31 23:59:55 1969 -0000
+  summary:     5
+  
+  changeset:   4:da6b357259d7
+  bisect:      good
+  parent:      1:37f42ae8b45e
+  user:        test
+  date:        Wed Dec 31 23:59:56 1969 -0000
+  summary:     4
+  
+  changeset:   3:e7f031aee8ca
+  bisect:      ignored
+  user:        test
+  date:        Wed Dec 31 23:59:57 1969 -0000
+  summary:     3
+  
+  changeset:   2:b1ad1b6bcc5c
+  bisect:      ignored
+  user:        test
+  date:        Wed Dec 31 23:59:58 1969 -0000
+  summary:     2
+  
+  changeset:   1:37f42ae8b45e
+  bisect:      good (implicit)
+  user:        test
+  date:        Wed Dec 31 23:59:59 1969 -0000
+  summary:     1
+  
+  changeset:   0:b4e73ffab476
+  bisect:      good (implicit)
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     0
+  
+  $ hg log --quiet --style bisect
+    14:cecd84203acc
+    13:86f7c8cdb6df
+  B 12:a76089b5f47c
+  B 11:5c3eb122d29c
+  B 10:b097cef2be03
+  U 9:8bcbdb072033
+  U 8:3cd112f87d77
+  S 7:577e237a73bd
+  G 6:e597fa2707c5
+  G 5:b9cea37a76bc
+  G 4:da6b357259d7
+  I 3:e7f031aee8ca
+  I 2:b1ad1b6bcc5c
+  G 1:37f42ae8b45e
+  G 0:b4e73ffab476