summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt McCormick (thewtex) <matt@mmmccormick.com>2010-09-09 11:45:14 -0500
committerMatt McCormick (thewtex) <matt@mmmccormick.com>2010-09-27 14:53:00 -0500
commitd5bb076453719934cd9eda65e72d337acb4fe5bd (patch)
treed048c424e090e3a66c77d435e18673137a96fc80
parent19f86ec15cc36f3edd30210724b0d11b080d9961 (diff)
downloadcmake-d5bb076453719934cd9eda65e72d337acb4fe5bd.tar.gz
pre-commit: Apply uncrustify and KWStyle check for modified files.
uncrustify (uncrustify.sourceforge.net) is applied to changed files prior to commit. This feature is off by default. To enable this behavior, set git config hooks.uncrustify true By default, the behavior of git-mergetool is used to review the changes uncrustify makes before they are added to the commit. For more information on this behavior, see git help mergetool KWStyle is run on the changed C++ files and the commit is aborted if the files do not pass the test. A file similar to the original is saved with a '*.kws' extension so that line numbers referenced in the error message can be examined. The test is off by default. To enable this behavoir, set git config hooks.KWStyle true Project specific uncrustify and KWStyle configuration files are set with 'git config'. For example, git config hooks.uncrustify.conf path/to/uncrustify.conf git config hooks.KWStyle.conf path/to/KWStyle.conf git config hooks.KWStyle.overwriteRulesConf path/to/overwrite.conf # optional If the appropriate values have not been set, die() is called. An optional KWStyle overwrite rules file can also been configured. The files on which to run the style checks must also be identified in the repository's '.gitattributes'. For example, *.h hooks.style *.cpp hooks.style Or, to only enable a subset of style hooks, *.h hooks.style=KWStyle *.cpp hooks.style=KWStyle,uncrustify Change-Id: Ia6b2d4136af3002eb0ec5d36f03c50df928917f4
-rwxr-xr-xpre-commit6
-rw-r--r--pre-commit-style252
2 files changed, 258 insertions, 0 deletions
diff --git a/pre-commit b/pre-commit
index bee9c90274..15a0151b00 100755
--- a/pre-commit
+++ b/pre-commit
@@ -247,3 +247,9 @@ while read src_mode dst_mode src_obj dst_obj status file; do
done
)
test -z "$bad" || die "$bad"
+
+#-----------------------------------------------------------------------------
+# Style hooks.
+. "$GIT_DIR/hooks/pre-commit-style"
+
+# vim: set filetype=sh tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab :
diff --git a/pre-commit-style b/pre-commit-style
new file mode 100644
index 0000000000..15af958fd0
--- /dev/null
+++ b/pre-commit-style
@@ -0,0 +1,252 @@
+#=============================================================================
+# Copyright 2010 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run uncrustify and KWStyle pre-commit hooks.
+#
+# 'git config' is used to enable the hooks and set their configuration files.
+# The repository .gitattributes must also enable the hooks on the targeted
+# files.
+
+do_KWStyle=$(git config --bool hooks.KWStyle) || do_KWStyle=false
+
+do_uncrustify=$(git config --bool hooks.uncrustify) || do_uncrustify=false
+
+#-----------------------------------------------------------------------------
+# Check if we want to run the style on a given file. Uses git attributes. If
+# the hook.style attribute is set, then all styles are executed. If the
+# hook.style attribute is set to a value, only the values given are executed.
+# Also, do not run the style check if there are unstaged changes in the file.
+# The first positional parameter is the file to check.
+# The second positional parameter is the style to check.
+# Returns 0 for execute, 1 for don't execute.
+run_style_on_file() {
+ # Do not run on submodule changes.
+ if git diff-index --cached $against -- "$1" | grep -q '^:...... 160000'; then
+ return 1
+ fi
+ if ! git diff-files --quiet -- "$1"; then
+ # A way to always allow skipping.
+ skip_unstaged=$(git config --bool hooks.styleSkipUnstaged) ||
+ skip_unstaged=false
+ file_sha=$(git diff-index --cached --abbrev=7 $against -- "$1" | \
+ awk '{print substr($3,1,9) substr($4,1,7)}')
+ if file_skip_unstaged=$(git config "hooks.$1.styleSkipUnstaged"); then
+ if test ",$file_skip_unstaged," = ",$file_sha," -o \
+ ",$file_skip_unstaged," = ",true,"; then
+ skip_unstaged=true
+ fi
+ fi
+
+ if $skip_unstaged; then
+ echo "The file '$1' contains unstaged stages. Skipping style \
+check '$2'."
+ else
+ die "Style check '$2' cannot run on '$1' with unstaged stages.
+
+Allow skipping the style check for this commit with
+
+ git config \"hooks.$1.styleSkipUnstaged\" $file_sha"
+ fi
+ return 1
+ fi
+ style=$(git check-attr hooks.style -- "$1" |
+ sed 's/^[^:]*: hooks.style: //')
+ case "$style" in
+ 'unset') return 1 ;;
+ 'set') return 0 ;;
+ 'unspecified') return 1 ;;
+ *) echo ",$style," | grep -iq ",$2," && return 0 ;;
+ esac
+ return 1
+}
+
+#-----------------------------------------------------------------------------
+# KWStyle.
+check_for_KWStyle() {
+ KWStyle_path=$(git config hooks.KWStyle.path) ||
+ KWStyle_path=$(which KWStyle) ||
+ die "KWStyle executable was not found.
+
+Please install KWStyle or set the executable location with
+
+ git config hooks.KWStyle.path /path/to/KWStyle
+
+See http://public.kitware.com/KWStyle/"
+
+ KWStyle_conf=$(git config hooks.KWStyle.conf)
+ if ! test -f "$KWStyle_conf"; then
+ die "The file '$KWStyle_conf' does not exist.
+
+Please run
+
+ git config hooks.KWStyle.conf path/to/KWStyle.conf.xml"
+ fi
+ KWStyle_overWriteRulesConf=$(git config hooks.KWStyle.overwriteRulesConf)
+ if test $? -eq 0 && ! test -f "$KWStyle_overWriteRulesConf"; then
+ die "The hooks.KWStyle.overwriteRulesConf file '$KWStyle_overWriteRulesConf' does not exist."
+ fi
+}
+
+run_KWStyle_on_file() {
+ if test -z "$KWStyle_overWriteRulesConf"; then
+ "$KWStyle_path" -v -xml "$KWStyle_conf" "$1"
+ else
+ "$KWStyle_path" -v -xml "$KWStyle_conf" -o "$KWStyle_overWriteRulesConf" "$1"
+ fi
+
+ if test $? -ne 0; then
+ cp -- "$1"{,.kws}
+ die "KWStyle check failed.
+
+Line numbers in the errors shown refer to the file:
+${1}.kws"
+ fi
+}
+
+run_KWStyle() {
+ git diff-index --cached --diff-filter=ACMR --name-only $against -- |
+ while read f; do
+ if run_style_on_file "$f" KWStyle; then
+ run_KWStyle_on_file "$f"
+ fi
+ done
+}
+
+#-----------------------------------------------------------------------------
+# uncrustify.
+check_for_uncrustify() {
+ uncrustify_path=$(git config hooks.uncrustify.path) ||
+ uncrustify_path=$(which uncrustify) ||
+ die "uncrustify executable was not found.
+
+Please install uncrustify or set the executable location with
+
+ git config hooks.uncrustify.path /path/to/uncrustify
+
+ See http://uncrustify.sourceforge.net/"
+
+ uncrustify_conf=$(git config hooks.uncrustify.conf)
+ if ! test -f "$uncrustify_conf"; then
+ die "The file '$uncrustify_conf' does not exist.
+
+Please run
+
+ git config hooks.uncrustify.conf path/to/uncrustify.conf"
+ fi
+}
+
+run_uncrustify_on_file() {
+ MERGED="$1"
+ if run_style_on_file "$MERGED" uncrustify; then
+ ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
+ BACKUP="./$MERGED.BACKUP.$ext"
+ LOCAL="./$MERGED.STAGED.$ext"
+ REMOTE="./$MERGED.UNCRUSTIFY.$ext"
+ NEW_MERGED="./$MERGED.NEW.$ext"
+ OLD_MERGED="$MERGED"
+
+ mv -- "$MERGED" "$BACKUP"
+ # We temporarily change MERGED because the file might already be open, and
+ # the text editor may complain.
+ MERGED="$NEW_MERGED"
+ cp -- "$BACKUP" "$MERGED"
+ cp -- "$BACKUP" "$LOCAL"
+
+ if ! "$uncrustify_path" -c "$uncrustify_conf" -f "$LOCAL" \
+ -o "$REMOTE" 2> /dev/null; then
+ mv -- "$BACKUP" "$OLD_MERGED"
+
+ if test "$merge_keep_temporaries" = "false"; then
+ rm -f -- "$LOCAL" "$REMOTE" "$BACKUP"
+ fi
+
+ die "error when running uncrustify on $OLD_MERGED"
+ fi
+
+ if test $(git hash-object -- "$LOCAL") != $(git hash-object -- "$REMOTE") &&
+ ! run_merge_tool "$merge_tool" "false" </dev/tty; then
+ mv -- "$BACKUP" "$OLD_MERGED"
+
+ if test "$merge_keep_temporaries" = "false"; then
+ rm -f -- "$LOCAL" "$REMOTE" "$BACKUP" "$NEW_MERGED"
+ fi
+
+ die "uncrustify merge of $OLD_MERGED failed"
+ fi
+
+ mv -- "$NEW_MERGED" "$OLD_MERGED"
+ MERGED="$OLD_MERGED"
+
+ if test "$merge_keep_backup" = "true"; then
+ mv -- "$BACKUP" "$MERGED.orig"
+ else
+ rm -- "$BACKUP"
+ fi
+
+ git add -- "$MERGED"
+ rm -f -- "$LOCAL" "$REMOTE" "$BACKUP"
+
+ fi # end if run uncrustify on file
+
+ if $do_KWStyle && run_style_on_file "$MERGED" KWStyle; then
+ run_KWStyle_on_file "$MERGED"
+ else
+ return 0
+ fi
+}
+
+run_uncrustify() {
+ $do_KWStyle && check_for_KWStyle
+
+ merge_tool=$(get_merge_tool "$merge_tool") || die "Merge tool not configured.
+
+Set the merge tool with
+
+ git config merge.tool <toolname>
+
+For more information, see
+
+ git help mergetool"
+ merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
+ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
+ git diff-index --cached --diff-filter=ACMR --name-only $against -- |
+ while read MERGED; do
+ run_uncrustify_on_file "$MERGED"
+ done # end for changed files
+}
+
+# Do not run during merge commits for now.
+if test -f "$GIT_DIR/MERGE_HEAD"; then
+ :
+elif $do_uncrustify; then
+ # We use git-mergetool settings to review the uncrustify changes.
+ TOOL_MODE=merge
+ . "$(git --exec-path)/git-mergetool--lib"
+ # Redefine check_unchanged because we do not need to check if the merge was
+ # successful.
+ check_unchanged() {
+ status=0
+ }
+ check_for_uncrustify
+ run_uncrustify
+# do_uncrustify will run KWStyle on the files incrementally so excessive
+# uncrustify merges do not have to occur.
+elif $do_KWStyle; then
+ check_for_KWStyle
+ run_KWStyle
+fi
+
+# vim: set filetype=sh tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab :