v / cmd / tools / vgit-fmt-hook_test.v
221 lines · 204 sloc · 8.66 KB · 3a435fab682583d9b816358cbdc5d6e0484b5320
Raw
1import os
2
3const vexe = @VEXE
4const tfolder = os.to_slash(os.join_path(os.vtmp_dir(), 'fmt_hook_test'))
5const unformatted_content = ' fn main() {\nprintln( "hi" )\n println ( 123 )\n }'
6const formatted_content = "fn main() {\n\tprintln('hi')\n\tprintln(123)\n}\n"
7const hook_file = '.git/hooks/pre-commit'
8// 'env -S' not supported on OpenBSD
9$if openbsd {
10 const foreign_script = '#!/bin/sh\ncat <<EOF | ${vexe} run -\nprintln("hello hello")\nEOF'
11} $else {
12 const foreign_script = '#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp\nprintln("hello hello")'
13}
14
15const git = os.to_slash(os.find_abs_path_of_executable('git') or {
16 eprintln('git is needed for this test, skipping...')
17 exit(0)
18})
19
20const v = os.to_slash(os.find_abs_path_of_executable('v') or {
21 eprintln('v needs to be installed and available on the path for this test, skipping...')
22 exit(0)
23})
24
25fn testsuite_begin() {
26 unbuffer_stdout()
27 eprintln('>>>>>> preparing tfolder: ${tfolder}')
28 full_remove(tfolder) or {}
29 os.mkdir_all(tfolder) or { panic('> could not create ${tfolder}, err: ${err}') }
30 os.chdir(tfolder)!
31 os.write_file('main.v', unformatted_content) or { panic(err) }
32 assert !os.is_dir('.git')
33 os.execute_or_exit('git init .')
34 os.execute_or_exit('git config core.eol lf')
35 os.execute_or_exit('git config core.autocrlf input')
36 os.execute_or_exit('git config user.email "[email protected]"')
37 os.execute_or_exit('git config user.name "Myself"')
38 assert os.is_dir('.git')
39 os.execute_or_exit('git add .')
40 os.execute_or_exit('git commit -m "start testing, initially unformatted"')
41 os.execute_or_exit('git checkout -b start') // use a known name, instead of master or main or who knows what else ...
42 assert read_file('main.v') == unformatted_content
43 // show_git_status()
44}
45
46fn testsuite_end() {
47 reset_to_start_state()
48 show_git_status()
49 os.chdir(os.wd_at_startup)!
50 if os.getenv('VTEST_KEEP_TFOLDER') != '1' {
51 full_remove(tfolder)!
52 eprintln('>>>>>> deleted ${tfolder} . Use VTEST_KEEP_TFOLDER=1 to keep it to ease diagnosing platform issues.')
53 }
54 assert true
55}
56
57fn test_commit_no_vfmt() {
58 eprintln('>>>> ${@FN}')
59 reset_to_start_state()
60 assert os.execute_or_exit('git checkout -b unformatted').exit_code == 0
61 append('main.v', '//') or { panic(err) }
62 assert os.execute_or_exit('git add .').exit_code == 0
63 assert os.execute_or_exit('git commit -m "unformatted change"').exit_code == 0
64 assert os.execute_or_exit('git diff start').exit_code == 0
65 assert read_file('main.v').starts_with(unformatted_content)
66}
67
68fn test_run_vfmt_manually() {
69 eprintln('>>>> ${@FN}')
70 reset_to_start_state()
71 assert os.execute_or_exit('git checkout -b formatted').exit_code == 0
72 os.write_file('README.md', 'some new content') or { panic(err) }
73 assert os.execute_or_exit('${os.quoted_path(vexe)} fmt -w .').exit_code == 0
74 assert os.execute_or_exit('git add .').exit_code == 0
75 assert os.execute_or_exit('git commit -m "formatted change"').exit_code == 0
76 assert os.execute_or_exit('git diff start').exit_code == 0
77 assert read_file('main.v') == formatted_content
78}
79
80fn test_run_git_fmt_hook() {
81 eprintln('>>>> ${@FN}')
82 reset_to_start_state()
83 res := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook')
84 assert res.exit_code == 0
85 assert res.output.contains('> CURRENT git repo pre-commit hook: missing')
86 assert res.output.contains('> Main V repo pre-commit hook script: size: ')
87 // Git hook = shell script on OpenBSD
88 $if openbsd {
89 assert res.output.contains('git_pre_commit_hook.sh')
90 } $else {
91 assert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')
92 }
93 assert res.output.contains('> Files have different hashes.')
94 assert res.output.contains('> Use `v git-fmt-hook install`')
95}
96
97fn test_run_git_fmt_hook_status_explicit() {
98 eprintln('>>>> ${@FN}')
99 reset_to_start_state()
100 res := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status')
101 assert res.exit_code == 0
102 assert res.output.contains('> CURRENT git repo pre-commit hook: missing')
103 assert res.output.contains('> Main V repo pre-commit hook script: size: ')
104 // Git hook = shell script on OpenBSD
105 $if openbsd {
106 assert res.output.contains('git_pre_commit_hook.sh')
107 } $else {
108 assert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')
109 }
110 assert res.output.contains('> Files have different hashes.')
111 assert res.output.contains('> Use `v git-fmt-hook install`')
112}
113
114fn test_run_git_fmt_hook_install() {
115 eprintln('>>>> ${@FN}')
116 reset_to_start_state()
117 os.execute_or_exit('git checkout -b formatting_with_hook')
118 append('main.v', '\n') or { panic(err) }
119 assert read_file('main.v').starts_with(unformatted_content)
120 assert !os.is_file(hook_file)
121 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0
122 assert os.is_file(hook_file)
123 res := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status')
124 assert res.output.contains('> CURRENT git repo pre-commit hook: size: ')
125 assert res.output.contains('> Main V repo pre-commit hook script: size: ')
126 // Git hook = shell script on OpenBSD
127 $if openbsd {
128 assert res.output.contains('git_pre_commit_hook.sh')
129 } $else {
130 assert res.output.contains('cmd/tools/git_pre_commit_hook.vsh')
131 }
132 assert res.output.contains(hook_file)
133 assert res.output.contains('> Both files are exactly the same.')
134 assert !res.output.contains('> Use `v git-fmt-hook install`')
135 assert res.output.contains('> Use `v git-fmt-hook remove`')
136 assert !res.output.contains('> Done.'), 'res:\n${res}'
137 os.execute_or_exit('git add -u')
138 os.execute_or_exit('git commit -m "this should be formatted"')
139 assert read_file('main.v') == formatted_content
140 dres := os.execute_or_exit('git diff start')
141 // dump(dres)
142 assert dres.exit_code == 0
143 assert dres.output.contains('+fn main() {')
144 assert dres.output.contains("+\tprintln('hi')")
145 second := os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install')
146 assert second.exit_code == 0
147}
148
149fn test_run_git_fmt_hook_remove() {
150 eprintln('>>>> ${@FN}')
151 reset_to_start_state()
152 os.execute_or_exit('git checkout start')
153 os.execute_or_exit('git checkout -b non_formatting_after_removing_hook')
154 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0
155 assert os.is_file(hook_file)
156 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook remove').exit_code == 0
157 assert !os.is_file(hook_file)
158 append('main.v', '\n') or { panic(err) }
159 assert read_file('main.v').starts_with(unformatted_content)
160 os.execute_or_exit('git add -u')
161 os.execute_or_exit('git commit -m "this should NOT be formatted again"')
162 assert read_file('main.v').starts_with(unformatted_content)
163}
164
165fn test_run_git_fmt_hook_install_and_remove_on_foreign_hook_should_be_a_nop() {
166 eprintln('>>>> ${@FN}')
167 reset_to_start_state()
168 os.execute_or_exit('git checkout start')
169 os.execute_or_exit('git checkout -b install_and_remove_should_be_a_nop_on_a_foreign_hook')
170 os.write_file(hook_file, foreign_script) or { panic(err) }
171 os.chmod(hook_file, 0o0777) or { panic(err) }
172 assert read_file(hook_file) == foreign_script
173 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0
174 assert read_file(hook_file) == foreign_script
175 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook remove').exit_code == 0
176 assert read_file(hook_file) == foreign_script
177 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook install').exit_code == 0
178 assert read_file(hook_file) == foreign_script
179 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook status').exit_code == 0
180 assert read_file(hook_file) == foreign_script
181 assert os.execute_or_exit('${os.quoted_path(vexe)} git-fmt-hook').exit_code == 0
182 assert read_file(hook_file) == foreign_script
183 append('main.v', '\n') or { panic(err) }
184 append('main.v', '\n') or { panic(err) }
185 assert read_file('main.v').starts_with(unformatted_content)
186 os.execute_or_exit('git add -u')
187 fcommiting := os.execute_or_exit('git commit -m "this should NOT be formatted 2"')
188 assert fcommiting.exit_code == 0
189 assert fcommiting.output.contains('hello hello')
190 assert read_file('main.v').starts_with(unformatted_content)
191}
192
193fn show_git_status() {
194 os.system('git log --graph --all --decorate')
195 os.system('git status')
196}
197
198fn append(path string, content string) ! {
199 mut f := os.open_append('main.v')!
200 f.write_string(content)!
201 f.close()
202}
203
204fn read_file(path string) string {
205 return os.read_file(path) or { panic(err) }
206}
207
208fn reset_to_start_state() {
209 os.execute('git checkout start')
210 os.rm('.git/hooks/pre-commit') or {}
211 assert read_file('main.v') == unformatted_content
212}
213
214fn full_remove(path string) ! {
215 // TODO: fix this on windows; the files inside .git/ are with read only permissions, and os.rmdir_all() can not delete them, until they are chmoded to writable
216 files := os.walk_ext(path + '/.git', '')
217 for f in files {
218 os.chmod(f, 0o777) or {}
219 }
220 os.rmdir_all(path)!
221}
222