| 1 | #!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp |
| 2 | |
| 3 | import os |
| 4 | import 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 | |
| 30 | fn 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 | |