#!/bin/bash #---------------------------------*- sh -*------------------------------------- # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | # \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. # \\/ M anipulation | #------------------------------------------------------------------------------ # License # This file is part of OpenFOAM. # # OpenFOAM is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # OpenFOAM is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with OpenFOAM. If not, see . # # Script # pre-commit-hook # # Description # pre-commit hook for git. # Copy or link this file as ".git/hooks/pre-commit" # # Eg, # ( # cd $WM_PROJECT_DIR/.git/hooks && # ln -sf ../../bin/tools/pre-commit-hook pre-commit # ) # # Hook receives: empty # # Checks for # - illegal code, e.g. # - copyright is current, e.g. if present, contains XXX- # - columns greater than 80 for *.[CH] files # # Note # Using "git commit --no-verify" it is possible to override the hook. # # By supplying arguments to the hook, it can also be used to manually # test the specified files/directories for standards conformance. # #------------------------------------------------------------------------------ hookName="pre-commit" die() { echo '$hookName hook failure' 1>&2 echo '-----------------------' 1>&2 echo '' 1>&2 echo "$@" 1>&2 echo '' 1>&2 exit 1 } #----------------------------------------------------------------------------- # Check content that will be added by this commit. if git rev-parse --verify HEAD > /dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # called manually with arguments for the files/directories to be tested? if [ "$#" -gt 0 ] then case "$1" in -h | -help) die "interactive usage: supply list of files/directories to check" ;; esac # obtain list of all specified files/directories fileList=$(git ls-files -- $@ 2>/dev/null) else # list of all files to be committed fileList=$(git diff-index --cached --name-only $against --) fi # # no files changed: can skip all the checks # this usage can correspond to a 'git commit --amend' # [ -n "$fileList" ] || exit 0 unset badFiles # join list of files with this amount of space Indent=" " # # report bad files and die if there are any # dieOnBadFiles() { if [ -n "$badFiles" ] then echo '$hookName hook failure' 1>&2 echo '-----------------------' 1>&2 echo "$@" 1>&2 echo '' 1>&2 echo "File(s):" 1>&2 echo "$badFiles" 1>&2 echo '' 1>&2 exit 1 fi } # # qualify 'git grep' to check cached value or from a specific commit # gitScope() { if [ "$#" -gt 0 ] then echo "$1:" else echo "--cached -- " fi } # # check for bad strings, characters, etc # checkIllegalCode() { echo "$hookName: check bad strings/characters etc ..." 1>&2 reBad="(N""abla|"$'\t'")" msgBad="N""abla or " scope=$(gitScope $@) badFiles=$( for f in $fileList do case "$f" in # exclude potential makefiles (wmake/[Mm]akefile* | wmake/rules/*) ;; (*) # parse line numbers from grep output: # : contents lines=$(git grep -E -hn -e "$reBad" $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" ;; esac done ) dieOnBadFiles "Remove/correct bad '$msgBad' references" } # # check that OpenCFD copyright is current # checkCopyright() { year=$(date +%Y) echo "$hookName: check copyright ..." 1>&2 scope=$(gitScope $@) badFiles=$( for f in $fileList do # NB: need to have OpenCFD on a separate line to prevent # this check being caught by itself! # # parse line numbers from grep output: # : contents # lines=$(git grep -F -hn -e Copyright \ --and -e OpenCFD \ --and --not -e "$year" \ $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" done ) dieOnBadFiles "Update copyright year, e.g. XXXX-$year" } # # limit line length to 80-columns # checkLineLength() { echo "$hookName: check line lengths ..." 1>&2 scope=$(gitScope $@) badFiles=$( for f in $fileList do # limit to *.[CH] files case "$f" in (*.[CH]) # parse line numbers from grep output: # : contents lines=$(git grep -hn -e '^.\{81,\}' $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" ;; esac done ) dieOnBadFiles "Limit code to 80 columns before pushing" } # # limit line length to 80-columns, except C++ comment lines # checkLineLengthNonComments() { echo "$hookName: check line lengths ..." 1>&2 scope=$(gitScope $@) badFiles=$( for f in $fileList do # limit to *.[CH] files case "$f" in (*.[CH]) # parse line numbers from grep output: # : contents lines=$(git grep -hn -e '^.\{81,\}' \ --and --not -e '^ *//' \ $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" ;; esac done ) dieOnBadFiles "Limit code to 80 columns before pushing" } # # limit line length to 80-columns, except #directive lines # checkLineLengthNonDirective() { echo "$hookName: check line lengths ..." 1>&2 scope=$(gitScope $@) badFiles=$( for f in $fileList do # limit to *.[CH] files case "$f" in (*.[CH]) # parse line numbers from grep output: # : contents lines=$(git grep -hn -e '^.\{81,\}' \ --and --not -e '^ *#' \ $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" ;; esac done ) dieOnBadFiles "Limit code to 80 columns before pushing" } #------------------------------------------------------------------------------ # Main code : do all checks # # builtin whitespace check to avoid trailing space, including CR-LF endings bad=$(git diff-index --cached --check $against --) || die "$bad" # check for illegal code, e.g. , etc checkIllegalCode # ensure OpenCFD copyright contains correct year checkCopyright # ensure code conforms to 80 columns max checkLineLengthNonDirective exit 0 #------------------------------------------------------------------------------