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("", "--good", help="known good revision (default HEAD~100)", default
='HEAD~100')
13 parser
.add_option("", "--bad", help="known bad revision (default HEAD)", default
='HEAD')
14 parser
.add_option("", "--skip-build-errors", help="skip revision where make fails",
15 action
='store_true', default
=False)
16 parser
.add_option("", "--autogen", help="run autogen before each build",action
="store_true", default
=False)
17 parser
.add_option("", "--autogen-command", help="command to use for autogen (default ./autogen.sh)",
18 type='str', default
="./autogen.sh")
19 parser
.add_option("", "--configure", help="run configure.developer before each build",
20 action
="store_true", default
=False)
21 parser
.add_option("", "--configure-command", help="the command for configure (default ./configure.developer)",
22 type='str', default
="./configure.developer")
23 parser
.add_option("", "--build-command", help="the command to build the tree (default 'make -j')",
24 type='str', default
="make -j")
25 parser
.add_option("", "--test-command", help="the command to test the tree (default 'make test')",
26 type='str', default
="make test")
27 parser
.add_option("", "--clean", help="run make clean before each build",
28 action
="store_true", default
=False)
31 (opts
, args
) = parser
.parse_args()
34 def run_cmd(cmd
, dir=".", show
=True, output
=False, checkfail
=True):
36 print("Running: '%s' in '%s'" % (cmd
, dir))
38 return Popen([cmd
], shell
=True, stdout
=PIPE
, cwd
=dir).communicate()[0]
40 return check_call(cmd
, shell
=True, cwd
=dir)
42 return call(cmd
, shell
=True, cwd
=dir)
45 '''get to the top of the git repo'''
48 if os
.path
.isdir(os
.path
.join(p
, ".git")):
50 p
= os
.path
.abspath(os
.path
.join(p
, '..'))
54 gitroot
= find_git_root()
56 # create a bisect script
57 f
= tempfile
.NamedTemporaryFile(delete
=False)
59 f
.write("cd %s || exit 125\n" % cwd
)
61 f
.write("%s || exit 125\n" % opts
.autogen_command
)
63 f
.write("%s || exit 125\n" % opts
.configure_command
)
65 f
.write("make clean || exit 125\n")
66 if opts
.skip_build_errors
:
70 f
.write("%s || exit %u\n" % (opts
.build_command
, build_err
))
71 f
.write("%s || exit 1\n" % opts
.test_command
)
76 run_cmd("git bisect reset", dir=gitroot
)
83 run_cmd("git bisect reset", dir=gitroot
, show
=False, checkfail
=False)
84 run_cmd("git bisect start %s %s --" % (opts
.bad
, opts
.good
), dir=gitroot
)
85 ret
= run_cmd("git bisect run bash %s" % f
.name
, dir=gitroot
, show
=True, checkfail
=False)
86 except KeyboardInterrupt:
89 except Exception as reason
:
90 print("Failed bisect: %s" % reason
)
93 run_cmd("git bisect reset", dir=gitroot
)