2 # use git bisect to work out what commit caused a test failure
3 # Copyright Andrew Tridgell 2010
4 # released under GNU GPL v3 or later
7 from subprocess
import call
, check_call
, Popen
, PIPE
8 import os
, tempfile
, sys
9 from optparse
import OptionParser
11 parser
= OptionParser()
12 parser
.add_option("", "--tests", help="list of tests to run", default
='*')
13 parser
.add_option("", "--quick", help="use make quicktest", default
='')
14 parser
.add_option("", "--good", help="known good revision (default HEAD~100)", default
='HEAD~100')
15 parser
.add_option("", "--bad", help="known bad revision (default HEAD)", default
='HEAD')
16 parser
.add_option("", "--skip-build-errors", help="skip revision where make fails",
17 action
='store_true', default
=False)
18 parser
.add_option("", "--autogen", help="run autogen before each build",action
="store_true", default
=False)
19 parser
.add_option("", "--configure", help="run configure.developer before each build",
20 action
="store_true", default
=False)
21 parser
.add_option("", "--clean", help="run make clean before each build",
22 action
="store_true", default
=False)
23 parser
.add_option("-j", "", help="use make -j N", dest
='N', type='int', action
="store", default
=1)
25 (opts
, args
) = parser
.parse_args()
28 def run_cmd(cmd
, dir=".", show
=True, output
=False, checkfail
=True):
30 print("Running: '%s' in '%s'" % (cmd
, dir))
32 return Popen([cmd
], shell
=True, stdout
=PIPE
, cwd
=dir).communicate()[0]
34 return check_call(cmd
, shell
=True, cwd
=dir)
36 return call(cmd
, shell
=True, cwd
=dir)
39 '''get to the top of the git repo'''
42 if os
.path
.isdir(os
.path
.join(p
, ".git")):
44 p
= os
.path
.abspath(os
.path
.join(p
, '..'))
48 gitroot
= find_git_root()
50 # create a bisect script
51 f
= tempfile
.NamedTemporaryFile(delete
=False)
53 f
.write("cd %s || exit 125\n" % cwd
)
55 f
.write("./autogen.sh || exit 125\n")
57 f
.write("./configure.developer || exit 125\n")
59 f
.write("make clean || exit 125\n")
60 if opts
.skip_build_errors
:
61 f
.write("make -j %u || exit 125\n" % opts
.N
)
63 f
.write("make -j %u || exit 1\n" % opts
.N
)
68 f
.write("make -j %u %s TESTS='%s' FAIL_IMMEDIATELY=1 || exit 1\n" % (opts
.N
, target
, opts
.tests
))
73 run_cmd("git bisect reset", dir=gitroot
)
80 run_cmd("git bisect reset", dir=gitroot
, show
=False, checkfail
=False)
81 run_cmd("git bisect start %s %s --" % (opts
.bad
, opts
.good
), dir=gitroot
)
82 ret
= run_cmd("git bisect run bash %s" % f
.name
, dir=gitroot
, show
=True, checkfail
=False)
83 except KeyboardInterrupt:
86 except Exception, reason
:
87 print("Failed bisect: %s" % reason
)