v / cmd / tools
Raw file | 178 loc (162 sloc) | 4.76 KB | Latest commit hash 017ace6ea
1module main
2
3import os
4import v.util.version
5import v.util.recompilation
6
7const vexe = os.real_path(os.getenv_opt('VEXE') or { @VEXE })
8
9const vroot = os.dir(vexe)
10
11struct App {
12 is_verbose bool
13 is_prod bool
14 vexe string
15 vroot string
16}
17
18fn new_app() App {
19 return App{
20 is_verbose: '-v' in os.args
21 is_prod: '-prod' in os.args
22 vexe: vexe
23 vroot: vroot
24 }
25}
26
27fn main() {
28 app := new_app()
29 recompilation.must_be_enabled(app.vroot, 'Please install V from source, to use `v up` .')
30 os.chdir(app.vroot)!
31 println('Updating V...')
32 app.update_from_master()
33 v_hash := version.githash(false)
34 current_hash := version.githash(true)
35 // println(v_hash)
36 // println(current_hash)
37 if v_hash == current_hash {
38 println('V is already updated.')
39 app.show_current_v_version()
40 return
41 }
42 $if windows {
43 app.backup('cmd/tools/vup.exe')
44 }
45 if !app.recompile_v() {
46 app.show_current_v_version()
47 eprintln('Recompiling V *failed*.')
48 eprintln('Try running `${get_make_cmd_name()}` .')
49 exit(1)
50 }
51 app.recompile_vup()
52 app.show_current_v_version()
53}
54
55fn (app App) vprintln(s string) {
56 if app.is_verbose {
57 println(s)
58 }
59}
60
61fn (app App) update_from_master() {
62 app.vprintln('> updating from master ...')
63 if !os.exists('.git') {
64 // initialize as if it had been cloned
65 app.git_command('init')
66 app.git_command('remote add origin https://github.com/vlang/v')
67 app.git_command('fetch')
68 app.git_command('reset --hard origin/master')
69 app.git_command('clean --quiet -xdf --exclude v.exe --exclude cmd/tools/vup.exe')
70 } else {
71 // pull latest
72 app.git_command('pull https://github.com/vlang/v master')
73 }
74}
75
76fn (app App) recompile_v() bool {
77 // Note: app.vexe is more reliable than just v (which may be a symlink)
78 opts := if app.is_prod { '-prod' } else { '' }
79 vself := '${os.quoted_path(app.vexe)} ${opts} self'
80 app.vprintln('> recompiling v itself with `${vself}` ...')
81 self_result := os.execute(vself)
82 if self_result.exit_code == 0 {
83 println(self_result.output.trim_space())
84 return true
85 } else {
86 app.vprintln('`${vself}` failed, running `make`...')
87 app.vprintln(self_result.output.trim_space())
88 }
89 return app.make(vself)
90}
91
92fn (app App) recompile_vup() bool {
93 vup_result := os.execute('${os.quoted_path(app.vexe)} -g cmd/tools/vup.v')
94 if vup_result.exit_code != 0 {
95 eprintln('recompiling vup.v failed:')
96 eprintln(vup_result.output)
97 return false
98 }
99 return true
100}
101
102fn (app App) make(vself string) bool {
103 make := get_make_cmd_name()
104 make_result := os.execute(make)
105 if make_result.exit_code != 0 {
106 eprintln('> ${make} failed:')
107 eprintln('> make output:')
108 eprintln(make_result.output)
109 return false
110 }
111 app.vprintln(make_result.output)
112 return true
113}
114
115fn (app App) show_current_v_version() {
116 vout := os.execute('${os.quoted_path(app.vexe)} version')
117 if vout.exit_code >= 0 {
118 mut vversion := vout.output.trim_space()
119 if vout.exit_code == 0 {
120 latest_v_commit := vversion.split(' ').last().all_after('.')
121 latest_v_commit_time := os.execute('git show -s --format=%ci ${latest_v_commit}')
122 if latest_v_commit_time.exit_code == 0 {
123 vversion += ', timestamp: ' + latest_v_commit_time.output.trim_space()
124 }
125 }
126 println('Current V version: ${vversion}')
127 }
128}
129
130fn (app App) backup(file string) {
131 backup_file := '${file}_old.exe'
132 if os.exists(backup_file) {
133 os.rm(backup_file) or { eprintln('failed removing ${backup_file}: ${err.msg()}') }
134 }
135 os.mv(file, backup_file) or { eprintln('failed moving ${file}: ${err.msg()}') }
136}
137
138fn (app App) git_command(command string) {
139 app.vprintln('git_command: git ${command}')
140 git_result := os.execute('git ${command}')
141 if git_result.exit_code < 0 {
142 app.get_git()
143 // Try it again with (maybe) git installed
144 os.execute_or_exit('git ${command}')
145 }
146 if git_result.exit_code != 0 {
147 eprintln(git_result.output)
148 exit(1)
149 }
150 app.vprintln(git_result.output)
151}
152
153fn (app App) get_git() {
154 $if windows {
155 println('Downloading git 32 bit for Windows, please wait.')
156 // We'll use 32 bit because maybe someone out there is using 32-bit windows
157 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"')
158 if res_download.exit_code != 0 {
159 eprintln('Unable to install git automatically: please install git manually')
160 panic(res_download.output)
161 }
162 res_git32 := os.execute(os.quoted_path(os.join_path_single(os.getwd(), 'git32.exe')))
163 if res_git32.exit_code != 0 {
164 eprintln('Unable to install git automatically: please install git manually')
165 panic(res_git32.output)
166 }
167 } $else { // Probably some kind of *nix, usually need to get using a package manager.
168 eprintln("error: Install `git` using your system's package manager")
169 }
170}
171
172fn get_make_cmd_name() string {
173 $if windows {
174 return 'make.bat'
175 } $else {
176 return 'make'
177 }
178}