| 1 | import os |
| 2 | import term |
| 3 | import flag |
| 4 | |
| 5 | const tools_folder = os.real_path(os.dir(os.executable())) |
| 6 | |
| 7 | const oldvexe = fullpath(tools_folder, 'oldv') |
| 8 | |
| 9 | const oldv_source = fullpath(tools_folder, 'oldv.v') |
| 10 | |
| 11 | const vroot = os.real_path(os.dir(os.dir(tools_folder))) |
| 12 | |
| 13 | const vexe = fullpath(vroot, 'v') |
| 14 | |
| 15 | fn fullpath(folder string, fname string) string { |
| 16 | return os.real_path(os.join_path_single(folder, exename(fname))) |
| 17 | } |
| 18 | |
| 19 | fn exename(n string) string { |
| 20 | if n.ends_with('.v') || os.user_os() != 'windows' { |
| 21 | return n |
| 22 | } |
| 23 | return '${n}.exe' |
| 24 | } |
| 25 | |
| 26 | struct Context { |
| 27 | mut: |
| 28 | old_commit string |
| 29 | new_commit string |
| 30 | command string |
| 31 | } |
| 32 | |
| 33 | fn main() { |
| 34 | mut fp := flag.new_flag_parser(os.args) |
| 35 | mut context := Context{} |
| 36 | fp.application(os.file_name(os.executable())) |
| 37 | fp.version('0.0.2') |
| 38 | fp.description('\n Find at what commit a regression occurred. |
| 39 | To find when a regression happened (regression_bug.v should fail on master): |
| 40 | ./v run cmd/tools/regress.v --old a7019ac --command " ./v run /abs/path/to/regression_bug.v" |
| 41 | To find when a feature was implemented (feature.v should succeed on master): |
| 42 | ./v run cmd/tools/regress.v --old a7019ac --command "! ./v run /abs/path/to/feature.v"') |
| 43 | fp.skip_executable() |
| 44 | |
| 45 | context.new_commit = fp.string('new', `n`, 'master', 'The new commit, by default: master.') |
| 46 | context.old_commit = fp.string('old', `o`, '', |
| 47 | 'A known old commit, required (for it, COMMAND should exit with 0).') |
| 48 | context.command = fp.string('command', `c`, '', |
| 49 | 'A command to execute. Should exit with 0 for the *old* commits.') |
| 50 | fp.finalize() or {} |
| 51 | if context.old_commit == '' { |
| 52 | eprintln('--old COMMIT is required') |
| 53 | exit(1) |
| 54 | } |
| 55 | if context.command == '' { |
| 56 | eprintln('--command "COMMAND" is required') |
| 57 | exit(2) |
| 58 | } |
| 59 | if !os.exists(oldvexe) { |
| 60 | if 0 != execute('${os.quoted_path(vexe)} -o ${os.quoted_path(oldvexe)} ${os.quoted_path(oldv_source)}') { |
| 61 | panic('can not compile ${oldvexe}') |
| 62 | } |
| 63 | } |
| 64 | os.execute('git checkout master') |
| 65 | os.execute('git bisect reset') |
| 66 | os.execute('git checkout ${context.new_commit}') |
| 67 | os.execute('git bisect start') |
| 68 | os.execute('git bisect new') |
| 69 | os.execute('git checkout ${context.old_commit}') |
| 70 | os.execute('git bisect old') |
| 71 | println(term.colorize(term.bright_yellow, term.header('', '-'))) |
| 72 | execute('git bisect run ${os.quoted_path(oldvexe)} --bisect -c "${context.command}"') |
| 73 | println(term.colorize(term.bright_yellow, term.header('', '-'))) |
| 74 | os.execute('git bisect reset') |
| 75 | os.execute('git checkout master') |
| 76 | } |
| 77 | |
| 78 | fn execute(cmd string) int { |
| 79 | eprintln('### ${cmd}') |
| 80 | return os.system(cmd) |
| 81 | } |
| 82 | |