diff --git a/cmd/tools/modules/scripting/scripting.v b/cmd/tools/modules/scripting/scripting.v index 55ddc22c14..edf6a0ade3 100644 --- a/cmd/tools/modules/scripting/scripting.v +++ b/cmd/tools/modules/scripting/scripting.v @@ -46,26 +46,25 @@ pub fn cprintln_strong(omessage string) { pub fn verbose_trace(label string, message string) { if os.getenv('VERBOSE').len > 0 { - slabel := '$time.now().format_ss_milli() scripting.$label' - cprintln('# ${slabel:-40s} : $message') + slabel := '$time.now().format_ss_milli() $label' + cprintln('# ${slabel:-43s} : $message') } } pub fn verbose_trace_strong(label string, omessage string) { if os.getenv('VERBOSE').len > 0 { - slabel := '$time.now().format_ss_milli() scripting.$label' + slabel := '$time.now().format_ss_milli() $label' mut message := omessage if scripting.term_colors { message = term.bright_green(message) } - cprintln('# ${slabel:-40s} : $message') + cprintln('# ${slabel:-43s} : $message') } } pub fn verbose_trace_exec_result(x os.Result) { if os.getenv('VERBOSE').len > 0 { cprintln('# cmd.exit_code : ${x.exit_code.str():-4s} cmd.output:') - cprintln('# ----------------------------------- #') mut lnum := 1 lines := x.output.split_into_lines() for oline in lines { @@ -76,17 +75,37 @@ pub fn verbose_trace_exec_result(x os.Result) { cprintln('# ${lnum:3d}: $line') lnum++ } - cprintln('# ----------------------------------- #') + cprintln('# ----------------------------------------------------------------------') } } +fn modfn(mname string, fname string) string { + return '${mname}.$fname' +} + pub fn chdir(path string) { - verbose_trace_strong(@FN, 'cd $path') + verbose_trace_strong(modfn(@MOD, @FN), 'cd $path') os.chdir(path) } +pub fn mkdir(path string) ? { + verbose_trace_strong(modfn(@MOD, @FN), 'mkdir $path') + os.mkdir(path) or { + verbose_trace(modfn(@MOD, @FN), '## failed.') + return err + } +} + +pub fn mkdir_all(path string) ? { + verbose_trace_strong(modfn(@MOD, @FN), 'mkdir -p $path') + os.mkdir_all(path) or { + verbose_trace(modfn(@MOD, @FN), '## failed.') + return err + } +} + pub fn rmrf(path string) { - verbose_trace_strong(@FN, 'rm -rf $path') + verbose_trace_strong(modfn(@MOD, @FN), 'rm -rf $path') if os.exists(path) { if os.is_dir(path) { os.rmdir_all(path) or { panic(err) } @@ -98,10 +117,10 @@ 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_strong(@FN, cmd) + verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code != 0 { - verbose_trace(@FN, '## failed.') + verbose_trace(modfn(@MOD, @FN), '## failed.') return error(x.output) } verbose_trace_exec_result(x) @@ -110,10 +129,10 @@ pub fn exec(cmd string) ?os.Result { // run a command, tracing its results, and returning ONLY its output pub fn run(cmd string) string { - verbose_trace_strong(@FN, cmd) + verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code < 0 { - verbose_trace(@FN, '## failed.') + verbose_trace(modfn(@MOD, @FN), '## failed.') return '' } verbose_trace_exec_result(x) @@ -124,10 +143,10 @@ pub fn run(cmd string) string { } pub fn exit_0_status(cmd string) bool { - verbose_trace_strong(@FN, cmd) + verbose_trace_strong(modfn(@MOD, @FN), cmd) x := os.execute(cmd) if x.exit_code < 0 { - verbose_trace(@FN, '## failed.') + verbose_trace(modfn(@MOD, @FN), '## failed.') return false } verbose_trace_exec_result(x) @@ -138,7 +157,7 @@ pub fn exit_0_status(cmd string) bool { } pub fn tool_must_exist(toolcmd string) { - verbose_trace(@FN, toolcmd) + verbose_trace(modfn(@MOD, @FN), toolcmd) if exit_0_status('type $toolcmd') { return } diff --git a/cmd/tools/modules/vgit/vgit.v b/cmd/tools/modules/vgit/vgit.v index 59714b0844..766c3ced2c 100644 --- a/cmd/tools/modules/vgit/vgit.v +++ b/cmd/tools/modules/vgit/vgit.v @@ -4,11 +4,6 @@ import os import flag import scripting -const ( - remote_v_repo_url = 'https://github.com/vlang/v' - remote_vc_repo_url = 'https://github.com/vlang/vc' -) - pub fn check_v_commit_timestamp_before_self_rebuilding(v_timestamp int) { if v_timestamp >= 1561805697 { return @@ -164,9 +159,9 @@ pub mut: pub fn add_common_tool_options(mut context VGitOptions, mut fp flag.FlagParser) []string { tdir := os.temp_dir() - context.workdir = os.real_path(fp.string('workdir', `w`, tdir, 'A writable base folder. Default: $tdir')) - context.v_repo_url = fp.string('vrepo', 0, vgit.remote_v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.') - context.vc_repo_url = fp.string('vcrepo', 0, vgit.remote_vc_repo_url, 'The url of the vc repository. You can clone it + context.workdir = os.real_path(fp.string('workdir', `w`, context.workdir, 'A writable base folder. Default: $tdir')) + context.v_repo_url = fp.string('vrepo', 0, context.v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.') + context.vc_repo_url = fp.string('vcrepo', 0, context.vc_repo_url, 'The url of the vc repository. You can clone it ${flag.space}beforehand, and then just give the local folder ${flag.space}path here. That will eliminate the network ops ${flag.space}done by this tool, which is useful, if you want diff --git a/cmd/tools/oldv.v b/cmd/tools/oldv.v index fc3c195c7c..3d7b03e1ac 100644 --- a/cmd/tools/oldv.v +++ b/cmd/tools/oldv.v @@ -29,22 +29,20 @@ const ( struct Context { mut: - 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' - // this will be derived from commit_v + vgo vgit.VGitOptions + vgcontext vgit.VGitContext + commit_v string = 'master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too) 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. path_vc string // the full path to the vc folder inside workdir. 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 + cc string = 'cc' // the C compiler to use for bootstrapping. + cleanup bool // should the tool run a cleanup first + use_cache bool // use local cached copies for --vrepo and --vcrepo in } fn (mut c Context) compile_oldv_if_needed() { - mut vgit_context := vgit.VGitContext{ + c.vgcontext = vgit.VGitContext{ workdir: c.vgo.workdir v_repo_url: c.vgo.v_repo_url vc_repo_url: c.vgo.vc_repo_url @@ -53,28 +51,91 @@ fn (mut c Context) compile_oldv_if_needed() { path_v: c.path_v path_vc: c.path_vc } - vgit_context.compile_oldv_if_needed() - c.commit_v_hash = vgit_context.commit_v__hash - if !os.exists(vgit_context.vexepath) && c.cmd_to_run.len > 0 { + c.vgcontext.compile_oldv_if_needed() + c.commit_v_hash = c.vgcontext.commit_v__hash + if !os.exists(c.vgcontext.vexepath) && c.cmd_to_run.len > 0 { // NB: 125 is a special code, that git bisect understands as 'skip this commit'. // it is used to inform git bisect that the current commit leads to a build failure. exit(125) } } +const cache_oldv_folder = os.join_path(os.cache_dir(), 'oldv') + +const cache_oldv_folder_v = os.join_path(cache_oldv_folder, 'v') + +const cache_oldv_folder_vc = os.join_path(cache_oldv_folder, 'vc') + +fn sync_cache() { + scripting.verbose_trace(@FN, 'start') + if !os.exists(cache_oldv_folder) { + scripting.verbose_trace(@FN, 'creating $cache_oldv_folder') + scripting.mkdir_all(cache_oldv_folder) or { + scripting.verbose_trace(@FN, '## failed.') + exit(1) + } + } + scripting.chdir(cache_oldv_folder) + for reponame in ['v', 'vc'] { + repofolder := os.join_path(cache_oldv_folder, reponame) + if !os.exists(repofolder) { + scripting.verbose_trace(@FN, 'cloning to $repofolder') + scripting.exec('git clone --quiet https://github.com/vlang/$reponame $repofolder') or { + scripting.verbose_trace(@FN, '## error during clone: $err') + exit(1) + } + } + scripting.chdir(repofolder) + scripting.exec('git pull --quiet') or { + scripting.verbose_trace(@FN, 'pulling to $repofolder') + scripting.verbose_trace(@FN, '## error during pull: $err') + exit(1) + } + } + scripting.verbose_trace(@FN, 'done') +} + fn main() { scripting.used_tools_must_exist(['git', 'cc']) + // + // Resetting VEXE here allows for `v run cmd/tools/oldv.v'. + // the parent V would have set VEXE, which later will + // affect the V's run from the tool itself. + os.setenv('VEXE', '', true) + // mut context := Context{} + context.vgo.workdir = cache_oldv_folder mut fp := flag.new_flag_parser(os.args) fp.application(os.file_name(os.executable())) fp.version(tool_version) fp.description(tool_description) fp.arguments_description('VCOMMIT') fp.skip_executable() - fp.limit_free_args(1, 1) - context.cleanup = fp.bool('clean', 0, true, 'Clean before running (slower).') + context.use_cache = fp.bool('cache', `u`, true, 'Use a cache of local repositories for --vrepo and --vcrepo in \$HOME/.cache/oldv/') + if context.use_cache { + context.vgo.v_repo_url = cache_oldv_folder_v + context.vgo.vc_repo_url = cache_oldv_folder_vc + } else { + context.vgo.v_repo_url = 'https://github.com/vlang/v' + context.vgo.vc_repo_url = 'https://github.com/vlang/vc' + } + should_sync := fp.bool('cache-sync', `s`, false, 'Update the local cache') + if !should_sync { + fp.limit_free_args(1, 1) + } + //// + context.cleanup = fp.bool('clean', 0, false, 'Clean before running (slower).') context.cmd_to_run = fp.string('command', `c`, '', 'Command to run in the old V repo.\n') commits := vgit.add_common_tool_options(mut context.vgo, mut fp) + if should_sync { + sync_cache() + exit(0) + } + if context.use_cache { + if !os.is_dir(cache_oldv_folder_v) || !os.is_dir(cache_oldv_folder_vc) { + sync_cache() + } + } if commits.len > 0 { context.commit_v = commits[0] } else { @@ -102,7 +163,9 @@ fn main() { if context.cmd_to_run.len > 0 { scripting.cprintln_strong('# command: ${context.cmd_to_run:-34s}') cmdres := os.execute_or_panic(context.cmd_to_run) - scripting.cprintln_strong('# exit code: ${cmdres.exit_code:-4d}') + if cmdres.exit_code != 0 { + scripting.cprintln_strong('# exit code: ${cmdres.exit_code:-4d}') + } scripting.cprint_strong('# result: ') print(cmdres.output) exit(cmdres.exit_code)