diff --git a/bin/tools/HookFunctions b/bin/tools/HookFunctions new file mode 100755 index 000000000..592194fc1 --- /dev/null +++ b/bin/tools/HookFunctions @@ -0,0 +1,354 @@ +#---------------------------------*- sh -*------------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation +# \\/ 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 +# HookFunctions +# +# Description +# Functions for automatically checking code pre commit and receive +# +#------------------------------------------------------------------------------ + +headerSeparator="-----------------------------------" +echoIndent=" " + +#----------------------------------------------------------------------------- + + +# +# report failure and exit +# +die() +{ + echo "$hookName hook failure" 1>&2 + echo $headerSeparator 1>&2 + echo '' 1>&2 + echo "$@" 1>&2 + echo '' 1>&2 + exit 1 +} + + +# +# report failure, listing bad files and exit +# +dieOnBadFiles() +{ + if [ -n "$badFiles" ] + then + echo "$hookName hook failure" 1>&2 + echo $headerSeparator 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="("$'\t'")" + msgBad="" + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + case "$f" in + # exclude potential makefiles + (*[Mm]akefile* | wmake/rules/* | *.f* | *.v[cf]proj | *.pdf | *.png | *.html | *.gif | *.css | *.gz) + ;; + (*) + fileType=`file -b $f` + if [ "$fileType" != "data" ] + then + # parse line numbers from grep output: + # : contents + lines=$(git grep -E -hn -e "$reBad" $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$echoIndent$f -- lines: $lines" + fi + ;; + esac + done + ) + + dieOnBadFiles "Remove/correct bad '$msgBad' references" +} + + +# +# 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 "$echoIndent$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 "$echoIndent$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 "$echoIndent$f -- lines: $lines" + ;; + esac + done + ) + + dieOnBadFiles "Limit code to 80 columns before pushing" +} + + +# +# check for non-standard code patterns +# +checkNonStandardCodePatterns() +{ + echo "$hookName: checking for non-standard code ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # limit to *.[CH] files + case "$f" in + (*.[CH]) + # Directly report the incorrect markers + git grep -n --color -e '> >' \ + --or -w -e 'NULL' \ + $scope"$f" + ;; + esac + done + ) + + dieOnBadFiles "$(cat< > + + which instead should be: + + List> + + 2. The use of the 'NULL' macro should be replaced by 'nullptr' + +$headerSeparator +MESSAGE + )" +} + + +# +# check that header files respect the policy of file names matching the +# #ifndef/#define bounds +# +checkHeaderIfndefNames() +{ + echo "$hookName: check header files #ifndef/#define names ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # limit to *.H files + case "$f" in + (*.H) + fileName=$(basename $f) + correctMangledName=$(basename $f | sed 's=\.=_=') + + if git grep -q -e "#ifndef.*_H" $scope"$f" && ! git grep -q -e "#ifndef[ ]\+$correctMangledName" $scope"$f" + then + echo "Updated #ifndef/#define for: $f" 1>&2 + echo $f + + currentMangled=$(grep "#ifndef.*_H" $f | sed 's=#ifndef\s*==') + + sed -i -e 's='$currentMangled'='$correctMangledName'=' $f + fi + ;; + esac + done + ) + + dieOnBadFiles "Some header files were automatically updated to respect #ifndef naming convention; Please check these before pushing" +} + + +# +# check that OpenFOAM Foundation copyright is current +# +checkCopyright() +{ + echo "$hookName: check copyright ..." 1>&2 + + scope=$(gitScope $@) + year=$(date +%Y) + + badFiles=$( + for f in $fileList + do + startYear=$( + git grep -h -e "Copyright.*OpenFOAM" $scope"$f" | \ + head -n 1 | \ + sed 's/[^0-9]*\([0-9]*\).*/\1/g' + ) + endYear=$( + git grep -h -e "Copyright.*-.*OpenFOAM" $scope"$f" | \ + head -n 1 | \ + sed 's/[^-]*-\([0-9]*\).*/\1/g' + ) + + if [ "$startYear" != "" ] + then + if [ "$endYear" != "" ] + then + # Date is of type 2011-2012 OpenFOAM Foundation + if [ "$year" != "$endYear" ] + then + echo "Updated copyright for: $f" 1>&2 + echo "$f" + sed -i -e "s/$startYear-$endYear OpenFOAM/$startYear-$year OpenFOAM/g" $f + fi + else + # Date is of type 2011 OpenFOAM Foundation + if [ "$year" != "$startYear" ] + then + echo "$f" + echo "Updated copyright for: $f" 1>&2 + sed -i -e "s/$startYear OpenFOAM/$startYear-$year OpenFOAM/g" $f + fi + fi + fi + done + ) + + dieOnBadFiles "Some copyright dates were automatically updated; Please check these before pushing" +} + + +#------------------------------------------------------------------------------ diff --git a/bin/tools/pre-commit-hook b/bin/tools/pre-commit-hook index 4d6f5c42f..055c913e5 100755 --- a/bin/tools/pre-commit-hook +++ b/bin/tools/pre-commit-hook @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation +# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -38,8 +38,12 @@ # Hook receives: empty # # Checks for +# - trailing whitespace and non-standard line endings # - illegal code, e.g. # - columns greater than 80 for *.[CH] files +# - non-standard code patterns +# - missmatched header #ifndef/#define names +# - incorrect copyright statements # # Note # Using "git commit --no-verify" it is possible to override the hook. @@ -49,351 +53,51 @@ # #------------------------------------------------------------------------------ -hookName="pre-commit" -headerSeparator="-----------------------------------" +. bin/tools/HookFunctions || exit 1 + +hookName="pre-commit" -die() -{ - echo "$hookName hook failure" 1>&2 - echo $headerSeparator 1>&2 - echo '' 1>&2 - echo "$@" 1>&2 - echo '' 1>&2 - exit 1 -} #----------------------------------------------------------------------------- -# Check content that will be added by this commit. +# Check content that will be added by this commit +# +# Clear +unset fileList +unset badFiles + +# Get the commit to test against if git rev-parse --verify HEAD > /dev/null 2>&1 then against=HEAD else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + # Git's "empty" object + against=$(git hash-object -t tree /dev/null) + fi -# called manually with arguments for the files/directories to be tested? +# Get the list of files to check if [ "$#" -gt 0 ] then + # Called with arguments for the files/directories to be tested 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 + # Called with out arguments to test staged changes 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' -# +# If no files have changed then the checks are not needed. 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 $headerSeparator 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="("$'\t'")" - msgBad="" - - scope=$(gitScope $@) - - badFiles=$( - for f in $fileList - do - case "$f" in - # exclude potential makefiles - (*[Mm]akefile* | wmake/rules/* | *.f* | *.v[cf]proj | *.pdf | *.png | *.html | *.gif | *.css | *.gz) - ;; - (*) - fileType=`file -b $f` - if [ "$fileType" != "data" ] - then - # 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" - fi - ;; - esac - done - ) - - dieOnBadFiles "Remove/correct bad '$msgBad' references" -} - - -# -# 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" -} - - -# -# check for non-standard code patterns -# -checkNonStandardCodePatterns() -{ - echo "$hookName: checking for non-standard code ..." 1>&2 - - scope=$(gitScope $@) - - badFiles=$( - for f in $fileList - do - # limit to *.[CH] files - case "$f" in - (*.[CH]) - # Directly report the incorrect markers - git grep -n --color -e '> >' \ - --or -w -e 'NULL' \ - $scope"$f" - ;; - esac - done - ) - - dieOnBadFiles "$(cat< > - - which instead should be: - - List> - - 2. The use of the 'NULL' macro should be replaced by 'nullptr' - -$headerSeparator -MESSAGE - )" -} - - -# -# check that header files respect the policy of file names matching the -# #ifndef/#define bounds -# -checkHeaderIfndefNames() -{ - echo "$hookName: check header files #ifndef/#define names ..." 1>&2 - - badFiles=$( - for f in $fileList - do - # limit to *.H files - case "$f" in - (*.H) - fileName=$(basename $f) - correctMangledName=$(basename $f | sed 's=\.=_=') - - if grep -q "#ifndef.*_H" $f - then - if ! grep "#ifndef.*_H" $f | grep -q $correctMangledName - then - echo "$(grep -H "#ifndef" $f | sed 's=#=\n\t#=') --> $correctMangledName" - - currentMangled=$(grep "#ifndef.*_H" $f | sed 's=#ifndef\s*==') - - sed -i -e 's='$currentMangled'='$correctMangledName'=' $f - fi - fi - ;; - esac - done - ) - - dieOnBadFiles "Some header files were automatically updated to respect #ifndef naming convention; Please check these before pushing" -} - - -# -# check that OpenFOAM Foundation copyright is current -# -checkCopyright() -{ - year=$(date +%Y) - echo "$hookName: check copyright ..." 1>&2 - - badFiles=$( - for f in $fileList - do - startYear=`grep -m 1 "Copyright.*OpenFOAM" $f | sed 's/[^0-9]*\([0-9]*\).*/\1/g'` - endYear=`grep -m 1 "Copyright.*-.*OpenFOAM" $f | sed 's/[^-]*-\([0-9]*\).*/\1/g'` - #echo "startYear=$startYear endYear=$endYear" - if [ "$startYear" != "" ] - then - if [ "$endYear" != "" ] - then - # Date is of type 2011-2012 OpenFOAM Foundation - if [ "$year" != "$endYear" ] - then - echo "Updated copyright for: $f" 1>&2 - echo "$f" - sed -i -e "s/$startYear-$endYear OpenFOAM/$startYear-$year OpenFOAM/g" $f - fi - else - # Date is of type 2011 OpenFOAM Foundation - if [ "$year" != "$startYear" ] - then - echo "$f" - echo "Updated copyright for: $f" 1>&2 - sed -i -e "s/$startYear OpenFOAM/$startYear-$year OpenFOAM/g" $f - fi - fi - fi - done - ) - - dieOnBadFiles "Some copyright dates were automatically updated; Please check these before pushing" -} - - #------------------------------------------------------------------------------ -# Main code : do all checks +# Main code. Do all checks. # # builtin whitespace check to avoid trailing space, including CR-LF endings @@ -411,7 +115,9 @@ checkNonStandardCodePatterns # check if #ifndef/#define bounds are named correctly checkHeaderIfndefNames +# check copyright checkCopyright exit 0 + #------------------------------------------------------------------------------ diff --git a/bin/tools/pre-receive-hook b/bin/tools/pre-receive-hook index 4a5a48096..3f42b187c 100755 --- a/bin/tools/pre-receive-hook +++ b/bin/tools/pre-receive-hook @@ -3,7 +3,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | -# \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation +# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -42,192 +42,14 @@ # - columns greater than 80 for *.[CH] files # #------------------------------------------------------------------------------ + +. bin/tools/HookFunctions || exit 1 + hookName="pre-receive" -die() -{ - echo "$hookName hook failure" 1>&2 - echo '-----------------------------------' 1>&2 - echo '' 1>&2 - echo "$@" 1>&2 - echo '' 1>&2 - exit 1 -} - -#----------------------------------------------------------------------------- - -unset fileList -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="("$'\t'"|"$'\r\n'")" - msgBad=" or DOS-line-endings" - - scope=$(gitScope $@) - - badFiles=$( - for f in $fileList - do - case "$f" in - # exclude potential makefiles - (*[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" -} - - -# -# 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 +# Main code. Do all checks. # while read oldSHA1 newSHA1 refName @@ -236,20 +58,18 @@ do if [ "$newSHA1" = 0 ] then - # ref to be deleted + # Ref to be deleted continue elif [ "$oldSHA1" = 0 ] then - # ref to be created + # Ref to be created rawFileList=$(git diff-tree --root $newSHA1) else - # normal changes + # Normal changes rawFileList=$(git diff --name-only $oldSHA1..$newSHA1) fi - # - # no files changed: can skip all the checks - # + # No files have changed, so the checks are not necessary [ -n "$rawFileList" ] || continue fileList=$( @@ -267,6 +87,6 @@ do done - exit 0 + #------------------------------------------------------------------------------