1#!/usr/bin/env bash 2 3# Git pre-commit hook to check staged Python files for formatting issues with 4# yapf. 5# 6# INSTALLING: Copy this script into `.git/hooks/pre-commit`, and mark it as 7# executable. 8# 9# This requires that yapf is installed and runnable in the environment running 10# the pre-commit hook. 11# 12# When running, this first checks for unstaged changes to staged files, and if 13# there are any, it will exit with an error. Files with unstaged changes will be 14# printed. 15# 16# If all staged files have no unstaged changes, it will run yapf against them, 17# leaving the formatting changes unstaged. Changed files will be printed. 18# 19# BUGS: This does not leave staged changes alone when used with the -a flag to 20# git commit, due to the fact that git stages ALL unstaged files when that flag 21# is used. 22 23# Find all staged Python files, and exit early if there aren't any. 24PYTHON_FILES=() 25while IFS=$'\n' read -r line; do PYTHON_FILES+=("$line"); done \ 26 < <(git diff --name-only --cached --diff-filter=AM | grep --color=never '.py$') 27if [ ${#PYTHON_FILES[@]} -eq 0 ]; then 28 exit 0 29fi 30 31########## PIP VERSION ############# 32# Verify that yapf is installed; if not, warn and exit. 33if ! command -v yapf >/dev/null; then 34 echo 'yapf not on path; can not format. Please install yapf:' 35 echo ' pip install yapf' 36 exit 2 37fi 38######### END PIP VERSION ########## 39 40########## PIPENV VERSION ########## 41# if ! pipenv run yapf --version 2>/dev/null 2>&1; then 42# echo 'yapf not on path; can not format. Please install yapf:' 43# echo ' pipenv install yapf' 44# exit 2 45# fi 46###### END PIPENV VERSION ########## 47 48 49# Check for unstaged changes to files in the index. 50CHANGED_FILES=() 51while IFS=$'\n' read -r line; do CHANGED_FILES+=("$line"); done \ 52 < <(git diff --name-only "${PYTHON_FILES[@]}") 53if [ ${#CHANGED_FILES[@]} -gt 0 ]; then 54 echo 'You have unstaged changes to some files in your commit; skipping ' 55 echo 'auto-format. Please stage, stash, or revert these changes. You may ' 56 echo 'find `git stash -k` helpful here.' 57 echo 'Files with unstaged changes:' "${CHANGED_FILES[@]}" 58 exit 1 59fi 60 61# Format all staged files, then exit with an error code if any have uncommitted 62# changes. 63echo 'Formatting staged Python files . . .' 64 65########## PIP VERSION ############# 66yapf -i -r "${PYTHON_FILES[@]}" 67######### END PIP VERSION ########## 68 69########## PIPENV VERSION ########## 70# pipenv run yapf -i -r "${PYTHON_FILES[@]}" 71###### END PIPENV VERSION ########## 72 73 74CHANGED_FILES=() 75while IFS=$'\n' read -r line; do CHANGED_FILES+=("$line"); done \ 76 < <(git diff --name-only "${PYTHON_FILES[@]}") 77if [ ${#CHANGED_FILES[@]} -gt 0 ]; then 78 echo 'Reformatted staged files. Please review and stage the changes.' 79 echo 'Files updated: ' "${CHANGED_FILES[@]}" 80 exit 1 81else 82 exit 0 83fi 84