[PATCH 1 of 2] hbisect.get: use simpler code with repo.set(), fix 'pruned' set

Yann E. MORIN yann.morin.1998 at anciens.enib.fr
Tue Sep 20 13:23:06 CDT 2011


# HG changeset patch
# User "Yann E. MORIN" <yann.morin.1998 at anciens.enib.fr>
# Date 1316542788 -7200
# Node ID c5c1442b7ce44935fbf70d7c3012ea1ddc0bc37d
# Parent  353a1ba928f682a0a3e29bf54b90c7cdc2f98fef
hbisect.get: use simpler code with repo.set(), fix 'pruned' set

Use repo.set() wherever possible, instead of locally trying to
reproduce complex graph computations.

'pruned' now means 'all csets that will no longer be visited by the
bisection'. The change is done is this very patch instead of its own
dedicated one becasue the code changes all over the place, and the
previous 'pruned' code was totally rewritten by the cleanup, so it
was easier to just change the behavior at the same time.

The previous series went in too fast for this cleanup pass to be
included, so here it is. ;-)

Signed-off-by: "Yann E. MORIN" <yann.morin.1998 at anciens.enib.fr>

diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
--- a/mercurial/hbisect.py
+++ b/mercurial/hbisect.py
@@ -160,44 +160,43 @@
 
     - ``good``, ``bad``, ``skip``: as the names imply
     - ``range``              : all csets taking part in the bisection
-    - ``pruned``             : good|bad|skip, excluding out-of-range csets
+    - ``pruned``             : csets that are good, bad or skipped
     - ``untested``           : csets whose fate is yet unknown
     """
     state = load_state(repo)
     if status in ('good', 'bad', 'skip'):
         return [repo.changelog.rev(n) for n in state[status]]
     else:
-        # Build sets of good, bad, and skipped csets
-        goods = set(repo.changelog.rev(n) for n in state['good'])
-        bads  = set(repo.changelog.rev(n) for n in state['bad'])
-        skips = set(repo.changelog.rev(n) for n in state['skip'])
+        # In the floowing sets, we do *not* call 'bisect()' with more
+        # than one level of recusrsion, because that can be very, very
+        # time consuming. Instead, we always develop the expression as
+        # much as possible.
 
-        # Build kinship of good csets
-        ga = goods.copy()   # Goods' Ancestors
-        gd = goods.copy()   # Goods' Descendants
-        for g in goods:
-            ga |= set(repo.changelog.ancestors(g))
-            gd |= set(repo.changelog.descendants(g))
+        # 'range' is all csets that make the bisection:
+        #   - have a good ancestor and a bad descendant, or conversely
+        # that's because the bisection can go either way
+        range = '( bisect(bad)::bisect(good) | bisect(good)::bisect(bad) )'
 
-        # Build kinship of bad csets
-        ba = bads.copy()    # Bads' Ancestors
-        bd = bads.copy()    # Bads' Descendants
-        for b in bads:
-            ba |= set(repo.changelog.ancestors(b))
-            bd |= set(repo.changelog.descendants(b))
+        # '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)
 
-        # Build the range of the bisection
-        range  = set(c for c in ba if c in gd)
-        range |= set(c for c in ga if c in bd)
+        # 'untested' is all cset that are- in 'range', but not in 'pruned'
+        untested = '( (%s) - (%s) )' % (range, pruned)
 
         if status == 'range':
-            return [c for c in range]
+            return [c.rev() for c in repo.set(range)]
         elif status == 'pruned':
-            # We do not want skipped csets that are out-of-range
-            return [c for c in range if c in (goods | bads | skips)]
+            return [c.rev() for c in repo.set(pruned)]
         elif status == 'untested':
-            # Return the csets in range that are not pruned
-            return [c for c in range if not c in (goods | bads | skips)]
+            return [c.rev() for c in repo.set(untested)]
 
         else:
             raise error.ParseError(_('invalid bisect state'))
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -241,7 +241,7 @@
     ``skip``), or any of the meta-status:
 
     - ``range``      : all csets taking part in the bisection
-    - ``pruned``     : good|bad|skip, excluding out-of-range csets
+    - ``pruned``     : csets that are good, bad or skipped
     - ``untested``   : csets whose fate is yet unknown
     """
     status = getstring(x, _("bisect requires a string")).lower()
diff --git a/tests/test-bisect2.t b/tests/test-bisect2.t
--- a/tests/test-bisect2.t
+++ b/tests/test-bisect2.t
@@ -252,6 +252,9 @@
   $ hg bisect -b 17   # -> update to rev 6
   Testing changeset 6:a214d5d3811a (15 changesets remaining, ~3 tests)
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg log -q -r 'bisect(pruned)'
+  0:33b1f9bc8bc5
+  17:228c06deef46
   $ hg log -q -r 'bisect(untested)'
   1:4ca5088da217
   2:051e12f87bf1
@@ -305,22 +308,22 @@
   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
   13:b0a32c86eb31
+  15:857b178a7cf3
+  16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(untested)'
-  1:4ca5088da217
-  2:051e12f87bf1
-  3:0950834f0a9c
-  4:5c668c22234f
-  5:385a529b6670
   11:82ca6f06eccd
   12:9f259202bbe7
-  15:857b178a7cf3
-  16:609d82a7ebae
 
 complex bisect test 2  # first good rev is 13
 
@@ -332,16 +335,25 @@
   $ hg bisect -s      # -> update to rev 10
   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)'
+  1:4ca5088da217
+  6:a214d5d3811a
+  18:d42e18c7bc9b
   $ hg bisect -b      # -> update to rev 12
   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(untested)'
+  $ hg log -q -r 'bisect(pruned)'
+  1:4ca5088da217
   2:051e12f87bf1
   3:0950834f0a9c
   4:5c668c22234f
   5:385a529b6670
+  6:a214d5d3811a
   8:dab8161ac8fc
   9:3c77083deb4a
+  10:429fcd26f52d
+  18:d42e18c7bc9b
+  $ hg log -q -r 'bisect(untested)'
   11:82ca6f06eccd
   12:9f259202bbe7
   13:b0a32c86eb31
@@ -371,13 +383,6 @@
   13:b0a32c86eb31
   15:857b178a7cf3
   18:d42e18c7bc9b
-  $ hg log -q -r 'bisect(pruned)'
-  1:4ca5088da217
-  6:a214d5d3811a
-  10:429fcd26f52d
-  12:9f259202bbe7
-  13:b0a32c86eb31
-  18:d42e18c7bc9b
 
 complex bisect test 3
 
@@ -389,6 +394,9 @@
   $ hg bisect -b 16   # -> update to rev 6
   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)'
+  1:4ca5088da217
+  16:609d82a7ebae
   $ 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
@@ -398,6 +406,16 @@
   $ hg bisect -s      # -> update to rev 12
   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)'
+  1:4ca5088da217
+  2:051e12f87bf1
+  3:0950834f0a9c
+  4:5c668c22234f
+  5:385a529b6670
+  6:a214d5d3811a
+  10:429fcd26f52d
+  13:b0a32c86eb31
+  16:609d82a7ebae
   $ 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
@@ -445,15 +463,6 @@
   13:b0a32c86eb31
   15:857b178a7cf3
   16:609d82a7ebae
-  $ hg log -q -r 'bisect(pruned)'
-  1:4ca5088da217
-  6:a214d5d3811a
-  9:3c77083deb4a
-  10:429fcd26f52d
-  12:9f259202bbe7
-  13:b0a32c86eb31
-  15:857b178a7cf3
-  16:609d82a7ebae
 
 complex bisect test 4
 
@@ -471,9 +480,26 @@
   $ hg bisect -b      # -> update to rev 15
   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)'
+  8:dab8161ac8fc
+  9:3c77083deb4a
+  10:429fcd26f52d
+  11:82ca6f06eccd
+  12:9f259202bbe7
+  13:b0a32c86eb31
+  17:228c06deef46
   $ hg bisect -s      # -> update to rev 16
   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)'
+  8:dab8161ac8fc
+  9:3c77083deb4a
+  10:429fcd26f52d
+  11:82ca6f06eccd
+  12:9f259202bbe7
+  13:b0a32c86eb31
+  15:857b178a7cf3
+  17:228c06deef46
   $ hg bisect -s
   Due to skipped revisions, the first good revision could be any of:
   changeset:   15:857b178a7cf3
@@ -505,7 +531,10 @@
   17:228c06deef46
   $ hg log -q -r 'bisect(pruned)'
   8:dab8161ac8fc
+  9:3c77083deb4a
   10:429fcd26f52d
+  11:82ca6f06eccd
+  12:9f259202bbe7
   13:b0a32c86eb31
   15:857b178a7cf3
   16:609d82a7ebae
@@ -520,6 +549,8 @@
   [255]
   $ hg log -q -r 'bisect(range)'
   $ hg log -q -r 'bisect(pruned)'
+  7:50c76098bbf2
+  14:faa450606157
   $ hg bisect --reset
 
 end at merge: 17 bad, 11 good (but 9 is first bad)
@@ -553,21 +584,22 @@
   17:228c06deef46
   $ hg log -q -r 'bisect(pruned)'
   11:82ca6f06eccd
+  12:9f259202bbe7
   13:b0a32c86eb31
   15:857b178a7cf3
+  16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(untested)'
-  12:9f259202bbe7
-  16:609d82a7ebae
   $ hg bisect --extend
   Extending search to changeset 8:dab8161ac8fc
   2 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg log -q -r 'bisect(untested)'
-  12:9f259202bbe7
-  16:609d82a7ebae
   $ hg bisect -g # dab8161ac8fc
   Testing changeset 9:3c77083deb4a (3 changesets remaining, ~1 tests)
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg log -q -r 'bisect(untested)'
+  9:3c77083deb4a
+  10:429fcd26f52d
   $ hg bisect -b
   The first bad revision is:
   changeset:   9:3c77083deb4a
@@ -588,14 +620,14 @@
   $ hg log -q -r 'bisect(pruned)'
   8:dab8161ac8fc
   9:3c77083deb4a
+  10:429fcd26f52d
   11:82ca6f06eccd
+  12:9f259202bbe7
   13:b0a32c86eb31
   15:857b178a7cf3
+  16:609d82a7ebae
   17:228c06deef46
   $ hg log -q -r 'bisect(untested)'
-  10:429fcd26f52d
-  12:9f259202bbe7
-  16:609d82a7ebae
 
 user adds irrelevant but consistent information (here: -g 2) to bisect state
 
@@ -627,8 +659,9 @@
   12:9f259202bbe7
   13:b0a32c86eb31
   $ hg log -q -r 'bisect(pruned)'
+  2:051e12f87bf1
   8:dab8161ac8fc
   11:82ca6f06eccd
+  12:9f259202bbe7
   13:b0a32c86eb31
   $ hg log -q -r 'bisect(untested)'
-  12:9f259202bbe7


More information about the Mercurial-devel mailing list