aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/old/cmd/tools/oldv.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/old/cmd/tools/oldv.v')
-rw-r--r--v_windows/v/old/cmd/tools/oldv.v176
1 files changed, 176 insertions, 0 deletions
diff --git a/v_windows/v/old/cmd/tools/oldv.v b/v_windows/v/old/cmd/tools/oldv.v
new file mode 100644
index 0000000..03eaf83
--- /dev/null
+++ b/v_windows/v/old/cmd/tools/oldv.v
@@ -0,0 +1,176 @@
+import os
+import flag
+import scripting
+import vgit
+
+const (
+ tool_version = '0.0.3'
+ tool_description = ' Checkout an old V and compile it as it was on specific commit.
+| This tool is useful, when you want to discover when something broke.
+| It is also useful, when you just want to experiment with an older historic V.
+|
+| The VCOMMIT argument can be a git commitish like HEAD or master and so on.
+| When oldv is used with git bisect, you probably want to give HEAD. For example:
+| git bisect start
+| git bisect bad
+| git checkout known_good_commit
+| git bisect good
+| ## Now git will automatically checkout a middle commit between the bad and the good
+| cmd/tools/oldv HEAD --command="run commands in oldv folder, to verify if the commit is good or bad"
+| ## See what the result is, and either do: ...
+| git bisect good
+| ## ... or do:
+| git bisect bad
+| ## Now you just repeat the above steps, each time running oldv with the same command, then mark the result as good or bad,
+| ## until you find the commit, where the problem first occurred.
+| ## When you finish, do not forget to do:
+| git bisect reset'.strip_margin()
+)
+
+struct Context {
+mut:
+ 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
+ use_cache bool // use local cached copies for --vrepo and --vcrepo in
+ fresh_tcc bool // do use `make fresh_tcc`
+}
+
+fn (mut c Context) compile_oldv_if_needed() {
+ c.vgcontext = vgit.VGitContext{
+ workdir: c.vgo.workdir
+ v_repo_url: c.vgo.v_repo_url
+ vc_repo_url: c.vgo.vc_repo_url
+ cc: c.cc
+ commit_v: c.commit_v
+ path_v: c.path_v
+ path_vc: c.path_vc
+ make_fresh_tcc: c.fresh_tcc
+ }
+ 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()
+ 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.fresh_tcc = fp.bool('fresh_tcc', 0, true, 'Do `make fresh_tcc` when preparing a V compiler.')
+ 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 {
+ context.commit_v = scripting.run('git rev-list -n1 HEAD')
+ }
+ scripting.cprintln('################# context.commit_v: $context.commit_v #####################')
+ context.path_v = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_v)
+ context.path_vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc')
+ if !os.is_dir(context.vgo.workdir) {
+ eprintln('Work folder: $context.vgo.workdir , does not exist.')
+ exit(2)
+ }
+ ecc := os.getenv('CC')
+ if ecc != '' {
+ context.cc = ecc
+ }
+ if context.cleanup {
+ scripting.rmrf(context.path_v)
+ scripting.rmrf(context.path_vc)
+ }
+ context.compile_oldv_if_needed()
+ scripting.chdir(context.path_v)
+ shorter_hash := context.commit_v_hash[0..10]
+ scripting.cprintln('# v commit hash: $shorter_hash | folder: $context.path_v')
+ if context.cmd_to_run.len > 0 {
+ scripting.cprintln_strong('# command: ${context.cmd_to_run:-34s}')
+ cmdres := os.execute_or_exit(context.cmd_to_run)
+ 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)
+ }
+}