# HG changeset patch # User Matt Mackall # Date 1199146834 21600 # Node ID 35ec669cdd43e807a5420e2d0f6f04620c005789 # Parent 2dd202a6e15bb45d8d3f10acde440bdb3d12e3b0 bisect: handle search for bad to good transitions Automatically detect whether we're looking for a bad to good transition rather than the usual good to bad transition by detecting when badrev is inside the good set and flipping good/bad. diff -r 2dd202a6e15b -r 35ec669cdd43 mercurial/commands.py --- a/mercurial/commands.py Mon Dec 31 18:20:34 2007 -0600 +++ b/mercurial/commands.py Mon Dec 31 18:20:34 2007 -0600 @@ -258,11 +258,6 @@ working directory as bad or good and bisect will either update to another candidate changeset or announce that it has found the bad revision. - - Note: bisect expects bad revisions to be descendants of good - revisions. If you are looking for the point at which a problem was - fixed, then make the problem-free state \"bad\" and the - problematic state \"good.\" """ # backward compatibility if rev in "good bad reset init".split(): @@ -317,9 +312,9 @@ return # actually bisect - node, changesets = hbisect.bisect(repo.changelog, state) + node, changesets, good = hbisect.bisect(repo.changelog, state) if changesets == 0: - ui.write(_("The first bad revision is:\n")) + ui.write(_("The first %s revision is:\n") % (good and "good" or "bad")) displayer = cmdutil.show_changeset(ui, repo, {}) displayer.show(changenode=node) elif node is not None: diff -r 2dd202a6e15b -r 35ec669cdd43 mercurial/hbisect.py --- a/mercurial/hbisect.py Mon Dec 31 18:20:34 2007 -0600 +++ b/mercurial/hbisect.py Mon Dec 31 18:20:34 2007 -0600 @@ -12,25 +12,36 @@ def bisect(changelog, state): clparents = changelog.parentrevs - # only the earliest bad revision matters - badrev = min([changelog.rev(n) for n in state['bad']]) - bad = changelog.node(badrev) skip = dict.fromkeys([changelog.rev(n) for n in state['skip']]) - # build ancestors array - ancestors = [[]] * (changelog.count() + 1) # an extra for [-1] + def buildancestors(bad, good): + # only the earliest bad revision matters + badrev = min([changelog.rev(n) for n in bad]) + goodrevs = [changelog.rev(n) for n in good] + # build ancestors array + ancestors = [[]] * (changelog.count() + 1) # an extra for [-1] - # clear good revs from array - for node in state['good']: - ancestors[changelog.rev(node)] = None - for rev in xrange(changelog.count(), -1, -1): - if ancestors[rev] is None: - for prev in clparents(rev): - ancestors[prev] = None + # clear good revs from array + for node in goodrevs: + ancestors[node] = None + for rev in xrange(changelog.count(), -1, -1): + if ancestors[rev] is None: + for prev in clparents(rev): + ancestors[prev] = None - if ancestors[badrev] is None: + if ancestors[badrev] is None: + return None, None + return badrev, ancestors + + good = 0 + badrev, ancestors = buildancestors(state['bad'], state['good']) + if not ancestors: # looking for bad to good transition? + good = 1 + badrev, ancestors = buildancestors(state['good'], state['bad']) + if not ancestors: # now we're confused raise util.Abort(_("Inconsistent state, %s:%s is good and bad") % (badrev, hg.short(bad))) + bad = changelog.node(badrev) # build children dict children = {} @@ -52,7 +63,7 @@ # have we narrowed it down to one entry? tot = len(candidates) if tot == 1: - return (bad, 0) + return (bad, 0, good) perfect = tot / 2 # find the best node to test @@ -91,4 +102,4 @@ assert best_rev is not None best_node = changelog.node(best_rev) - return (best_node, tot) + return (best_node, tot, good) diff -r 2dd202a6e15b -r 35ec669cdd43 tests/test-bisect --- a/tests/test-bisect Mon Dec 31 18:20:34 2007 -0600 +++ b/tests/test-bisect Mon Dec 31 18:20:34 2007 -0600 @@ -31,3 +31,13 @@ hg bisect -g hg bisect -b hg bisect -g + +echo % bisect reverse test +hg bisect -r +hg bisect -b null +hg bisect -g tip +hg bisect -g +hg bisect -g +hg bisect -g +hg bisect -b +hg bisect -g diff -r 2dd202a6e15b -r 35ec669cdd43 tests/test-bisect.out --- a/tests/test-bisect.out Mon Dec 31 18:20:34 2007 -0600 +++ b/tests/test-bisect.out Mon Dec 31 18:20:34 2007 -0600 @@ -214,3 +214,20 @@ date: Thu Jan 01 00:00:29 1970 +0000 summary: msg 29 +% bisect reverse test +Testing changeset 15:e7fa0811edb0 (32 changesets remaining, ~5 tests) +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +Testing changeset 7:03750880c6b5 (16 changesets remaining, ~4 tests) +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +Testing changeset 3:b53bea5e2fcb (8 changesets remaining, ~3 tests) +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +Testing changeset 1:5cd978ea5149 (4 changesets remaining, ~2 tests) +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +Testing changeset 2:db07c04beaca (2 changesets remaining, ~1 tests) +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +The first good revision is: +changeset: 2:db07c04beaca +user: test +date: Thu Jan 01 00:00:02 1970 +0000 +summary: msg 2 +