1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
#!/bin/bash
# Auto format changed java files using google-java-format.
# To install, copy this file into $repo/.git/hooks and remove the .sh extension.
# Download the google-java-format JAR from
# https://github.com/google/google-java-format
# A more mature implementation of this would be a plugin for Yelp's pre-commit library:
# http://pre-commit.com/
echo "Running auto-formatter for any changed Java files"
echo "(formatting changes will be automatically added to your commit)"
# Grab root directory to help with creating an absolute path for changed files.
root_dir="$(git rev-parse --show-toplevel)"
[ -d "${root_dir}" ] || exit 1
# TODO add your path here.
jar_base_dir="git_hooks/"
# To avoid any unexpected behavior, we need to "stash" any unstaged changes.
# We could use "git stash" but the situation gets complicated because we
# need to make additional changes with the formatter.
# Here's how we could do this if we didn't need to make additional changes:
# http://stackoverflow.com/a/20480591
# But since we do, we follow the same general pattern as the "pre-commit" lib:
# https://github.com/pre-commit/pre-commit/blob/master/pre_commit/staged_files_only.py#L15
# Basically we just diff the unstaged changes, store the patch, and apply it later.
# In the future, we should consider migrating to using that library.
staged_changes_diff=$(mktemp -t format_patch)
git diff --ignore-submodules --binary --exit-code --no-color > $staged_changes_diff
if [ $? -eq 1 ]; then
echo "Found unstaged changes, storing in ${staged_changes_diff}"
echo "Clearing unstaged changes for formatting, will restore after formatting."
git checkout -- ${root_dir}
stored_staged_changes=true
else
stored_staged_changes=false
fi
formatter_jar="${root_dir}/${jar_base_dir}/google-java-format-1.6-SNAPSHOT-all-deps.jar"
formatter_cmd="java -jar ${formatter_jar}"
# Format file in-place and use 4-space style (AOSP).
formatter_args="--replace --aosp"
# filter=ACMR shows only added, changed, modified, or renamed files.
# Get only java files and prepend the root directory to make the paths absolute.
# Only format files in src/main/java and src/test/java (src/test/test-project contains java files that need to be left alone)
changed_java_files=($(git diff --cached --name-only --diff-filter=ACMR src/main/java src/test/java \
| grep ".*java$" \
| sed "s:^:${root_dir}/:"))
# If we have changed java files, format them!
if [ ${#changed_java_files[@]} -gt 0 ]; then
# Do the formatting, stage the changes, and print out which files were changed.
eval ${formatter_cmd} ${formatter_args} "${changed_java_files[@]}"
git add "${changed_java_files[@]}"
echo "${changed_java_files[@]}" | xargs basename | sed "s/^/ Formatting: /"
fi
echo "Finished formatting."
if $stored_staged_changes ; then
echo "Restoring unstaged changes"
git apply "${staged_changes_diff}"
if [ $? -eq 1 ]; then
echo "Shoot! We failed to re-apply your unstaged changes."
echo "The patch for these changes is preserved at ${staged_changes_diff}"
fi
fi
|