summaryrefslogtreecommitdiff
path: root/bin/svn-bisect.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/svn-bisect.py')
-rwxr-xr-xbin/svn-bisect.py72
1 files changed, 72 insertions, 0 deletions
diff --git a/bin/svn-bisect.py b/bin/svn-bisect.py
new file mode 100755
index 0000000..e9ebcf8
--- /dev/null
+++ b/bin/svn-bisect.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# -*- Python -*-
+
+import sys
+from math import log, ceil
+from optparse import OptionParser
+import subprocess
+
+# crack the command line
+parser = OptionParser(
+ usage="%prog lower-revision upper-revision test_script [arg1 ...]",
+ description="Binary search for a bug in a SVN checkout")
+(options,script_args) = parser.parse_args()
+
+# make sure we have sufficient parameters
+if len(script_args) < 1:
+ parser.error("Need a lower revision")
+elif len(script_args) < 2:
+ parser.error("Need an upper revision")
+elif len(script_args) < 3:
+ parser.error("Need a script to run")
+
+# extract our starting values
+lower = int(script_args[0])
+upper = int(script_args[1])
+script = script_args[2:]
+
+# print an error message and quit
+def error(s):
+ print >>sys.stderr, "******", s, "******"
+ sys.exit(1)
+
+# update to the specified version and run test
+def testfail(revision):
+ "Return true if test fails"
+ print "Updating to revision", revision
+ if subprocess.call(["svn","up","-qr",str(revision)]) != 0:
+ m = "SVN did not update properly to revision %d"
+ raise RuntimeError(m % revision)
+ return subprocess.call(script,shell=False) != 0
+
+# confirm that the endpoints are different
+print "****** Checking upper bracket", upper
+upperfails = testfail(upper)
+print "****** Checking lower bracket", lower
+lowerfails = testfail(lower)
+if upperfails == lowerfails:
+ error("Upper and lower revisions must bracket the failure")
+
+# binary search for transition
+msg = "****** max %d revisions to test (bug bracketed by [%d,%d])"
+while upper-lower > 1:
+ print msg % (ceil(log(upper-lower,2)), lower, upper)
+
+ mid = int((lower + upper)/2)
+ midfails = testfail(mid)
+ if midfails == lowerfails:
+ lower = mid
+ lowerfails = midfails
+ else:
+ upper = mid
+ upperfails = midfails
+
+# show which revision was first to fail
+if upperfails != lowerfails: lower = upper
+print "The error was caused by revision", lower
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: