diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c68319bb0..b1d298f885 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1015,5 +1015,5 @@ jobs: run: git clone --depth 1 https://github.com/vlang/vab - name: Build vab run: cd vab; ../v ./vab.v ; cd .. - - name: Build vab with -prod - run: cd vab; ../v -prod ./vab.v ; cd .. + - name: Build vab with + run: cd vab; ../v ./vab.v ; cd .. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bee0cd6ea..e884c78018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ from local variables. - Support for compile time environment variables via `$env('ENV_VAR')`. - Allow method declaration of `==` and `<` operators and auto generate `!=`, `>`, `<=` and `>=`. - support `dump(expr)`, i.e. tracing of both the location, name and value of an expression +- deprecate os.exec in favour of os.executable() which does *NOT* return an option, when the command was not found ## V 0.2.1 *30 Dec 2020* diff --git a/cmd/tools/fast/fast.v b/cmd/tools/fast/fast.v index 3d061a54ea..9baa19fe74 100644 --- a/cmd/tools/fast/fast.v +++ b/cmd/tools/fast/fast.v @@ -50,7 +50,7 @@ fn main() { date := time.unix(commit_date.int()) mut out := os.create('table.html') ? // Place the new row on top - table = + table = ' $date.format() $commit @@ -81,7 +81,7 @@ fn main() { } fn exec(s string) string { - e := os.exec(s) or { panic(err) } + e := os.execute_or_panic(s) return e.output.trim_right('\r\n') } @@ -111,7 +111,7 @@ fn measure(cmd string, description string) int { } fn measure_steps(vdir string) (int, int, int) { - resp := os.exec('$vdir/vprod -o v.c -show-timings $vdir/cmd/v') or { panic(err) } + resp := os.execute_or_panic('$vdir/vprod -o v.c -show-timings $vdir/cmd/v') lines := resp.output.split_into_lines() if lines.len != 3 { return 0, 0, 0 diff --git a/cmd/tools/fast/fast_job.v b/cmd/tools/fast/fast_job.v index ed72a7431e..01c5a0bb69 100644 --- a/cmd/tools/fast/fast_job.v +++ b/cmd/tools/fast/fast_job.v @@ -17,20 +17,22 @@ fn main() { return } for { - os.exec('git pull --rebase') or { + res_pull := os.execute('git pull --rebase') + if res_pull.exit_code != 0 { println('failed to git pull. uncommitted changes?') return } // println('running fast') - resp := os.exec('./fast') or { - println(err) + resp := os.execute('./fast') + if resp.exit_code < 0 { + println(resp.output) return } if resp.exit_code != 0 { println('resp != 0, skipping') } else { os.chdir('website') - os.exec('git checkout gh-pages') ? + os.execute_or_panic('git checkout gh-pages') os.cp('../index.html', 'index.html') ? os.system('git commit -am "update benchmark"') os.system('git push origin gh-pages') diff --git a/cmd/tools/gen_vc.v b/cmd/tools/gen_vc.v index 82cb8d855b..f924dbd828 100644 --- a/cmd/tools/gen_vc.v +++ b/cmd/tools/gen_vc.v @@ -43,13 +43,13 @@ const ( // version app_version = '0.1.2' // description - app_description = "This tool regenerates V\'s bootstrap .c files every time the V master branch is updated." + app_description = "This tool regenerates V's bootstrap .c files every time the V master branch is updated." // assume something went wrong if file size less than this too_short_file_limit = 5000 // create a .c file for these os's vc_build_oses = [ 'nix', - /* all nix based os */ + // all nix based os 'windows', ] ) @@ -188,8 +188,8 @@ fn parse_flags(mut fp flag.FlagParser) FlagOptions { work_dir: fp.string('work-dir', 0, work_dir, 'gen_vc working directory') purge: fp.bool('purge', 0, false, 'force purge the local repositories') port: fp.int('port', 0, server_port, 'port for web server to listen on') - log_to: fp.string('log-to', 0, log_to, "log to is \'file\' or \'terminal\'") - log_file: fp.string('log-file', 0, log_file, "log file to use when log-to is \'file\'") + log_to: fp.string('log-to', 0, log_to, "log to is 'file' or 'terminal'") + log_file: fp.string('log-file', 0, log_file, "log file to use when log-to is 'file'") dry_run: fp.bool('dry-run', 0, dry_run, 'when specified dont push anything to remote repo') force: fp.bool('force', 0, false, 'force update even if already up to date') } @@ -318,9 +318,10 @@ fn (mut gen_vc GenVC) command_execute(cmd string, dry bool) string { return gen_vc.command_execute_dry(cmd) } gen_vc.logger.info('cmd: $cmd') - r := os.exec(cmd) or { + r := os.execute(cmd) + if r.exit_code < 0 { gen_vc.logger.error('$err_msg_cmd_x: "$cmd" could not start.') - gen_vc.logger.error(err.msg) + gen_vc.logger.error(r.output) // something went wrong, better start fresh next time gen_vc.purge_repos() gen_vc.gen_error = true diff --git a/cmd/tools/modules/scripting/scripting.v b/cmd/tools/modules/scripting/scripting.v index 19d7c0ae36..f9589118f7 100644 --- a/cmd/tools/modules/scripting/scripting.v +++ b/cmd/tools/modules/scripting/scripting.v @@ -60,19 +60,23 @@ pub fn rmrf(path string) { } } +// execute a command, and return a result, or an error, if it failed in any way. pub fn exec(cmd string) ?os.Result { verbose_trace(@FN, cmd) - x := os.exec(cmd) or { + x := os.execute(cmd) + if x.exit_code != 0 { verbose_trace(@FN, '## failed.') - return err + return error(x.output) } verbose_trace_exec_result(x) return x } +// run a command, tracing its results, and returning ONLY its output pub fn run(cmd string) string { verbose_trace(@FN, cmd) - x := os.exec(cmd) or { + x := os.execute(cmd) + if x.exit_code < 0 { verbose_trace(@FN, '## failed.') return '' } @@ -85,7 +89,8 @@ pub fn run(cmd string) string { pub fn exit_0_status(cmd string) bool { verbose_trace(@FN, cmd) - x := os.exec(cmd) or { + x := os.execute(cmd) + if x.exit_code < 0 { verbose_trace(@FN, '## failed.') return false } diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 3cf4e846bf..70fdeb6e0d 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -287,7 +287,8 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr { if testing.show_start { ts.append_message(.info, ' starting $relative_file ...') } - r := os.exec(cmd) or { + r := os.execute(cmd) + if r.exit_code < 0 { ts.failed = true ts.benchmark.fail() tls_bench.fail() @@ -387,7 +388,10 @@ pub fn v_build_failing_skipped(zargs string, folder string, oskipped []string) b } pub fn build_v_cmd_failed(cmd string) bool { - res := os.exec(cmd) or { return true } + res := os.execute(cmd) + if res.exit_code < 0 { + return true + } if res.exit_code != 0 { eprintln('') eprintln(res.output) diff --git a/cmd/tools/oldv.v b/cmd/tools/oldv.v index afdbb8f121..d9f99733bb 100644 --- a/cmd/tools/oldv.v +++ b/cmd/tools/oldv.v @@ -29,10 +29,10 @@ const ( struct Context { mut: - vgo vgit.VGitOptions - commit_v string = 'master' + vgo vgit.VGitOptions + commit_v string = 'master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too) - commit_vc string = 'master' + commit_vc string = 'master' // this will be derived from commit_v commit_v_hash string // this will be filled from the commit-ish commit_v using rev-list. It IS a commit hash. path_v string // the full path to the v folder inside workdir. @@ -40,7 +40,7 @@ mut: cmd_to_run string // the command that you want to run *in* the oldv repo cc string = 'cc' // the C compiler to use for bootstrapping. - cleanup bool // should the tool run a cleanup first + cleanup bool // should the tool run a cleanup first } fn (mut c Context) compile_oldv_if_needed() { @@ -100,9 +100,7 @@ fn main() { scripting.cprintln('# v commit hash: $context.commit_v_hash') scripting.cprintln('# checkout folder: $context.path_v') if context.cmd_to_run.len > 0 { - cmdres := os.exec(context.cmd_to_run) or { - panic(err) - } + cmdres := os.execute_or_panic(context.cmd_to_run) scripting.cprintln('# command: ${context.cmd_to_run:-34s} exit code: ${cmdres.exit_code:-4d} result:') println(cmdres.output) exit(cmdres.exit_code) diff --git a/cmd/tools/repeat.v b/cmd/tools/repeat.v index 3553a9e82d..c5a19e9c98 100644 --- a/cmd/tools/repeat.v +++ b/cmd/tools/repeat.v @@ -42,7 +42,7 @@ mut: } struct Aints { - values []int + values []int mut: imin int imax int @@ -206,7 +206,10 @@ fn (mut context Context) run() { for i in 1 .. context.warmup + 1 { print('${context.cgoback}warming up run: ${i:4}/${context.warmup:-4} for ${cmd:-50s} took ${duration:6} ms ...') mut sw := time.new_stopwatch({}) - os.exec(cmd) or { continue } + res := os.execute(cmd) + if res.exit_code != 0 { + continue + } duration = int(sw.elapsed().milliseconds()) } run_warmups++ @@ -225,8 +228,8 @@ fn (mut context Context) run() { eprintln('${i:10} non 0 exit code for cmd: $cmd') continue } - context.results[icmd].outputs << - res.output.trim_right('\r\n').replace('\r\n', '\n').split('\n') + context.results[icmd].outputs << res.output.trim_right('\r\n').replace('\r\n', + '\n').split('\n') context.results[icmd].timings << duration sum += duration runs++ diff --git a/cmd/tools/test_if_v_test_system_works.v b/cmd/tools/test_if_v_test_system_works.v index 11596cee27..a86abd8b99 100644 --- a/cmd/tools/test_if_v_test_system_works.v +++ b/cmd/tools/test_if_v_test_system_works.v @@ -55,7 +55,7 @@ fn main() { fn check_ok(cmd string) string { println('> check_ok cmd: $cmd') - res := os.exec(cmd) or { panic(err) } + res := os.execute(cmd) if res.exit_code != 0 { eprintln('> check_ok failed.\n$res.output') exit(1) @@ -65,7 +65,7 @@ fn check_ok(cmd string) string { fn check_fail(cmd string) string { println('> check_fail cmd: $cmd') - res := os.exec(cmd) or { panic(err) } + res := os.execute(cmd) if res.exit_code == 0 { eprintln('> check_fail succeeded, but it should have failed.\n$res.output') exit(1) diff --git a/cmd/tools/vcheck-md.v b/cmd/tools/vcheck-md.v index 59698486a0..2b30efd22b 100644 --- a/cmd/tools/vcheck-md.v +++ b/cmd/tools/vcheck-md.v @@ -211,7 +211,10 @@ fn (mut f MDFile) debug() { } fn cmdexecute(cmd string) int { - res := os.exec(cmd) or { return 1 } + res := os.execute(cmd) + if res.exit_code < 0 { + return 1 + } if res.exit_code != 0 { eprint(res.output) } @@ -219,7 +222,7 @@ fn cmdexecute(cmd string) int { } fn silent_cmdexecute(cmd string) int { - res := os.exec(cmd) or { return 1 } + res := os.execute(cmd) return res.exit_code } diff --git a/cmd/tools/vcreate.v b/cmd/tools/vcreate.v index e6a069adde..ec3cc155b4 100644 --- a/cmd/tools/vcreate.v +++ b/cmd/tools/vcreate.v @@ -81,7 +81,8 @@ fn (c &Create) write_main(new bool) { fn (c &Create) create_git_repo(dir string) { // Create Git Repo and .gitignore file if !os.is_dir('$dir/.git') { - os.exec('git init $dir') or { + res := os.execute('git init $dir') + if res.exit_code != 0 { cerror('Unable to create git repo') exit(4) } diff --git a/cmd/tools/vdoctor.v b/cmd/tools/vdoctor.v index 644f2a8fba..6effed5873 100644 --- a/cmd/tools/vdoctor.v +++ b/cmd/tools/vdoctor.v @@ -30,9 +30,9 @@ fn (mut a App) collect_info() { arch_details << 'little endian' } if os_kind == 'macos' { - arch_details << a.cmd({ + arch_details << a.cmd( command: 'sysctl -n machdep.cpu.brand_string' - }) + ) } if os_kind == 'linux' { mut cpu_details := '' @@ -48,16 +48,16 @@ fn (mut a App) collect_info() { arch_details << cpu_details } if os_kind == 'windows' { - arch_details << a.cmd({ + arch_details << a.cmd( command: 'wmic cpu get name /format:table' line: 1 - }) + ) } // mut os_details := '' - wsl_check := a.cmd({ + wsl_check := a.cmd( command: 'cat /proc/sys/kernel/osrelease' - }) + ) if os_kind == 'linux' { os_details = a.get_linux_os_name() if 'hypervisor' in a.cpu_info('flags') { @@ -75,26 +75,27 @@ fn (mut a App) collect_info() { os_details += ' (WSL)' } // From https://unix.stackexchange.com/a/14346 - if a.cmd(command: '[ "$(awk \'\$5=="/" {print \$1}\' 0 { return a.cached_cpuinfo[key] } - info := os.exec('cat /proc/cpuinfo') or { - return a.cached_cpuinfo[key] + info := os.execute('cat /proc/cpuinfo') + if info.exit_code != 0 { + return '`cat /proc/cpuinfo` could not run' } a.cached_cpuinfo = a.parse(info.output, ':') return a.cached_cpuinfo[key] } fn (mut a App) git_info() string { - mut out := a.cmd({ + mut out := a.cmd( command: 'git -C . describe --abbrev=8 --dirty --always --tags' - }).trim_space() - os.exec('git -C . remote add V_REPO https://github.com/vlang/v') or { } // ignore failure (i.e. remote exists) - os.exec('git -C . fetch V_REPO') or { } - commit_count := a.cmd({ + ).trim_space() + os.execute('git -C . remote add V_REPO https://github.com/vlang/v') // ignore failure (i.e. remote exists) + os.execute('git -C . fetch V_REPO') + commit_count := a.cmd( command: 'git rev-list @{0}...V_REPO/master --right-only --count' - }).int() + ).int() if commit_count > 0 { out += ' ($commit_count commit(s) behind V master)' } @@ -262,12 +263,12 @@ fn (mut a App) report_tcc_version(tccfolder string) { a.line(tccfolder, 'N/A') return } - tcc_branch_name := a.cmd({ + tcc_branch_name := a.cmd( command: 'git -C $tccfolder rev-parse --abbrev-ref HEAD' - }) - tcc_commit := a.cmd({ + ) + tcc_commit := a.cmd( command: 'git -C $tccfolder describe --abbrev=8 --dirty --always --tags' - }) + ) a.line('$tccfolder status', '$tcc_branch_name $tcc_commit') } @@ -278,9 +279,7 @@ fn (mut a App) report_info() { } fn is_writable_dir(path string) bool { - res := os.is_writable_folder(path) or { - false - } + res := os.is_writable_folder(path) or { false } return res } diff --git a/cmd/tools/vfmt.v b/cmd/tools/vfmt.v index 01b06c5047..1d10e5ea29 100644 --- a/cmd/tools/vfmt.v +++ b/cmd/tools/vfmt.v @@ -117,7 +117,8 @@ fn main() { if foptions.is_verbose { eprintln('vfmt worker_cmd: $worker_cmd') } - worker_result := os.exec(worker_cmd) or { + worker_result := os.execute(worker_cmd) + if worker_result.exit_code != 0 { errors++ continue } @@ -277,7 +278,7 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path } fn (f FormatOptions) str() string { - return + return 'FormatOptions{ is_l: $f.is_l, is_w: $f.is_w, is_diff: $f.is_diff, is_verbose: $f.is_verbose,' + ' is_all: $f.is_all, is_worker: $f.is_worker, is_debug: $f.is_debug, is_noerror: $f.is_noerror,' + ' is_verify: $f.is_verify" }' diff --git a/cmd/tools/vpm.v b/cmd/tools/vpm.v index f196e52d5d..27510bde11 100644 --- a/cmd/tools/vpm.v +++ b/cmd/tools/vpm.v @@ -193,13 +193,7 @@ fn vpm_install(module_names []string) { vcs_install_cmd := supported_vcs_install_cmds[vcs] cmd := '$vcs_install_cmd "$mod.url" "$final_module_path"' verbose_println(' command: $cmd') - cmdres := os.exec(cmd) or { - errors++ - println('Could not install module "$name" to "$final_module_path" .') - verbose_println('Error command: $cmd') - verbose_println('Error details: $err') - continue - } + cmdres := os.execute(cmd) if cmdres.exit_code != 0 { errors++ println('Failed installing module "$name" to "$final_module_path" .') @@ -232,13 +226,7 @@ fn vpm_update(m []string) { vcs := vcs_used_in_dir(final_module_path) or { continue } vcs_cmd := supported_vcs_update_cmds[vcs[0]] verbose_println(' command: $vcs_cmd') - vcs_res := os.exec('$vcs_cmd') or { - errors++ - println('Could not update module "$name".') - verbose_println('Error command: $vcs_cmd') - verbose_println('Error details:\n$err') - continue - } + vcs_res := os.execute('$vcs_cmd') if vcs_res.exit_code != 0 { errors++ println('Failed updating module "$name".') @@ -265,9 +253,10 @@ fn get_outdated() ?[]string { vcs_cmd_steps := supported_vcs_outdated_steps[vcs[0]] mut outputs := []string{} for step in vcs_cmd_steps { - res := os.exec(step) or { + res := os.execute(step) + if res.exit_code < 0 { verbose_println('Error command: $step') - verbose_println('Error details:\n$err') + verbose_println('Error details:\n$res.output') return error('Error while checking latest commits for "$name".') } if vcs[0] == 'hg' { diff --git a/cmd/tools/vrepl.v b/cmd/tools/vrepl.v index 0c8754f9aa..bad89e66aa 100644 --- a/cmd/tools/vrepl.v +++ b/cmd/tools/vrepl.v @@ -381,9 +381,10 @@ fn repl_run_vfile(file string) ?os.Result { $if trace_repl_temp_files ? { eprintln('>> repl_run_vfile file: $file') } - s := os.exec('"$vexe" -repl run "$file"') or { - rerror(err.msg) - return err + s := os.execute('"$vexe" -repl run "$file"') + if s.exit_code < 0 { + rerror(s.output) + return error(s.output) } return s } diff --git a/cmd/tools/vself.v b/cmd/tools/vself.v index 9bf7269332..a21de12c95 100644 --- a/cmd/tools/vself.v +++ b/cmd/tools/vself.v @@ -32,7 +32,7 @@ fn main() { } fn compile(vroot string, cmd string) { - result := os.exec(cmd) or { panic(err) } + result := os.execute_or_panic(cmd) if result.exit_code != 0 { eprintln('cannot compile to `$vroot`: \n$result.output') exit(1) diff --git a/cmd/tools/vsetup-freetype.v b/cmd/tools/vsetup-freetype.v index 0d4b33f14e..c17ee6746a 100644 --- a/cmd/tools/vsetup-freetype.v +++ b/cmd/tools/vsetup-freetype.v @@ -3,16 +3,21 @@ module main import os import v.pref +const freetype_repo_url = 'https://github.com/ubawurinna/freetype-windows-binaries' + +const freetype_folder = os.join_path('thirdparty', 'freetype') + fn main() { $if windows { println('Setup freetype...') vroot := os.dir(pref.vexe_path()) os.chdir(vroot) - if os.is_dir('./thirdparty/freetype') { + if os.is_dir(freetype_folder) { println('Thirdparty "freetype" is already installed.') } else { - s := os.exec('git clone --depth=1 https://github.com/ubawurinna/freetype-windows-binaries ./thirdparty/freetype/') or { - panic(err) + s := os.execute('git clone --depth=1 $freetype_repo_url $freetype_folder') + if s.exit_code != 0 { + panic(s.output) } println(s.output) println('Thirdparty "freetype" installed successfully.') diff --git a/cmd/tools/vsymlink.v b/cmd/tools/vsymlink.v index 881da93d57..3c058c152d 100644 --- a/cmd/tools/vsymlink.v +++ b/cmd/tools/vsymlink.v @@ -31,7 +31,7 @@ fn setup_symlink_unix(vexe string) { } link_path = link_dir + '/v' } - ret := os.exec('ln -sf $vexe $link_path') or { panic(err) } + ret := os.execute_or_panic('ln -sf $vexe $link_path') if ret.exit_code == 0 { println('Symlink "$link_path" has been created') } else { diff --git a/cmd/tools/vtest-parser.v b/cmd/tools/vtest-parser.v index d3a21671cb..c6c7b2b556 100644 --- a/cmd/tools/vtest-parser.v +++ b/cmd/tools/vtest-parser.v @@ -13,11 +13,10 @@ const ( support_color = term.can_show_color_on_stderr() && term.can_show_color_on_stdout() ecode_timeout = 101 ecode_memout = 102 - ecode_exec = 103 ecode_details = map{ - '101': 'too slow' - '102': 'too memory hungry' - '103': 'worker executable not found' + -1: 'worker executable not found' + 101: 'too slow' + 102: 'too memory hungry' } ) @@ -217,10 +216,7 @@ fn (mut context Context) process_whole_file_in_worker(path string) (int, int) { context.cut_index = i // needed for the progress bar cmd := '"$context.myself" $verbosity --worker --timeout_ms ${context.timeout_ms:5} --cut_index ${i:5} --path "$path" ' context.log(cmd) - res := os.exec(cmd) or { os.Result{ - output: err.msg - exit_code: ecode_exec - } } + mut res := os.execute(cmd) context.log('worker exit_code: $res.exit_code | worker output:\n$res.output') if res.exit_code != 0 { fails++ @@ -236,7 +232,7 @@ fn (mut context Context) process_whole_file_in_worker(path string) (int, int) { err := if is_panic { red('parser failure: panic') } else { - red('parser failure: crash, ${ecode_details[res.exit_code.str()]}') + red('parser failure: crash, ${ecode_details[res.exit_code]}') } path_to_line := bold('$path:$line:$col:') err_line := last_line.trim_left('\t') diff --git a/cmd/tools/vup.v b/cmd/tools/vup.v index 7ff83b8f69..d019c50e59 100644 --- a/cmd/tools/vup.v +++ b/cmd/tools/vup.v @@ -41,7 +41,7 @@ fn main() { app.backup('cmd/tools/vup.exe') } app.recompile_v() - os.exec('"$app.vexe" cmd/tools/vup.v') or { panic(err) } + os.execute_or_panic('"$app.vexe" cmd/tools/vup.v') app.show_current_v_version() } @@ -71,14 +71,13 @@ fn (app App) recompile_v() { opts := if app.is_prod { '-prod' } else { '' } vself := '"$app.vexe" $opts self' app.vprintln('> recompiling v itself with `$vself` ...') - if self_result := os.exec(vself) { - if self_result.exit_code == 0 { - println(self_result.output.trim_space()) - return - } else { - app.vprintln('`$vself` failed, running `make`...') - app.vprintln(self_result.output.trim_space()) - } + self_result := os.execute(vself) + if self_result.exit_code == 0 { + println(self_result.output.trim_space()) + return + } else { + app.vprintln('`$vself` failed, running `make`...') + app.vprintln(self_result.output.trim_space()) } app.make(vself) } @@ -88,19 +87,19 @@ fn (app App) make(vself string) { $if windows { make = 'make.bat' } - make_result := os.exec(make) or { panic(err) } + make_result := os.execute_or_panic(make) app.vprintln(make_result.output) } fn (app App) show_current_v_version() { - if vout := os.exec('"$app.vexe" version') { + vout := os.execute('"$app.vexe" version') + if vout.exit_code >= 0 { mut vversion := vout.output.trim_space() if vout.exit_code == 0 { latest_v_commit := vversion.split(' ').last().all_after('.') - if latest_v_commit_time := os.exec('git show -s --format=%ci $latest_v_commit') { - if latest_v_commit_time.exit_code == 0 { - vversion += ', timestamp: ' + latest_v_commit_time.output.trim_space() - } + latest_v_commit_time := os.execute('git show -s --format=%ci $latest_v_commit') + if latest_v_commit_time.exit_code == 0 { + vversion += ', timestamp: ' + latest_v_commit_time.output.trim_space() } } println('Current V version:') @@ -118,10 +117,11 @@ fn (app App) backup(file string) { fn (app App) git_command(command string) { app.vprintln('git_command: git $command') - git_result := os.exec('git $command') or { + git_result := os.execute('git $command') + if git_result.exit_code < 0 { app.get_git() // Try it again with (maybe) git installed - os.exec('git $command') or { panic(err) } + os.execute_or_panic('git $command') } if git_result.exit_code != 0 { eprintln(git_result.output) @@ -134,13 +134,15 @@ fn (app App) get_git() { $if windows { println('Downloading git 32 bit for Windows, please wait.') // We'll use 32 bit because maybe someone out there is using 32-bit windows - os.exec('bitsadmin.exe /transfer "vgit" https://github.com/git-for-windows/git/releases/download/v2.30.0.windows.2/Git-2.30.0.2-32-bit.exe "$os.getwd()/git32.exe"') or { + res_download := os.execute('bitsadmin.exe /transfer "vgit" https://github.com/git-for-windows/git/releases/download/v2.30.0.windows.2/Git-2.30.0.2-32-bit.exe "$os.getwd()/git32.exe"') + if res_download.exit_code != 0 { eprintln('Unable to install git automatically: please install git manually') - panic(err) + panic(res_download.output) } - os.exec('$os.getwd()/git32.exe') or { + res_git32 := os.execute('$os.getwd()/git32.exe') + if res_git32.exit_code != 0 { eprintln('Unable to install git automatically: please install git manually') - panic(err) + panic(res_git32.output) } } $else { // Probably some kind of *nix, usually need to get using a package manager. eprintln("error: Install `git` using your system's package manager") diff --git a/cmd/tools/vvet/vet_test.v b/cmd/tools/vvet/vet_test.v index 6209f9168c..fd62ce93e6 100644 --- a/cmd/tools/vvet/vet_test.v +++ b/cmd/tools/vvet/vet_test.v @@ -34,7 +34,10 @@ fn check_path(vexe string, dir string, tests []string) int { program := path print(path + ' ') // -force is needed so that `v vet` would not skip the regression files - res := os.exec('$vexe vet -force $program') or { panic(err) } + res := os.execute('$vexe vet -force $program') + if res.exit_code < 0 { + panic(res.output) + } mut expected := os.read_file(program.replace('.vv', '') + '.out') or { panic(err) } expected = clean_line_endings(expected) found := clean_line_endings(res.output) diff --git a/cmd/v/help/help_test.v b/cmd/v/help/help_test.v index 78cf6d6e4b..ac395b6577 100644 --- a/cmd/v/help/help_test.v +++ b/cmd/v/help/help_test.v @@ -2,21 +2,21 @@ import os fn test_help() { vexe := os.getenv('VEXE') - res := os.exec('"$vexe" help') or { panic(err) } + res := os.execute('"$vexe" help') assert res.exit_code == 0 assert res.output.starts_with('V is a tool for managing V source code.') } fn test_help_as_short_option() { vexe := os.getenv('VEXE') - res := os.exec('"$vexe" -h') or { panic(err) } + res := os.execute('"$vexe" -h') assert res.exit_code == 0 assert res.output.starts_with('V is a tool for managing V source code.') } fn test_help_as_long_option() { vexe := os.getenv('VEXE') - res := os.exec('"$vexe" --help') or { panic(err) } + res := os.execute('"$vexe" --help') assert res.exit_code == 0 assert res.output.starts_with('V is a tool for managing V source code.') } diff --git a/examples/dynamic_library_loading/use_test.v b/examples/dynamic_library_loading/use_test.v index 5e36b05be7..e468cc1d28 100644 --- a/examples/dynamic_library_loading/use_test.v +++ b/examples/dynamic_library_loading/use_test.v @@ -40,13 +40,13 @@ fn test_can_compile_main_program() { fn v_compile(vopts string) os.Result { cmd := '"$vexe" -showcc $vopts' dump(cmd) - res := os.exec(cmd) or { panic(err) } + res := os.execute_or_panic(cmd) dump(res) // assert res.exit_code == 0 - $if !windows { - os.system('ls -al $cfolder') - } $else { + $if windows { os.system('dir $cfolder /a') + } $else { + os.system('ls -al $cfolder') } return res } diff --git a/vlib/builtin/bare/syscallwrapper_test.v b/vlib/builtin/bare/syscallwrapper_test.v index b293978c8e..0f80b05f2f 100644 --- a/vlib/builtin/bare/syscallwrapper_test.v +++ b/vlib/builtin/bare/syscallwrapper_test.v @@ -1,22 +1,24 @@ import os fn test_syscallwrappers() { - if true { return } + if true { + return + } $if linux { $if x64 { exe := os.executable() vdir := os.dir(exe) if vdir.len > 1 { - dot_checks := vdir + "/.checks" + dot_checks := vdir + '/.checks' assert os.is_dir(dot_checks) os.chdir(dot_checks) - checks_v := "checks.v" + checks_v := 'checks.v' assert os.exists(checks_v) - rc := os.exec("v run $checks_v") or { panic(err) } - assert !rc.output.contains("V panic: An assertion failed.") - assert !rc.output.contains("failed") + rc := os.execute_or_panic('v run $checks_v') assert rc.exit_code == 0 + assert !rc.output.contains('V panic: An assertion failed.') + assert !rc.output.contains('failed') } else { panic("Can't find test directory") } diff --git a/vlib/gg/text_rendering.v b/vlib/gg/text_rendering.v index d3678e9a0f..2ee791d7a3 100644 --- a/vlib/gg/text_rendering.v +++ b/vlib/gg/text_rendering.v @@ -107,8 +107,11 @@ fn new_ft(c FTConfig) ?&FT { return none } } - bold_path := if c.custom_bold_font_path != '' { c.custom_bold_font_path } else { get_font_path_variant(c.font_path, - .bold) } + bold_path := if c.custom_bold_font_path != '' { + c.custom_bold_font_path + } else { + get_font_path_variant(c.font_path, .bold) + } bytes_bold := os.read_bytes(bold_path) or { debug_font_println('failed to load font "$bold_path"') bytes @@ -290,7 +293,10 @@ pub fn system_font_path() string { } } } - s := os.exec('fc-list') or { panic('failed to fetch system fonts') } + s := os.execute('fc-list') + if s.exit_code != 0 { + panic('failed to fetch system fonts') + } system_fonts := s.output.split('\n') for line in system_fonts { for font in fonts { diff --git a/vlib/os/os.v b/vlib/os/os.v index b2011fe351..a06b61caa0 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -596,3 +596,22 @@ pub mut: version string machine string } + +[deprecated: 'use os.execute or os.execute_or_panic instead'] +pub fn exec(cmd string) ?Result { + res := execute(cmd) + if res.exit_code < 0 { + return error_with_code(res.output, -1) + } + return res +} + +pub fn execute_or_panic(cmd string) Result { + res := execute(cmd) + if res.exit_code != 0 { + eprintln('failed cmd: $cmd') + eprintln('failed code: $res.exit_code') + panic(res.output) + } + return res +} diff --git a/vlib/os/os_nix.c.v b/vlib/os/os_nix.c.v index 368113adc6..b99f5f348b 100644 --- a/vlib/os/os_nix.c.v +++ b/vlib/os/os_nix.c.v @@ -156,15 +156,18 @@ pub fn mkdir(path string) ?bool { return true } -// exec starts the specified command, waits for it to complete, and returns its output. -pub fn exec(cmd string) ?Result { +// execute starts the specified command, waits for it to complete, and returns its output. +pub fn execute(cmd string) Result { // if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') { - // return error(';, &&, || and \\n are not allowed in shell commands') + // return Result{ exit_code: -1, output: ';, &&, || and \\n are not allowed in shell commands' } // } pcmd := '$cmd 2>&1' f := vpopen(pcmd) if isnil(f) { - return error('exec("$cmd") failed') + return Result{ + exit_code: -1 + output: 'exec("$cmd") failed' + } } buf := [4096]byte{} mut res := strings.new_builder(1024) @@ -177,9 +180,6 @@ pub fn exec(cmd string) ?Result { soutput := res.str() // res.free() exit_code := vpclose(f) - if exit_code == 127 { - return error_with_code(soutput, 127) - } return Result{ exit_code: exit_code output: soutput diff --git a/vlib/os/os_windows.c.v b/vlib/os/os_windows.c.v index b9945d8110..88bbd550b7 100644 --- a/vlib/os/os_windows.c.v +++ b/vlib/os/os_windows.c.v @@ -221,10 +221,13 @@ pub fn get_error_msg(code int) string { return unsafe { string_from_wide(ptr_text) } } -// exec starts the specified command, waits for it to complete, and returns its output. -pub fn exec(cmd string) ?Result { +// execute starts the specified command, waits for it to complete, and returns its output. +pub fn execute(cmd string) Result { if cmd.contains(';') || cmd.contains('&&') || cmd.contains('||') || cmd.contains('\n') { - return error(';, &&, || and \\n are not allowed in shell commands') + return Result{ + exit_code: -1 + output: ';, &&, || and \\n are not allowed in shell commands' + } } mut child_stdin := &u32(0) mut child_stdout_read := &u32(0) @@ -237,14 +240,20 @@ pub fn exec(cmd string) ?Result { if !create_pipe_ok { error_num := int(C.GetLastError()) error_msg := get_error_msg(error_num) - return error_with_code('exec failed (CreatePipe): $error_msg', error_num) + return Result{ + exit_code: error_num + output: 'exec failed (CreatePipe): $error_msg' + } } set_handle_info_ok := C.SetHandleInformation(child_stdout_read, C.HANDLE_FLAG_INHERIT, 0) if !set_handle_info_ok { error_num := int(C.GetLastError()) error_msg := get_error_msg(error_num) - return error_with_code('exec failed (SetHandleInformation): $error_msg', error_num) + return Result{ + exit_code: error_num + output: 'exec failed (SetHandleInformation): $error_msg' + } } proc_info := ProcessInformation{} start_info := StartupInfo{ @@ -264,8 +273,10 @@ pub fn exec(cmd string) ?Result { if !create_process_ok { error_num := int(C.GetLastError()) error_msg := get_error_msg(error_num) - return error_with_code('exec failed (CreateProcess) with code $error_num: $error_msg cmd: $cmd', - error_num) + return Result{ + exit_code: error_num + output: 'exec failed (CreateProcess) with code $error_num: $error_msg cmd: $cmd' + } } C.CloseHandle(child_stdin) C.CloseHandle(child_stdout_write) diff --git a/vlib/term/term_nix.c.v b/vlib/term/term_nix.c.v index 6dab16ae4c..ce96ca15c5 100644 --- a/vlib/term/term_nix.c.v +++ b/vlib/term/term_nix.c.v @@ -35,8 +35,9 @@ pub fn get_cursor_position() Coord { } // TODO: use termios.h, C.tcgetattr & C.tcsetattr directly, // instead of using `stty` - oldsettings := os.exec('stty -g') or { - os.Result{} + mut oldsettings := os.execute('stty -g') + if oldsettings.exit_code < 0 { + oldsettings = os.Result{} } os.system('stty -echo -icanon time 0') print('\033[6n') @@ -91,7 +92,9 @@ pub fn set_terminal_title(title string) bool { if is_atty(1) <= 0 || os.getenv('TERM') == 'dumb' { return true } - print('\033]0;${title}\007') + print('\033]0') + print(title) + print('\007') return true } diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index cde45d1a00..771b33363b 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -47,7 +47,8 @@ fn (mut v Builder) find_win_cc() ? { $if !windows { return none } - os.exec('$v.pref.ccompiler -v') or { + ccompiler_version_res := os.execute('$v.pref.ccompiler -v') + if ccompiler_version_res.exit_code != 0 { if v.pref.is_verbose { println('$v.pref.ccompiler not found, looking for msvc...') } @@ -57,7 +58,8 @@ fn (mut v Builder) find_win_cc() ? { } vpath := os.dir(pref.vexe_path()) thirdparty_tcc := os.join_path(vpath, 'thirdparty', 'tcc', 'tcc.exe') - os.exec('$thirdparty_tcc -v') or { + tcc_version_res := os.execute('$thirdparty_tcc -v') + if tcc_version_res.exit_code != 0 { if v.pref.is_verbose { println('tcc not found') } @@ -209,15 +211,14 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) { ccoptions.guessed_compiler = v.pref.ccompiler if ccoptions.guessed_compiler == 'cc' && v.pref.is_prod { // deliberately guessing only for -prod builds for performance reasons - if ccversion := os.exec('cc --version') { - if ccversion.exit_code == 0 { - if ccversion.output.contains('This is free software;') - && ccversion.output.contains('Free Software Foundation, Inc.') { - ccoptions.guessed_compiler = 'gcc' - } - if ccversion.output.contains('clang version ') { - ccoptions.guessed_compiler = 'clang' - } + ccversion := os.execute('cc --version') + if ccversion.exit_code == 0 { + if ccversion.output.contains('This is free software;') + && ccversion.output.contains('Free Software Foundation, Inc.') { + ccoptions.guessed_compiler = 'gcc' + } + if ccversion.output.contains('clang version ') { + ccoptions.guessed_compiler = 'clang' } } } @@ -528,9 +529,7 @@ fn (mut v Builder) cc() { mut ccompiler := v.pref.ccompiler if v.pref.os == .ios { ios_sdk := if v.pref.is_ios_simulator { 'iphonesimulator' } else { 'iphoneos' } - ios_sdk_path_res := os.exec('xcrun --sdk $ios_sdk --show-sdk-path') or { - panic("Couldn't find iphonesimulator") - } + ios_sdk_path_res := os.execute_or_panic('xcrun --sdk $ios_sdk --show-sdk-path') mut isysroot := ios_sdk_path_res.output.replace('\n', '') ccompiler = 'xcrun --sdk iphoneos clang -isysroot $isysroot' } @@ -635,12 +634,7 @@ fn (mut v Builder) cc() { // Run ccompiler_label := 'C ${os.file_name(ccompiler):3}' util.timing_start(ccompiler_label) - res := os.exec(cmd) or { - os.Result{ - exit_code: 111 - output: 'C compilation failed.\n$err.msg' - } - } + res := os.execute(cmd) util.timing_measure(ccompiler_label) if v.pref.show_c_output { v.show_c_compiler_output(res) @@ -694,28 +688,6 @@ fn (mut v Builder) cc() { } break } - // Link it if we are cross compiling and need an executable - /* - if v.os == .linux && !linux_host && v.pref.build_mode != .build { - v.out_name = v.out_name.replace('.o', '') - obj_file := v.out_name + '.o' - println('linux obj_file=$obj_file out_name=$v.out_name') - ress := os.exec('/usr/local/Cellar/llvm/8.0.0/bin/ld.lld --sysroot=$sysroot ' + - '-v -o $v.out_name ' + - '-m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 ' + - '/usr/lib/x86_64-linux-gnu/crt1.o ' + - '$sysroot/lib/x86_64-linux-gnu/libm-2.28.a ' + - '/usr/lib/x86_64-linux-gnu/crti.o ' + - obj_file + - ' /usr/lib/x86_64-linux-gnu/libc.so ' + - '/usr/lib/x86_64-linux-gnu/crtn.o') or { - verror(err.msg) - return - } - println(ress.output) - println('linux cross compilation done. resulting binary: "$v.out_name"') - } - */ if v.pref.compress { $if windows { println('-compress does not work on Windows for now') @@ -794,12 +766,7 @@ fn (mut b Builder) cc_linux_cross() { if b.pref.show_cc { println(cc_cmd) } - cc_res := os.exec(cc_cmd) or { - os.Result{ - exit_code: 1 - output: 'no `cc` command found' - } - } + cc_res := os.execute(cc_cmd) if cc_res.exit_code != 0 { println('Cross compilation for Linux failed (first step, cc). Make sure you have clang installed.') verror(cc_res.output) @@ -817,14 +784,11 @@ fn (mut b Builder) cc_linux_cross() { if b.pref.show_cc { println(linker_cmd) } - res := os.exec(linker_cmd) or { - println('Cross compilation for Linux failed (second step, lld).') - verror(err.msg) - return - } + res := os.execute(linker_cmd) if res.exit_code != 0 { println('Cross compilation for Linux failed (second step, lld).') verror(res.output) + return } println(b.pref.out_name + ' has been successfully compiled') } @@ -982,11 +946,7 @@ fn (mut v Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CF $if trace_thirdparty_obj_files ? { println('>>> build_thirdparty_obj_files cmd: $cmd') } - res := os.exec(cmd) or { - eprintln('exec failed for thirdparty object build cmd:\n$cmd') - verror(err.msg) - return - } + res := os.execute(cmd) os.chdir(current_folder) if res.exit_code != 0 { eprintln('failed thirdparty object build cmd:\n$cmd') diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index dd33228f0a..ea51093a7b 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -93,12 +93,12 @@ fn (mut b Builder) run_compiled_executable_and_exit() { } if b.pref.os == .ios { device := '"iPhone SE (2nd generation)"' - os.exec('xcrun simctl boot $device') or { panic(err) } + os.execute_or_panic('xcrun simctl boot $device') bundle_name := b.pref.out_name.split('/').last() display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name } - os.exec('xcrun simctl install $device ${display_name}.app') or { panic(err) } + os.execute_or_panic('xcrun simctl install $device ${display_name}.app') bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' } - os.exec('xcrun simctl launch $device $bundle_id') or { panic(err) } + os.execute_or_panic('xcrun simctl launch $device $bundle_id') } else { exefile := os.real_path(b.pref.out_name) mut cmd := '"$exefile"' diff --git a/vlib/v/builder/js.v b/vlib/v/builder/js.v index 0a2b149731..ea5ae26653 100644 --- a/vlib/v/builder/js.v +++ b/vlib/v/builder/js.v @@ -56,9 +56,10 @@ pub fn (mut b Builder) compile_js() { fn (mut b Builder) run_js() { cmd := 'node ' + b.pref.out_name + '.js' - res := os.exec(cmd) or { - println('JS compilation failed.') - verror(err.msg) + res := os.execute(cmd) + if res.exit_code != 0 { + eprintln('JS compilation failed:') + verror(res.output) return } println(res.output) diff --git a/vlib/v/builder/msvc.v b/vlib/v/builder/msvc.v index 4a259441fc..3f86446fd3 100644 --- a/vlib/v/builder/msvc.v +++ b/vlib/v/builder/msvc.v @@ -137,7 +137,10 @@ fn find_vs(vswhere_dir string, host_arch string, target_arch string) ?VsInstalla // VSWhere is guaranteed to be installed at this location now // If its not there then end user needs to update their visual studio // installation! - res := os.exec('"$vswhere_dir\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') ? + res := os.execute('"$vswhere_dir\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') + if res.exit_code != 0 { + return error_with_code(res.output, res.exit_code) + } res_output := res.output.trim_right('\r\n') // println('res: "$res"') version := os.read_file('$res_output\\VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt') or { @@ -315,8 +318,9 @@ pub fn (mut v Builder) cc_msvc() { // Also the double quotes at the start ARE needed. v.show_cc(cmd, out_name_cmd_line, args) util.timing_start('C msvc') - res := os.exec(cmd) or { - println(err) + res := os.execute(cmd) + if res.exit_code != 0 { + eprintln(res.output) verror('msvc error') return } @@ -367,11 +371,7 @@ fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags $if trace_thirdparty_obj_files ? { println('>>> build_thirdparty_obj_file_with_msvc cmd: $cmd') } - res := os.exec(cmd) or { - println('msvc: failed to execute msvc compiler (to build a thirdparty object); cmd: $cmd') - verror(err.msg) - return - } + res := os.execute(cmd) if res.exit_code != 0 { println('msvc: failed to build a thirdparty object; cmd: $cmd') verror(res.output) diff --git a/vlib/v/compiler_errors_test.v b/vlib/v/compiler_errors_test.v index bfb8e56480..bdcb2eafa5 100644 --- a/vlib/v/compiler_errors_test.v +++ b/vlib/v/compiler_errors_test.v @@ -177,6 +177,11 @@ fn (mut tasks Tasks) run() { m_skip_files << 'vlib/v/checker/tests/missing_c_lib_header_1.vv' m_skip_files << 'vlib/v/checker/tests/missing_c_lib_header_with_explanation_2.vv' } + $if msvc { + // TODO: investigate why MSVC regressed + m_skip_files << 'vlib/v/checker/tests/missing_c_lib_header_1.vv' + m_skip_files << 'vlib/v/checker/tests/missing_c_lib_header_with_explanation_2.vv' + } for i in 0 .. tasks.all.len { if tasks.all[i].path in m_skip_files { tasks.all[i].is_skipped = true @@ -252,7 +257,7 @@ fn (mut task TaskDescription) execute() { } program := task.path cli_cmd := '$task.vexe $task.voptions $program' - res := os.exec(cli_cmd) or { panic(err) } + res := os.execute(cli_cmd) expected_out_path := program.replace('.vv', '') + task.result_extension task.expected_out_path = expected_out_path task.cli_cmd = cli_cmd diff --git a/vlib/v/fmt/fmt_keep_test.v b/vlib/v/fmt/fmt_keep_test.v index 3b130ccc73..fb4cfa1b90 100644 --- a/vlib/v/fmt/fmt_keep_test.v +++ b/vlib/v/fmt/fmt_keep_test.v @@ -87,7 +87,10 @@ fn fill_bin2v_keep() ? { img0 := os.join_path('tutorials', 'img', 'hello.png') img1 := os.join_path('tutorials', 'img', 'time.png') os.rm(b2v_keep_path) ? - os.exec('v bin2v -w $b2v_keep_path $img0 $img1') ? + res := os.execute('v bin2v -w $b2v_keep_path $img0 $img1') + if res.exit_code < 0 { + return error_with_code(res.output, res.exit_code) + } } fn restore_bin2v_placeholder() ? { diff --git a/vlib/v/gen/js/jsgen_test.v b/vlib/v/gen/js/jsgen_test.v index 2115b8fb68..8bae0074e3 100644 --- a/vlib/v/gen/js/jsgen_test.v +++ b/vlib/v/gen/js/jsgen_test.v @@ -48,7 +48,7 @@ fn find_test_files() []string { } fn is_nodejs_working() bool { - node_res := os.exec('node --version') or { return false } + node_res := os.execute('node --version') if node_res.exit_code != 0 { return false } diff --git a/vlib/v/gen/x64/tests/x64_test.v b/vlib/v/gen/x64/tests/x64_test.v index c1905481f8..8c89ac977c 100644 --- a/vlib/v/gen/x64/tests/x64_test.v +++ b/vlib/v/gen/x64/tests/x64_test.v @@ -28,18 +28,17 @@ fn test_x64() { bench.set_total_expected_steps(tests.len) for test in tests { bench.step() - full_test_path := os.real_path(test) - println('x.v: $wrkdir/x.v') - os.system('cp $dir/$test $wrkdir/x.v') // cant run .vv file - os.exec('$vexe -o exe -x64 $wrkdir/x.v') or { + full_test_path := os.real_path(os.join_path(dir, test)) + relative_test_path := full_test_path.replace(vroot + '/', '') + work_test_path := '$wrkdir/x.v' + os.cp(full_test_path, work_test_path) or {} + res_x64 := os.execute('$vexe -o exe -x64 $work_test_path') + if res_x64.exit_code != 0 { bench.fail() eprintln(bench.step_message_fail('x64 $test failed')) continue } - res := os.exec('./exe') or { - bench.fail() - continue - } + res := os.execute('./exe') if res.exit_code != 0 { bench.fail() eprintln(bench.step_message_fail('$full_test_path failed to run')) @@ -61,7 +60,7 @@ fn test_x64() { continue } bench.ok() - eprintln(bench.step_message_ok('testing file: $test')) + eprintln(bench.step_message_ok(relative_test_path)) } bench.stop() eprintln(term.h_divider('-')) diff --git a/vlib/v/live/executable/reloader.v b/vlib/v/live/executable/reloader.v index eadcbf7fd5..a4cad91ddd 100644 --- a/vlib/v/live/executable/reloader.v +++ b/vlib/v/live/executable/reloader.v @@ -69,10 +69,7 @@ fn compile_lib(mut r live.LiveReloadInfo) ?string { cmd := '$r.vexe $r.vopts -o $new_lib_path $r.original' elog(r, '> compilation cmd: $cmd') cwatch := time.new_stopwatch({}) - recompilation_result := os.exec(cmd) or { - eprintln('recompilation failed') - return none - } + recompilation_result := os.execute(cmd) elog(r, 'compilation took: ${cwatch.elapsed().milliseconds()}ms') if recompilation_result.exit_code != 0 { eprintln('recompilation error:') diff --git a/vlib/v/tests/array_init_test.v b/vlib/v/tests/array_init_test.v index b1a06e548c..e95dd7efbf 100644 --- a/vlib/v/tests/array_init_test.v +++ b/vlib/v/tests/array_init_test.v @@ -8,7 +8,9 @@ fn test_array_init() { a << 1 assert '$a, $a.len, $a.cap' == '[1], 1, 3' - c := Init{len: 3} + c := Init{ + len: 3 + } mut d := []string{cap: c.len} d << 'aaa' d << 'bbb' @@ -59,50 +61,50 @@ fn test_array_int_full_options() { println('Test array of int values') a := []int{len: 2, cap: 10} // this creates an array with 2 items, initial capacity 10, default value of array type - println('array a: length: ${a.len}, capacity: ${a.cap}, content: $a') + println('array a: length: $a.len, capacity: $a.cap, content: $a') assert a.len == 2 assert a.cap == 10 assert a.cap >= a.len - assert a.str() == "[0, 0]" + assert a.str() == '[0, 0]' b := []int{len: 10, cap: 100, init: 1} // this creates an array with 10 one and initial capacity 100 elements, value given _ = b.clone() // discard result variable, sample - println('array b: length: ${b.len}, capacity: ${b.cap}, content: $b') + println('array b: length: $b.len, capacity: $b.cap, content: $b') assert b.len == 10 assert b.cap == 100 assert b.cap >= b.len - assert b.str() == "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]" + assert b.str() == '[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]' mut c := []int{len: 2, cap: 10, init: 1} // this creates an array with 2 one and initial capacity 10 elements, value given _ = c.clone() // discard result variable, sample - println('array c: length: ${c.len}, capacity: ${c.cap}, content: $c') + println('array c: length: $c.len, capacity: $c.cap, content: $c') assert c.len == 2 assert c.cap == 10 assert c.cap >= c.len - assert c.str() == "[1, 1]" + assert c.str() == '[1, 1]' // add some items to the array, to check limits c << [3, 4, 5, 6, 7, 8, 9, 10] // add 8 items, from another array // update one item, to have the right number in the sequence ... c[1] = 2 - println('array c: length: ${c.len}, capacity: ${c.cap}, content now: $c') + println('array c: length: $c.len, capacity: $c.cap, content now: $c') assert c.len == 10 assert c.cap == 10 assert c.cap >= c.len - assert c.str() == "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" + assert c.str() == '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]' // add some more item after initial capacity, to ensure it's expandable c << [11, 12, 13, 14, 15, 16] - println('array c: length: ${c.len}, capacity: ${c.cap}, content now: $c') + println('array c: length: $c.len, capacity: $c.cap, content now: $c') assert c.len == 16 assert c.cap >= c.len - assert c.str() == "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]" + assert c.str() == '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]' } fn test_array_string_full_options() { println('Test array of string values') a := []string{len: 2, cap: 10} // this creates an array with 2 items, initial capacity 10, default value of array type - println('array a: length: ${a.len}, capacity: ${a.cap}') // ok - println('array a: length: ${a.len}, capacity: ${a.cap}, content: "$a"') + println('array a: length: $a.len, capacity: $a.cap') // ok + println('array a: length: $a.len, capacity: $a.cap, content: "$a"') assert a.len == 2 assert a.cap == 10 assert a.cap >= a.len @@ -110,8 +112,8 @@ fn test_array_string_full_options() { b := []string{len: 10, cap: 100, init: 'b'} // this creates an array with 10 'b', initial capacity 100 elements, value given _ = b.clone() // discard result variable, sample - println('array b: length: ${b.len}, capacity: ${b.cap}') // ok - println('array b: length: ${b.len}, capacity: ${b.cap}, content: $b') + println('array b: length: $b.len, capacity: $b.cap') // ok + println('array b: length: $b.len, capacity: $b.cap, content: $b') assert b.len == 10 assert b.cap == 100 assert b.cap >= b.len @@ -119,7 +121,7 @@ fn test_array_string_full_options() { mut c := []string{len: 2, cap: 10, init: 'c'} // this creates an array with 2 'c' and initial capacity 10 elements, value given _ = c.clone() // discard result variable, sample - println('array c: length: ${c.len}, capacity: ${c.cap}, content: $c') + println('array c: length: $c.len, capacity: $c.cap, content: $c') assert c.len == 2 assert c.cap == 10 assert c.cap >= c.len @@ -129,7 +131,7 @@ fn test_array_string_full_options() { // update some items, to have the right number in the sequence ... c[0] = 'a' c[1] = 'b' - println('array c: length: ${c.len}, capacity: ${c.cap}, content now: $c') + println('array c: length: $c.len, capacity: $c.cap, content now: $c') assert c.len == 10 assert c.cap == 10 assert c.cap >= c.len @@ -137,7 +139,7 @@ fn test_array_string_full_options() { // add some more item after initial capacity, to ensure all is good c << ['11', '12', '13', '14', '15', '16'] // c << ['11', nil, '13', '14', '15', '16'] // check later if/how to handle this ... - println('array c: length: ${c.len}, capacity: ${c.cap}, content now: $c') + println('array c: length: $c.len, capacity: $c.cap, content now: $c') assert c.len == 16 assert c.cap >= c.len assert c.str() == "['a', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', '11', '12', '13', '14', '15', '16']" @@ -149,8 +151,8 @@ pub mut: } fn test_array_init_in_struct_field() { - m := MyStruct { - ar: []f32{len: 4, init:1.2} + m := MyStruct{ + ar: []f32{len: 4, init: 1.2} } println(m) assert m.ar.str() == '[1.2, 1.2, 1.2, 1.2]' @@ -171,39 +173,42 @@ fn test_array_init_cast_type_in_struct_field() { } fn test_multi_dimensional_array_init() { - a := [][]int{len:2, init:[]int{len:4, init:2}} + a := [][]int{len: 2, init: []int{len: 4, init: 2}} assert '$a' == '[[2, 2, 2, 2], [2, 2, 2, 2]]' - b := [][]string{len:3, init:[]string{len:2, init:'abc'}} + b := [][]string{len: 3, init: []string{len: 2, init: 'abc'}} assert '$b' == "[['abc', 'abc'], ['abc', 'abc'], ['abc', 'abc']]" - c := [][]f64{len:2, init:[]f64{len:2, init:2.2}} + c := [][]f64{len: 2, init: []f64{len: 2, init: 2.2}} assert '$c' == '[[2.2, 2.2], [2.2, 2.2]]' - d := [][]int{len:3, init:[]int{len:2}} + d := [][]int{len: 3, init: []int{len: 2}} assert '$d' == '[[0, 0], [0, 0], [0, 0]]' - e := [][]string{len:2, init:[]string{len:3}} + e := [][]string{len: 2, init: []string{len: 3}} assert '$e' == "[['', '', ''], ['', '', '']]" - f := [][]int{len:3} + f := [][]int{len: 3} assert '$f' == '[[], [], []]' } fn test_array_init_direct_call() { assert []int{len: 2, init: 0}.len == 2 - assert []int{len: 3, init: 1}.map(it*2) == [2,2,2] + assert []int{len: 3, init: 1}.map(it * 2) == [2, 2, 2] } // test array init with sumtype type Alphabet = Abc | Xyz + struct Abc { val int } + struct Xyz { val int } -fn test_array_init_with_sumtype () { + +fn test_array_init_with_sumtype() { a := [Alphabet(Abc{1}), Xyz{2}] a0 := a[0] a1 := a[1] @@ -228,14 +233,18 @@ fn test_array_init_with_sumtype () { fn test_array_init_inferred_from_optional() { a := read() or { [] } x := 1 - b := read() or { match x { - 1 { - [] + b := read() or { + match x { + 1 { + [] + } + else { + [] + } } - else { - [] - } - }} + } + println(a) + println(b) } fn read() ?[]string { diff --git a/vlib/v/tests/blank_ident_test.v b/vlib/v/tests/blank_ident_test.v index a526645fc2..610799c196 100644 --- a/vlib/v/tests/blank_ident_test.v +++ b/vlib/v/tests/blank_ident_test.v @@ -88,7 +88,9 @@ fn test_nested_for_in_array_simple() { fn test_nested_for_in_array_key() { for _, v in [1, 2, 3] { + assert v > 0 for _, w in [1, 2, 3] { + assert w > 0 assert true } } @@ -96,7 +98,9 @@ fn test_nested_for_in_array_key() { fn test_nested_for_in_array_val() { for i, _ in [1, 2, 3] { + assert i > -1 for j, _ in [1, 2, 3] { + assert j > -1 assert true } } @@ -111,7 +115,7 @@ fn test_nested_for_in_array_both() { } const ( - m = { + m = map{ 'key': 'value' } ) @@ -172,12 +176,14 @@ fn fn_for_in_variadic_args_simple(arr ...string) { fn fn_for_in_variadic_args_key(arr ...string) { for _, v in arr { + assert v > 'A' assert true } } fn fn_for_in_variadic_args_val(arr ...string) { for i, _ in arr { + assert i > -1 assert true } } @@ -198,7 +204,9 @@ fn fn_nested_for_in_variadic_args(arr ...string) { fn fn_nested_for_in_variadic_args_key(arr ...string) { for _, v in arr { + assert v > 'A' for _, w in arr { + assert w > 'A' assert true } } @@ -206,7 +214,9 @@ fn fn_nested_for_in_variadic_args_key(arr ...string) { fn fn_nested_for_in_variadic_args_val(arr ...string) { for i, _ in arr { + assert i > -1 for j, _ in arr { + assert j > -1 assert true } } @@ -301,4 +311,13 @@ fn test_blank_multi_return() { _, h, _ := multi_return() i, _, _ := multi_return() _, _, _ := multi_return() + assert c == 1 + assert e == 1 + assert i == 1 + assert a == 2 + assert f == 2 + assert h == 2 + assert b == '3' + assert d == '3' + assert g == '3' } diff --git a/vlib/v/tests/goto_test.v b/vlib/v/tests/goto_test.v index f065893953..b4654739ba 100644 --- a/vlib/v/tests/goto_test.v +++ b/vlib/v/tests/goto_test.v @@ -1,10 +1,13 @@ fn test_goto() { mut i := 0 - a: b := 1 + a: + b := 1 _ = b i++ if i < 3 { - goto a + unsafe { + goto a + } } assert i == 3 } diff --git a/vlib/v/tests/inout/compiler_test.v b/vlib/v/tests/inout/compiler_test.v index 6b03a72b07..9e8aea8870 100644 --- a/vlib/v/tests/inout/compiler_test.v +++ b/vlib/v/tests/inout/compiler_test.v @@ -1,7 +1,6 @@ // .out file: // To test a panic, remove everything after the long `===` line // You can also remove the line with 'line:' e.g. for a builtin fn - import os import term import v.util @@ -22,19 +21,23 @@ fn test_all() { println('no compiler tests found') assert false } - paths := vtest.filter_vtest_only(tests, + paths := vtest.filter_vtest_only(tests, basepath: dir ) for path in paths { print(path + ' ') program := path - compilation := os.exec('$vexe -o test -cflags "-w" -cg $program') or { panic(err) } + compilation := os.execute('$vexe -o test -cflags "-w" -cg $program') + if compilation.exit_code < 0 { + panic(compilation.output) + } if compilation.exit_code != 0 { panic('compilation failed: $compilation.output') } - res := os.exec('./test') or { + res := os.execute('./test') + if res.exit_code < 0 { println('nope') - panic(err) + panic(res.output) } $if windows { os.rm('./test.exe') or { } diff --git a/vlib/v/tests/multiple_paths_in_vmodules/vmodules_overrides_test.v b/vlib/v/tests/multiple_paths_in_vmodules/vmodules_overrides_test.v index 0212027941..c498792bfb 100644 --- a/vlib/v/tests/multiple_paths_in_vmodules/vmodules_overrides_test.v +++ b/vlib/v/tests/multiple_paths_in_vmodules/vmodules_overrides_test.v @@ -18,7 +18,7 @@ fn test_vexe_is_set() { fn test_compiling_without_vmodules_fails() { os.chdir(vroot) os.setenv('VMODULES', '', true) - res := os.exec('"$vexe" run "$mainvv"') or { panic(err) } + res := os.execute('"$vexe" run "$mainvv"') assert res.exit_code == 1 assert res.output.trim_space().contains('builder error: cannot import module "yyy" (not found)') } @@ -27,7 +27,7 @@ fn test_compiling_with_vmodules_works() { os.chdir(vroot) vmpaths := ['path1', 'path2', 'path3'].map(os.join_path(basepath, it)) os.setenv('VMODULES', vmpaths.join(os.path_delimiter), true) - res := os.exec('"$vexe" run "$mainvv"') or { panic(err) } + res := os.execute('"$vexe" run "$mainvv"') assert res.exit_code == 0 assert res.output.trim_space() == "['x', 'y', 'z']" } diff --git a/vlib/v/tests/named_break_continue_test.v b/vlib/v/tests/named_break_continue_test.v index c537528fe1..39f3ebe733 100644 --- a/vlib/v/tests/named_break_continue_test.v +++ b/vlib/v/tests/named_break_continue_test.v @@ -1,30 +1,45 @@ fn test_labelled_for() { mut i := 4 - goto L1 + unsafe { + goto L1 + } L1: for { i++ for { - if i < 7 {continue L1} - else {break L1} + if i < 7 { + continue L1 + } else { + break L1 + } } } assert i == 7 - goto L2 - L2: for ;; i++ { + unsafe { + goto L2 + } + L2: for ; true; i++ { for { - if i < 17 {continue L2} - else {break L2} + if i < 17 { + continue L2 + } else { + break L2 + } } } assert i == 17 - goto L3 - L3: for e in [1,2,3,4] { + unsafe { + goto L3 + } + L3: for e in [1, 2, 3, 4] { i = e for { - if i < 3 {continue L3} - else {break L3} + if i < 3 { + continue L3 + } else { + break L3 + } } } assert i == 3 diff --git a/vlib/v/tests/profile/profile_test.v b/vlib/v/tests/profile/profile_test.v index 9abfb6fedd..f802c7bd5b 100644 --- a/vlib/v/tests/profile/profile_test.v +++ b/vlib/v/tests/profile/profile_test.v @@ -12,7 +12,7 @@ fn test_vexe_exists() { fn test_v_profile_works() { os.chdir(vroot) program_source := os.join_path(vroot, 'vlib/v/tests/profile/profile_test_1.v') - res := os.exec('"$vexe" -profile - run $program_source') or { exit(1) } + res := os.execute('"$vexe" -profile - run $program_source') // eprintln('res: $res') assert res.exit_code == 0 assert res.output.len > 0 diff --git a/vlib/v/tests/repl/repl_test.v b/vlib/v/tests/repl/repl_test.v index 33312a19cc..0634c093c9 100644 --- a/vlib/v/tests/repl/repl_test.v +++ b/vlib/v/tests/repl/repl_test.v @@ -12,11 +12,14 @@ fn test_the_v_compiler_can_be_invoked() { println('vexecutable: $vexec') assert vexec != '' vcmd := '"$vexec" -version' - r := os.exec(vcmd) or { panic(err) } - // println('"$vcmd" exit_code: $r.exit_code | output: $r.output') + r := os.execute_or_panic(vcmd) assert r.exit_code == 0 + // println('"$vcmd" exit_code: $r.exit_code | output: $r.output') vcmd_error := '"$vexec" nonexisting.v' - r_error := os.exec(vcmd_error) or { panic(err) } + r_error := os.execute(vcmd_error) + if r_error.exit_code < 0 { + panic(r_error.output) + } // println('"$vcmd_error" exit_code: $r_error.exit_code | output: $r_error.output') assert r_error.exit_code == 1 actual_error := r_error.output.trim_space() diff --git a/vlib/v/tests/repl/runner/runner.v b/vlib/v/tests/repl/runner/runner.v index 4ec542475e..7072c80b8a 100644 --- a/vlib/v/tests/repl/runner/runner.v +++ b/vlib/v/tests/repl/runner/runner.v @@ -50,7 +50,8 @@ pub fn run_repl_file(wd string, vexec string, file string) ?string { os.write_file(input_temporary_filename, input) or { panic(err) } os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent) or { panic(err) } rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename' - r := os.exec(rcmd) or { + r := os.execute(rcmd) + if r.exit_code < 0 { os.rm(input_temporary_filename) or { panic(err) } return error('Could not execute: $rcmd') } @@ -73,7 +74,7 @@ pub fn run_repl_file(wd string, vexec string, file string) ?string { $diff ') } else { - return 'Repl file $file is OK' + return file.replace('./', '') } } @@ -84,7 +85,10 @@ pub fn run_prod_file(wd string, vexec string, file string) ?string { } expected_content := f_expected_content.replace('\r', '') cmd := '"$vexec" -prod run "$file"' - r := os.exec(cmd) or { return error('Could not execute: $cmd') } + r := os.execute(cmd) + if r.exit_code < 0 { + return error('Could not execute: $cmd') + } if r.exit_code != 0 { return error('$cmd return exit code: $r.exit_code') } diff --git a/vlib/v/tests/run_v_code_from_stdin_test.v b/vlib/v/tests/run_v_code_from_stdin_test.v index fde6f33444..31de20250e 100644 --- a/vlib/v/tests/run_v_code_from_stdin_test.v +++ b/vlib/v/tests/run_v_code_from_stdin_test.v @@ -15,7 +15,7 @@ fn pipe_to_v_run() ? { os.write_file(tmp_v_file, 'println(1 + 3)\nprintln("hello")\n') ? assert os.is_file(tmp_v_file) cmd := '$cat_cmd "$tmp_v_file" | "$vexe" run -' - res := os.exec(cmd) ? + res := os.execute(cmd) // eprintln('>> cmd: $cmd | res: $res') assert res.exit_code == 0 assert res.output.replace('\r', '').trim_space().split('\n') == ['4', 'hello'] diff --git a/vlib/v/tests/valgrind/valgrind_test.v b/vlib/v/tests/valgrind/valgrind_test.v index c3110e93c1..8a71556d2d 100644 --- a/vlib/v/tests/valgrind/valgrind_test.v +++ b/vlib/v/tests/valgrind/valgrind_test.v @@ -73,11 +73,7 @@ fn test_all() { full_path_to_source_file := os.join_path(vroot, test) compile_cmd := '$vexe -o $exe_filename -cg -cflags "-w" -autofree "$full_path_to_source_file"' vprintln('compile cmd: ${util.bold(compile_cmd)}') - res := os.exec(compile_cmd) or { - bench.fail() - eprintln(bench.step_message_fail('valgrind $test failed')) - continue - } + res := os.execute(compile_cmd) if res.exit_code != 0 { bench.fail() eprintln(bench.step_message_fail('file: $test could not be compiled.')) @@ -93,11 +89,7 @@ fn test_all() { } valgrind_cmd := 'valgrind --error-exitcode=1 --leak-check=full $exe_filename' vprintln('valgrind cmd: ${util.bold(valgrind_cmd)}') - valgrind_res := os.exec(valgrind_cmd) or { - bench.fail() - eprintln(bench.step_message_fail('valgrind could not be executed')) - continue - } + valgrind_res := os.execute(valgrind_cmd) if valgrind_res.exit_code != 0 { bench.fail() eprintln(bench.step_message_fail('failed valgrind check for ${util.bold(test)}')) diff --git a/vlib/v/util/diff.v b/vlib/v/util/diff.v index 90fe7c8c25..167f3c2c1f 100644 --- a/vlib/v/util/diff.v +++ b/vlib/v/util/diff.v @@ -22,7 +22,10 @@ pub fn find_working_diff_command() ?string { } continue } - p := os.exec('$diffcmd --version') or { continue } + p := os.execute('$diffcmd --version') + if p.exit_code < 0 { + continue + } if p.exit_code == 127 && diffcmd == env_difftool { // user setup is wonky, fix it return error('could not find specified VDIFF_TOOL $diffcmd') @@ -41,9 +44,12 @@ pub fn find_working_diff_command() ?string { // determine if the FileMerge opendiff tool is available fn opendiff_exists() bool { - o := os.exec('opendiff') or { return false } + o := os.execute('opendiff') + if o.exit_code < 0 { + return false + } if o.exit_code == 1 { // failed (expected), but found (i.e. not 127) - if o.output.contains('too few arguments') { // got some exptected output + if o.output.contains('too few arguments') { // got some expected output return true } } @@ -53,7 +59,10 @@ fn opendiff_exists() bool { pub fn color_compare_files(diff_cmd string, file1 string, file2 string) string { if diff_cmd != '' { full_cmd := '$diff_cmd --minimal --text --unified=2 --show-function-line="fn " "$file1" "$file2" ' - x := os.exec(full_cmd) or { return 'comparison command: `$full_cmd` failed' } + x := os.execute(full_cmd) + if x.exit_code < 0 { + return 'comparison command: `$full_cmd` not found' + } return x.output.trim_right('\r\n') } return '' diff --git a/vlib/v/util/util.v b/vlib/v/util/util.v index ff5260e006..2ec63f6cb2 100644 --- a/vlib/v/util/util.v +++ b/vlib/v/util/util.v @@ -229,7 +229,7 @@ pub fn launch_tool(is_verbose bool, tool_name string, args []string) { if is_verbose { println('Compiling $tool_name with: "$compilation_command"') } - tool_compilation := os.exec(compilation_command) or { panic(err) } + tool_compilation := os.execute_or_panic(compilation_command) if tool_compilation.exit_code != 0 { eprintln('cannot compile `$tool_source`: \n$tool_compilation.output') exit(1) @@ -428,8 +428,9 @@ pub fn check_module_is_installed(modulename string, is_verbose bool) ?bool { if is_verbose { eprintln('check_module_is_installed: updating with $update_cmd ...') } - update_res := os.exec(update_cmd) or { - return error('can not start $update_cmd, error: $err') + update_res := os.execute(update_cmd) + if update_res.exit_code < 0 { + return error('can not start $update_cmd, error: $update_res.output') } if update_res.exit_code != 0 { eprintln('Warning: `$modulename` exists, but is not updated. @@ -446,11 +447,12 @@ and the existing module `$modulename` may still work.') if is_verbose { eprintln('check_module_is_installed: cloning from $murl ...') } - cloning_res := os.exec('git clone $murl $mpath') or { - return error('git is not installed, error: $err') + cloning_res := os.execute('git clone $murl $mpath') + if cloning_res.exit_code < 0 { + return error_with_code('git is not installed, error: $cloning_res.output', cloning_res.exit_code) } if cloning_res.exit_code != 0 { - return error('cloning failed, details: $cloning_res.output') + return error_with_code('cloning failed, details: $cloning_res.output', cloning_res.exit_code) } if !os.exists(mod_v_file) { return error('even after cloning, $mod_v_file is still missing')