v / cmd / tools / git_pre_commit_hook.vsh
69 lines · 64 sloc · 2.78 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp
2
3import os
4import term
5
6// This script can be used to ensure that all committed V files are vfmt-ed automatically.
7// By default, once setup, it will run `v fmt -w` on them, before committing them.
8
9// To use the script in your V project, you need to be in the main folder
10// of your project, then do the equivalent of:
11// ```sh
12// cp /PATH/TO_YOUR/V/cmd/tools/git_pre_commit_hook.vsh .git/hooks/pre-commit
13// chmod 755 .git/hooks/pre-commit
14// ```
15//
16// You could also use `vgit-fmt-hook` tool to install/update/remove and get
17// status for this hook.
18// This tool copies the git hook VSH script in .git/hooks/pre-commit
19//
20// Note: you can use this command:
21// `git config --bool --add hooks.stopCommitOfNonVfmtedVFiles true`
22// ... to make it just *prevent* the committing of unformatted .v files,
23// i.e. stop the committing, if they are not, but *without modifying them*
24// automatically (you will then need to run `v fmt -w` on them manually).
25//
26// Note 2: Git supports skipping the hooks, by passing the `--no-verify` option.
27// That can be used to commit some .v files that are not formatted, without removing
28// the hook.
29
30fn main() {
31 // This hook cares only about the changed V files, that will be committed, as reported by git itself:
32 changed :=
33 os.execute('git diff --cached --name-only --diff-filter=ACMR -- "*.v" "*.vsh" "*.vv"')
34
35 all_changed_vfiles := changed.output.trim_space().split('\n')
36 // _input.vv files are NOT formatted on purpose.
37 // There is no point in verifying them, or ruining them over with `v fmt -w`.
38 // Just filter them out, but still report to the user, that they will not be formatted:
39 vfiles := all_changed_vfiles.filter(!it.ends_with('_input.vv'))
40 input_vfiles := all_changed_vfiles.filter(it.ends_with('_input.vv'))
41 if input_vfiles.len > 0 {
42 eprintln('>>> ${input_vfiles.len} `_input.vv` files found, that *will NOT be* formatted.')
43 for ifile in input_vfiles {
44 eprintln(' ${ifile}')
45 }
46 }
47 if changed.output == '' || vfiles.len == 0 {
48 eprintln('>>> 0 changed V files, that may need formatting found.')
49 exit(0)
50 }
51 configured_stop_committing := os.execute('git config --bool hooks.stopCommitOfNonVfmtedVFiles')
52 if configured_stop_committing.output.trim_space().bool() {
53 verify_result := os.execute('${os.quoted_path(@VEXE)} fmt -verify ${vfiles.join(' ')}')
54 if verify_result.exit_code != 0 {
55 eprintln(verify_result.output)
56 }
57 exit(verify_result.exit_code)
58 } else {
59 eprintln('The V pre commit hook will format ${vfiles.len} V file(s):')
60 // vfmt off
61 for vfile in vfiles {
62 eprintln(' ${term.bold('${vfile}')}')
63 }
64 // vfmt on
65 all_vfiles_on_a_line := vfiles.map(os.quoted_path(it)).join(' ')
66 os.system('${os.quoted_path(@VEXE)} fmt -w ${all_vfiles_on_a_line}')
67 os.system('git add ${all_vfiles_on_a_line}')
68 }
69}
70