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