summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2010-05-20 11:42:57 -0400
committerBrad King <brad.king@kitware.com>2010-05-20 11:42:57 -0400
commit7827726e88c2a4cacdda5cd09e6907925cd30f2f (patch)
tree024b3514c44c8f2d9aa3c7aafa32f43f50d33235
parent7cd6238240d440f0a69a0f4e8eecc3b2a23a1973 (diff)
downloadcmake-7827726e88c2a4cacdda5cd09e6907925cd30f2f.tar.gz
pre-commit: Check file modes
Check new files and files whose mode changes to verify that each file mode matches the content of the file. The mode of a file must be executable if and only if the file looks executable (name ends in a Windows executable extension or content starts with a shebang line).
-rwxr-xr-xpre-commit39
1 files changed, 39 insertions, 0 deletions
diff --git a/pre-commit b/pre-commit
index 14e03ab593..00dc8486ef 100755
--- a/pre-commit
+++ b/pre-commit
@@ -49,9 +49,11 @@ if test "$(git diff --cached --name-only --diff-filter=A -z $against |
'"$(git diff --cached --name-only --diff-filter=A $against)"
fi
+#-----------------------------------------------------------------------------
# Builtin whitespace checks.
bad=$(git diff-index --check --cached $against --) || die "$bad"
+#-----------------------------------------------------------------------------
# Reject leading TABs.
check_tab() {
git diff-index -p --cached $against -- "$1" |
@@ -78,3 +80,40 @@ done)
test -z "$bad" || die 'Leading TABs added in
'"$bad"'
Convert them to spaces (2 per TAB) before commit.'
+
+#-----------------------------------------------------------------------------
+# Check file modes.
+looks_executable() {
+ case "$1" in
+ *.bat) return 0 ;;
+ *.cmd) return 0 ;;
+ *.exe) return 0 ;;
+ *.com) return 0 ;;
+ esac
+ git cat-file blob "$2" | head -1 | grep "^#!/" > /dev/null
+}
+mode_not_exe () {
+ echo "The file '$file' has looks executable but does not have an executable mode."
+}
+mode_bad_exe () {
+ echo "The file '$file' has executable mode but does not look executable."
+}
+mode_non_file () {
+ echo "The path '$file' has a non-file mode."
+}
+check_mode() {
+ case "$dst_mode" in
+ 100755) looks_executable "$file" "$dst_obj" || mode_bad_exe ;;
+ 100644) looks_executable "$file" "$dst_obj" && mode_not_exe ;;
+ 160000) ;;
+ *) mode_non_file ;;
+ esac
+}
+bad=$(git diff-index --cached $against -- |
+sed -n '/^:[^:]/ {s/^://;p;}' |
+while read src_mode dst_mode src_obj dst_obj status file; do
+ if test "$src_mode" != "$dst_mode" -a "$dst_mode" != "000000"; then
+ check_mode
+ fi
+done)
+test -z "$bad" || die "$bad"