import net.urllib import os import readline const vroot = @VMODROOT // get output from `v doctor` fn get_vdoctor_output(is_verbose bool) string { vexe := os.getenv('VEXE') verbose_flag := if is_verbose { '-v' } else { '' } result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} doctor') if result.exit_code != 0 { eprintln('unable to get `v doctor` output: ${result.output}') return '' } return result.output } // get ouput from `v -g -o vdbg cmd/v && vdbg file.v` fn get_v_build_output(is_verbose bool, is_yes bool, file_path string) string { mut vexe := os.getenv('VEXE') // prepare a V compiler with -g to have better backtraces if possible wd := os.getwd() os.chdir(vroot) or {} verbose_flag := if is_verbose { '-v' } else { '' } vdbg_path := $if windows { '${vroot}/vdbg.exe' } $else { '${vroot}/vdbg' } vdbg_compilation_cmd := '${os.quoted_path(vexe)} ${verbose_flag} -g -o ${os.quoted_path(vdbg_path)} cmd/v' vdbg_result := os.execute(vdbg_compilation_cmd) os.chdir(wd) or {} if vdbg_result.exit_code == 0 { vexe = vdbg_path } else { eprintln('unable to compile V in debug mode: ${vdbg_result.output}\ncommand: ${vdbg_compilation_cmd}\n') } // mut result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} ${os.quoted_path(file_path)}') defer { os.rm(vdbg_path) or { if is_verbose { eprintln('unable to delete `vdbg`: ${err}') } } } if result.exit_code == 0 { defer { mut generated_file := file_path.all_before_last('.') $if windows { generated_file += '.exe' } os.rm(generated_file) or { if is_verbose { eprintln('unable to delete generated file: ${err}') } } } run := is_yes || ask('It looks like the compilation went well, do you want to run the file?') if run { result = os.execute('${os.quoted_path(vexe)} ${verbose_flag} run ${os.quoted_path(file_path)}') if result.exit_code == 0 && !is_yes { confirm_or_exit('It looks like the file ran correctly as well, are you sure you want to continue?') } } } return result.output } fn ask(msg string) bool { prompt := os.input_opt('${msg} [Y/n] ') or { 'y' } return prompt == '' || prompt[0].ascii_str().to_lower() != 'n' } fn confirm_or_exit(msg string) { if !ask(msg) { exit(1) } } fn main() { mut file_path := '' mut is_verbose := false mut is_yes := false for arg in os.args[2..] { match arg { '-v' { is_verbose = true } '-y' { is_yes = true } else { if !arg.ends_with('.v') && !arg.ends_with('.vsh') && !arg.ends_with('.vv') { eprintln('unknown argument: `${arg}`') exit(1) } if file_path != '' { eprintln('only one V file can be submitted') exit(1) } file_path = arg } } } if file_path == '' { eprintln('v bug: no v file listed to report') exit(1) } os.unsetenv('VCOLORS') // collect error information // output from `v doctor` vdoctor_output := get_vdoctor_output(is_verbose) // file content file_content := os.read_file(file_path) or { eprintln('unable to get file "${file_path}" content: ${err}') '' } // output from `v -g -o vdbg cmd/v && vdbg file.v` build_output := get_v_build_output(is_verbose, is_yes, file_path) // ask the user if he wants to submit even after an error if !is_yes && (vdoctor_output == '' || file_content == '' || build_output == '') { confirm_or_exit('An error occurred retrieving the information, do you want to continue?') } expected_result := readline.read_line('What did you expect to see? ') or { // Ctrl-C was pressed eprintln('\nCanceled') exit(1) } // open prefilled issue creation page, or print link as a fallback if !is_yes && vdoctor_output.contains('behind V master') { confirm_or_exit('It looks like your installation of V is outdated, we advise you to run `v up` before submitting an issue. Are you sure you want to continue?') } // When updating this template, make sure to update `.github/ISSUE_TEMPLATE/bug_report.md` too raw_body := ' **V doctor:** ``` ${vdoctor_output} ``` **What did you do?** `v -g -o vdbg cmd/v && vdbg ${file_path}` {file_content} **What did you expect to see?** ${expected_result} **What did you see instead?** ``` ${build_output}```' mut encoded_body := urllib.query_escape(raw_body.replace_once('{file_content}', '```v\n${file_content}\n```')) mut generated_uri := 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' if generated_uri.len > 8192 { // GitHub doesn't support URLs longer than 8192 characters encoded_body = urllib.query_escape(raw_body.replace_once('{file_content}', 'See attached file `${file_path}`')) generated_uri = 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' println('Your file is too big to be submitted. Head over to the following URL and attach your file.') println(generated_uri) } else { os.open_uri(generated_uri) or { if is_verbose { eprintln(err) } println(generated_uri) } } }