From be14d39a95771e40c3b7448b6488f7d164acce38 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 30 Apr 2015 16:15:09 +1200 Subject: First commit --- LICENSE | 22 ++++++++++++ README.markdown | 23 ++++++++++++ pre-commit | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 LICENSE create mode 100644 README.markdown create mode 100755 pre-commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6420c68 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Tom Ryder + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..ce4a3a2 --- /dev/null +++ b/README.markdown @@ -0,0 +1,23 @@ +Syntax checking Git hooks +========================= + +As used by Tom Ryder, because Michael Fincham asked. + +The `pre-commit` file goes in `.git/hooks` in your repository, and you make it +executable. You'll need `file(1)` and various other binaries in your PATH. + +This is nowhere near as tidy as it could be, but it correctly handles syntax +checking and linting of added or changed files only, without rescanning the +whole project. It does this with some byzantine Bash. It handles filenames with +funny characters (including newlines) correctly. + +I'll write some real documentation Laterâ„¢. + +License +------- + +Copyright (c) [Tom Ryder][1]. Distributed under [MIT License][2]. + +[1]: https://sanctum.geek.nz/ +[2]: http://opensource.org/licenses/MIT + diff --git a/pre-commit b/pre-commit new file mode 100755 index 0000000..31fb374 --- /dev/null +++ b/pre-commit @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# Tom Ryder + +# Start counting errors +declare -i errors + +# Read records supplied by git diff-index, null-terminated; we only want the +# sha1 object name of the staged file +while read -r -d '' _ _ _ sha1 _ ; do + + # git diff-files has a NULL both before and after the filename it prints, + # so we need to run read again to get the filename out to move on to the + # next record (this is a bit weird, but at least it works) + read -r -d '' filename _ + + # Skip the sha1 if it's empty (which is how diff-index shows deleted files + # or moves) + if [[ $sha1 != *[^0]* ]] ; then + continue + fi + + # Check Bash syntax + if [[ $filename == *.bash ]] || \ + git cat-file -p "$sha1" | file - | grep -iq 'Bourne-Again' ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with sh -n + if ! git cat-file -p "$sha1" | bash -n ; then + ((errors++)) + continue + fi + fi + + # Check shell script syntax + if [[ $filename == *.sh ]] || \ + git cat-file -p "$sha1" | file - | grep -iq 'POSIX shell' ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with sh -n + if ! git cat-file -p "$sha1" | sh -n ; then + ((errors++)) + continue + fi + fi + + # Check HTML syntax + if [[ $filename == *.html ]] || \ + git cat-file -p "$sha1" | file - | grep -iq html ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with HTML5 tidy(1) + if ! git cat-file -p "$sha1" | tidy -eq -utf8 ; then + ((errors++)) + continue + fi + fi + + # Check JS syntax and best practices + if [[ $filename == *.js ]] || \ + git cat-file -p "$sha1" | file - | grep -iq javascript ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with jslint (which sucks and is bad) + if ! jslint <(git cat-file -p "$sha1") ; then + ((errors++)) + continue + fi + fi + + # Check Perl syntax + if [[ $filename == *.pl ]] || \ + [[ $filename == *.pm ]] || \ + git cat-file -p "$sha1" | file - | grep -iq perl ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with perl -c; skip perlcritic if it doesn't pass + if ! git cat-file -p "$sha1" | perl -c ; then + ((errors++)) + continue + fi + + # Check the file with perlcritic --brutal + if ! git cat-file -p "$sha1" | perlcritic --brutal ; then + ((errors++)) + continue + fi + fi + + # Check PHP syntax + if [[ $filename == *.php ]] || \ + git cat-file -p "$sha1" | file - | grep -iq php ; then + printf 'Checking modified %s ... \n' "$filename" + + # Check the file with php -l + if ! git cat-file -p "$sha1" | php -l ; then + ((errors++)) + continue + fi + fi + +# Standard input for the while loop is here +done < <(git diff-index -z --cached HEAD) + +# Exit 0 if there were no errors, 1 if there were +exit "$((errors > 0))" + -- cgit v1.2.3