| #!/usr/bin/env bash |
| |
| # Git pre-commit hook to check staged Python files for formatting issues with |
| # yapf. |
| # |
| # INSTALLING: Copy this script into `.git/hooks/pre-commit`, and mark it as |
| # executable. |
| # |
| # This requires that yapf is installed and runnable in the environment running |
| # the pre-commit hook. |
| # |
| # When running, this first checks for unstaged changes to staged files, and if |
| # there are any, it will exit with an error. Files with unstaged changes will be |
| # printed. |
| # |
| # If all staged files have no unstaged changes, it will run yapf against them, |
| # leaving the formatting changes unstaged. Changed files will be printed. |
| # |
| # BUGS: This does not leave staged changes alone when used with the -a flag to |
| # git commit, due to the fact that git stages ALL unstaged files when that flag |
| # is used. |
| |
| # Find all staged Python files, and exit early if there aren't any. |
| PYTHON_FILES=() |
| while IFS=$'\n' read -r line; do PYTHON_FILES+=("$line"); done \ |
| < <(git diff --name-only --cached --diff-filter=AM | grep --color=never '.py$') |
| if [ ${#PYTHON_FILES[@]} -eq 0 ]; then |
| exit 0 |
| fi |
| |
| ########## PIP VERSION ############# |
| # Verify that yapf is installed; if not, warn and exit. |
| if ! command -v yapf >/dev/null; then |
| echo 'yapf not on path; can not format. Please install yapf:' |
| echo ' pip install yapf' |
| exit 2 |
| fi |
| ######### END PIP VERSION ########## |
| |
| ########## PIPENV VERSION ########## |
| # if ! pipenv run yapf --version 2>/dev/null 2>&1; then |
| # echo 'yapf not on path; can not format. Please install yapf:' |
| # echo ' pipenv install yapf' |
| # exit 2 |
| # fi |
| ###### END PIPENV VERSION ########## |
| |
| |
| # Check for unstaged changes to files in the index. |
| CHANGED_FILES=() |
| while IFS=$'\n' read -r line; do CHANGED_FILES+=("$line"); done \ |
| < <(git diff --name-only "${PYTHON_FILES[@]}") |
| if [ ${#CHANGED_FILES[@]} -gt 0 ]; then |
| echo 'You have unstaged changes to some files in your commit; skipping ' |
| echo 'auto-format. Please stage, stash, or revert these changes. You may ' |
| echo 'find `git stash -k` helpful here.' |
| echo 'Files with unstaged changes:' "${CHANGED_FILES[@]}" |
| exit 1 |
| fi |
| |
| # Format all staged files, then exit with an error code if any have uncommitted |
| # changes. |
| echo 'Formatting staged Python files . . .' |
| |
| ########## PIP VERSION ############# |
| yapf -i -r "${PYTHON_FILES[@]}" |
| ######### END PIP VERSION ########## |
| |
| ########## PIPENV VERSION ########## |
| # pipenv run yapf -i -r "${PYTHON_FILES[@]}" |
| ###### END PIPENV VERSION ########## |
| |
| |
| CHANGED_FILES=() |
| while IFS=$'\n' read -r line; do CHANGED_FILES+=("$line"); done \ |
| < <(git diff --name-only "${PYTHON_FILES[@]}") |
| if [ ${#CHANGED_FILES[@]} -gt 0 ]; then |
| echo 'Reformatted staged files. Please review and stage the changes.' |
| echo 'Files updated: ' "${CHANGED_FILES[@]}" |
| exit 1 |
| else |
| exit 0 |
| fi |