From 0ce996ffd4481cbaefe9483293aa67bf5c58d1b7 Mon Sep 17 00:00:00 2001 From: Will Bainbridge Date: Wed, 13 Mar 2019 12:40:25 +0000 Subject: [PATCH] hooks: Refactor The hook functions now all work in terms of local variables and argument passing. They return error codes rather than exiting. Fixing issues (updating copyright and correcting ifndef/define names) is now optional. The "interactive" aspect of the pre-recieve hook has been removed and placed into a new interactive-hook script that can be used for checking without commiting. The pre-recieve-hook has been updated to include all the newer checking added to pre-commit-hook. --- bin/tools/HookFunctions | 692 ++++++++++++++++++++----------------- bin/tools/interactive-hook | 92 +++++ bin/tools/pre-commit-hook | 84 +---- bin/tools/pre-receive-hook | 60 ++-- 4 files changed, 501 insertions(+), 427 deletions(-) create mode 100755 bin/tools/interactive-hook diff --git a/bin/tools/HookFunctions b/bin/tools/HookFunctions index 9a8d2afbe9..e236ec516a 100644 --- a/bin/tools/HookFunctions +++ b/bin/tools/HookFunctions @@ -2,7 +2,7 @@ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | Website: https://openfoam.org -# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation +# \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -29,11 +29,9 @@ # #------------------------------------------------------------------------------ -headerSeparator="-----------------------------------" - -echoIndent=" " - -sourceBanner="(\ +if [ -z "$sourceBanner" ] +then + sourceBanner="(\ /\*---------------------------------------------------------------------------\*\\\\|\ /\*--------------------------------\*- C\+\+ -\*----------------------------------\*\\\\|\ /\*---------------------------------\*- C -\*-----------------------------------\*\\\\) @@ -61,8 +59,11 @@ License (.| )*? \\\\\*---------------------------------------------------------------------------\*/" +fi -scriptBanner="(\ +if [ -z "$scriptBanner" ] +then + scriptBanner="(\ #------------------------------------------------------------------------------|\ #---------------------------------\*- sh -\*-------------------------------------|\ #----------------------------------\*-sh-\*--------------------------------------|\ @@ -91,8 +92,11 @@ scriptBanner="(\ (.| )*? #------------------------------------------------------------------------------" +fi -dictBanner="(\ +if [ -z "$dictBanner" ] +then + dictBanner="(\ /\*---------------------------------------------------------------------------\*\\\\|\ /\*--------------------------------\*- C\+\+ -\*----------------------------------\*\\\\) ========= \| @@ -102,374 +106,350 @@ dictBanner="(\ \\\\\\\\/ M anipulation \|(.| )*? \\\\\*---------------------------------------------------------------------------\*/" +fi #----------------------------------------------------------------------------- -# -# report failure and exit -# -die() +gitIsRevision() # commit { - echo "$hookName hook failure" 1>&2 - echo $headerSeparator 1>&2 - echo '' 1>&2 - echo "$@" 1>&2 - echo '' 1>&2 - exit 1 + git rev-parse --verify "$1" > /dev/null 2>&1 + return $? } -# -# report failure, listing bad files and exit -# -dieOnBadFiles() +scopeGit() # scope, cacheScope { - if [ -n "$badFiles" ] + if [ "$1" == "--cached" ] 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 + echo "$2" + elif gitIsRevision "$1" + then + echo "$1:" + else + echo "$(basename "$0"): $1 is not a valid scope" exit 1 fi } -# -# qualify 'git grep' to check cached value or from a specific commit -# -gitScopeGrep() +scopeGitGrep() # scope { - if [ "$#" -gt 0 ] + scopeGit "$1" "--cached -- " +} + + +scopeGitShow() # scope +{ + scopeGit "$1" ":" +} + + +reportStart() # startMessage +{ + echo -n "$1 ... " 1>&2 +} + + +reportEnd() # failMessage, errorCount, errorMessages... +{ + local failMessage errorCount + + failMessage=$1 + shift + errorCount=$1 + shift + if [ "$errorCount" -eq 0 ] then - echo "$1:" + echo PASSED 1>&2 else - echo "--cached -- " + echo "FAILED with $errorCount errors:" 1>&2 + echo "$failMessage" | sed "s/^/ /g" 1>&2 + for errorMessage in "$@" + do + echo "$errorMessage" | sed "s/^/ /g" 1>&2 + done fi } -# -# qualify 'git show' to check cached value or from a specific commit -# -gitScopeShow() +checkPattern() # scope, pattern, include, exclude, files... { - if [ "$#" -gt 0 ] + local scope pattern include exclude lines errorCount=0 + + scope=$(scopeGitGrep "$1") + shift + pattern="$1" + shift + include="$1" + shift + exclude="$1" + shift + + # Loop files, accumulating errors + for file in "$@" + do + case "$file" in + ($exclude) + ;; + ($include) + if [ "$(file -b "$file")" != "data" ] + then + lines=$( \ + eval git grep -E -hn $pattern $scope"$file" \ + | sed -e "s/:.*//" \ + | tr "\n" " " \ + ) + if [ -n "$lines" ] + then + echo "$file: Lines $lines" + ((++errorCount)) + fi + fi + ;; + esac + done + + return $errorCount +} + + +checkTabs() # scope, files... +{ + reportStart "Check for tabs" + + local scope pattern include exclude errorCount errorMessages + + scope=$1 + shift + pattern="-e $'\t'" + include="*" + exclude="*[Mm]akefile* | wmake/rules/* | bin/tools/gtagsrc | *.f* | *.v[cf]proj | *.pdf | *.png | *.html | *.gif | *.css | *.gz" + + errorMessages="$(checkPattern "$scope" "$pattern" "$include" "$exclude" "$@")" + errorCount=$? + + reportEnd "Remove characters from the following files:" $errorCount "$errorMessages" + return $errorCount +} + + +checkLineEnds() # scope, files... +{ + reportStart "Check for bad line endings" + + local scope pattern include exclude errorCount errorMessages + + scope=$1 + shift + pattern="-e \"[ ]+$\" --or -e $'\r'" + include="*" + exclude="*.md" + + errorMessages="$(checkPattern "$scope" "$pattern" "$include" "$exclude" "$@")" + errorCount=$? + + reportEnd "Remove trailing whitespace and characters in the following files:" $errorCount "$errorMessages" + return $errorCount +} + + +checkLineLength() # scope, files... +{ + reportStart "Check line lengths" + + local scope pattern include exclude errorCount errorMessages + + scope=$1 + shift + pattern="-e \"^.{81,}\" --and --not -e \"^ *#\"" + include="*.[CH]" + exclude="" + + errorMessages="$(checkPattern "$scope" "$pattern" "$include" "$exclude" "$@")" + errorCount=$? + + reportEnd "Limit lines to 80 characters in the following files:" $errorCount "$errorMessages" + return $errorCount +} + + +checkNonStandardCode() # scope, files... +{ + reportStart "Check for non-standard code" + + local scope pattern include exclude errorCount errorMessages + + scope=$1 + shift + pattern="-e \"> >\" --or -e \"NULL\"" + include="*.[CH]" + exclude="" + + errorMessages="$(checkPattern "$scope" "$pattern" "$include" "$exclude" "$@")" + errorCount=$? + + reportEnd "$(cat << EOF +The following is considerd non-standard code: + + 1. Spaced ending of multi-level template parameters. For example, + + List > + + should instead be written: + + List> + + 2. The 'NULL' macro. This should be replaced by 'nullptr'. + +Remove these patterns from the following files: +EOF +)" $errorCount "$errorMessages" + + return $errorCount +} + + +checkHeaderIfndefNames() # scope, fix, files... +{ + reportStart "Check header file #ifndef/#define names" + + local scopeGrep fix correctDefine currentDefine failMessage errorCount=0 errorMessages=() + + scopeGrep=$(scopeGitGrep "$1") + shift + fix=$1 + shift + + for file in "$@" + do + case "$file" in + (*.H) + correctDefine=$(basename "$file" | sed 's/\./_/') + + if git grep -q -e "#ifndef.*_H" --and --not -e "#ifndef.*[ _]$correctDefine" $scopeGrep"$file" + then + ((++errorCount)) + errorMessages+=("$file") + + currentDefine=$(grep "#ifndef.*_H" "$file" | sed 's/#ifndef\s*//') + + if $fix + then + sed -i -e "s/$currentDefine/$correctDefine/" "$file" + fi + fi + ;; + esac + done + + if $fix then - echo "$1:" + failMessage="The following files have been automatically updated so that the +#ifndef/#define statements match the file name. Check and re-add them +before pushing:" else - echo ":" + failMessage=" +Revise the following files so that the #ifndef/#define statements match +the file name:" fi + + reportEnd "$failMessage" $errorCount "${errorMessages[@]}" + return $errorCount } -# -# check for bad strings, characters, etc -# -checkIllegalCode() +checkBanner() # scope, files... { - echo "$hookName: check bad strings/characters etc ..." 1>&2 + reportStart "Check banners" - reBad="("$'\t'")" - msgBad="" + local scopeGrep scopeShow fileName fileExtension errorCount=0 errorMessages=() - scope=$(gitScopeGrep $@) + scopeGrep=$(scopeGitGrep "$1") + scopeShow=$(scopeGitShow "$1") + shift - badFiles=$( - for f in $fileList + for file in "$@" do - case "$f" in - # exclude potential makefiles - (*[Mm]akefile* | wmake/rules/* | bin/tools/gtagsrc | *.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=$(gitScopeGrep $@) - - 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=$(gitScopeGrep $@) - - 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=$(gitScopeGrep $@) - - 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=$(gitScopeGrep $@) - - 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=$(gitScopeGrep $@) - - 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 the banners are correctly formatted -# -checkBanner() -{ - echo "$hookName: check banner ..." 1>&2 - - scopeGrep=$(gitScopeGrep $@) - scopeShow=$(gitScopeShow $@) - - badFiles=$( - for f in $fileList - do - fFile="${f##*/}" - [[ "$fFile" = *.* ]] && fExt="${fFile##*.}" || fExt="" + fileName=$(basename "$file") + fileExtension=${fileName##*.} # Skip links - if [ -h "$f" ] + if [ -h "$file" ] then : # Copyrighted source and script files - elif git grep -q -e "Copyright (C) [0-9-]\+ OpenFOAM Foundation" $scopeGrep"$f" + elif git grep -q -e "Copyright (C) [0-9-]\+ OpenFOAM Foundation" $scopeGrep"$file" then - case "$fExt" in - (c|C|Cver|cxx|dox|H|h|l|L) - if ! git show $scopeShow"$f" | pcregrep -q -M "$sourceBanner" - then - echo $f - fi - ;; - (''|awk|csh|gnuplot|sed|sh) - if ! git show $scopeShow"$f" | pcregrep -q -M "$scriptBanner" - then - echo $f - fi - ;; - (*) - # Unknown extension - echo "Banner not checked for copyrighted file $f" 1>&2 - ;; + case "$fileExtension" in + (c|C|Cver|cxx|dox|H|h|l|L) + if ! git show $scopeShow"$file" | pcregrep -q -M "$sourceBanner" + then + ((++errorCount)) + errorMessages+=("$file") + fi + ;; + (''|awk|csh|gnuplot|sed|sh) + if ! git show $scopeShow"$file" | pcregrep -q -M "$scriptBanner" + then + ((++errorCount)) + errorMessages+=("$file") + fi + ;; + (*) + : + #((++errorCount)) + #errorMessages+=("$file: Unknown extension") + ;; esac # Versioned case files - elif git grep -q -e "Version: \(dev\|[0-9.]+\)" $scopeGrep"$f" + elif git grep -q -e "Version: \(dev\|[0-9.]+\)" $scopeGrep"$file" then - if ! git show $scopeShow"$f" | pcregrep -q -M "$dictBanner" + if ! git show $scopeShow"$file" | pcregrep -q -M "$dictBanner" then - echo $f + ((++errorCount)) + errorMessages+=("$file") fi # Unknown files - elif git grep -q -e "OpenFOAM: The Open Source CFD Toolbox" $scopeGrep"$f" + elif git grep -q -e "OpenFOAM: The Open Source CFD Toolbox" $scopeGrep"$file" then - : #echo "Banner not checked for file $f" 1>&2 + : + #((++errorCount)) + #errorMessages+=("$file: Missing copyright or version") fi done - ) - dieOnBadFiles "Fix banner formatting before pushing" + reportEnd "Correct the banner formating in the following files:" $errorCount "${errorMessages[@]}" + return $errorCount } -# -# check that OpenFOAM Foundation copyright is current -# -checkCopyright() +checkCopyright() # scope, fix, files... { - echo "$hookName: check copyright ..." 1>&2 + reportStart "Check copyright" - scope=$(gitScopeGrep $@) + local scopeGrep fix year startYear endYear errorCount=0 errorMessages=() failMessage + + scopeGrep=$(scopeGitGrep "$1") + shift + fix=$1 + shift year=$(date +%Y) - badFiles=$( - for f in $fileList + for file in "$@" 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' - ) + startYear=$( \ + git grep -h -e "Copyright.*OpenFOAM" $scopeGrep"$file" \ + | head -n 1 \ + | sed 's/[^0-9]*\([0-9]*\).*/\1/g' + ) + endYear=$( \ + git grep -h -e "Copyright.*-.*OpenFOAM" $scopeGrep"$file" \ + | head -n 1 \ + | sed 's/[^-]*-\([0-9]*\).*/\1/g' + ) if [ "$startYear" != "" ] then @@ -478,25 +458,89 @@ checkCopyright() # 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 + ((++errorCount)) + errorMessages+=("$file") + if $fix + then + sed -i -e "s/$startYear-$endYear OpenFOAM/$startYear-$year OpenFOAM/g" "$file" + fi 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 + ((++errorCount)) + errorMessages+=("$file") + if $fix + then + sed -i -e "s/$startYear OpenFOAM/$startYear-$year OpenFOAM/g" "$file" + fi fi fi fi done - ) - dieOnBadFiles "Some copyright dates were automatically updated; Please check these before pushing" + if $fix + then + failMessage="The following files have had their copyright dates automatically +updated. Check and re-add them before pushing:" + else + failMessage="Update the copyright dates in the following files:" + fi + + reportEnd "$failMessage" $errorCount "${errorMessages[@]}" + return $errorCount + } +checkAllNoCopyright() # scope, fix, files... +{ + local scope fix returnCode=0 + + scope="$1" + shift + fix="$1" + shift + + # Check for tabs + checkTabs "$scope" "$@" || returnCode=1 + + # Check line endings + checkLineEnds "$scope" "$@" || returnCode=1 + + # Ensure code line lengths do not exceed 80 columns + checkLineLength "$scope" "$@" || returnCode=1 + + # Check for non-standard code patterns + checkNonStandardCode "$scope" "$@" || returnCode=1 + + # Check if #ifndef/#define bounds are named correctly + checkHeaderIfndefNames "$scope" "$fix" "$@" || returnCode=1 + + # Check banner + checkBanner "$scope" "$@" || returnCode=1 + + return $returnCode +} + + +checkAll() # scope, fix, files... +{ + local scope fix returnCode=0 + + scope="$1" + shift + fix="$1" + shift + + # Check all except copyright + checkAllNoCopyright "$scope" "$fix" "$@" || returnCode=1 + + # Check copyright + checkCopyright "$scope" "$fix" "$@" || returnCode=1 + + return $returnCode +} + #------------------------------------------------------------------------------ diff --git a/bin/tools/interactive-hook b/bin/tools/interactive-hook new file mode 100755 index 0000000000..12ef79f2e6 --- /dev/null +++ b/bin/tools/interactive-hook @@ -0,0 +1,92 @@ +#!/bin/bash +#---------------------------------*- sh -*------------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | Website: https://openfoam.org +# \\ / A nd | Copyright (C) 2019 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 +# interactive-hook +# +# Description +# Script to interactively run the checks performed by the pre-commit and +# pre-recieve hooks. +# +#------------------------------------------------------------------------------ + +. $WM_PROJECT_DIR/bin/tools/HookFunctions || exit 1 + +usage() { + cat << EOF + Usage: ${0##*/} [OPTION] ... +Options: + -h, -help print this usage + -s, -scope which commit to check, or "--cached" for staged changes + -f, -fix additionally fix files where possible + -c, -copyright also check that the copyright date is up to date +EOF +} + +error() { + usage 1>&2 + exit 1 +} + +scope=HEAD +fix=false +copyright=false +paths=() +while [ "$#" -gt 0 ] +do + case "$1" in + (-h | -help) + usage && exit 0 + ;; + (-s | -scope) + scope="$2" + shift 2 + ;; + (-f | -fix) + fix=true + shift + ;; + (-c | -copyright) + copyright=true + shift + ;; + -*) + error + ;; + (*) + paths+=("$1") + shift + ;; + esac +done + +[ "${#paths[@]}" -gt 0 ] || paths=(".") + +readarray -t files < <(git ls-files -- "${paths[@]}") + +$copyright && check=checkAll || check=checkAllNoCopyright + +$check "$scope" $fix "${files[@]}" && exit 0 || exit 1 + +#------------------------------------------------------------------------------ diff --git a/bin/tools/pre-commit-hook b/bin/tools/pre-commit-hook index 2ed5166c4d..25e8ab8602 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 | Website: https://openfoam.org -# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation +# \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -26,100 +26,46 @@ # pre-commit-hook # # Description -# pre-commit hook for git. -# Copy or link this file as ".git/hooks/pre-commit" -# -# Eg, +# pre-commit hook for git. Copy or link this file to +# ".git/hooks/pre-commit"; e.g., # ( # cd $WM_PROJECT_DIR/.git/hooks && # ln -sf ../../bin/tools/pre-commit-hook pre-commit # ) # -# Hook receives: empty +# Hook receives: (nothing) # -# Checks for +# Checks for: +# - tabs # - trailing whitespace and non-standard line endings -# - illegal code, e.g. -# - columns greater than 80 for *.[CH] files -# - non-standard code patterns +# - lines longer that than 80 characters +# - non-standard code patterns, > > and NULL # - mismatched header #ifndef/#define names # - incorrect copyright statements # # 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. -# #------------------------------------------------------------------------------ -. bin/tools/HookFunctions || exit 1 +. ./bin/tools/HookFunctions || exit 1 -hookName="pre-commit" - - -#----------------------------------------------------------------------------- -# Check content that will be added by this commit -# - -# Clear -unset fileList -unset badFiles - -# Get the commit to test against +# Get the commit to test against, or git's "empty" object if there is no head if git rev-parse --verify HEAD > /dev/null 2>&1 then against=HEAD else - # Git's "empty" object against=$(git hash-object -t tree /dev/null) - fi # 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 - fileList=$(git ls-files -- $@ 2>/dev/null) -else - # Called with out arguments to test staged changes - fileList=$(git diff-index --cached --name-only $against --) -fi +readarray -t files < <(git diff-index --cached --name-only "$against" --) # If no files have changed then the checks are not needed. This usage can -# correspond to a 'git commit --amend' -[ -n "$fileList" ] || exit 0 +# correspond to a 'git commit --amend'. +[ "${#files[@]}" -gt 0 ] || exit 0 - -#------------------------------------------------------------------------------ -# Main code. Do all checks. - -# Builtin whitespace check to avoid trailing space, including CR-LF endings -bad=$(git diff-index --cached --check $against -- ':(exclude)*.md') || die "$bad" - -# Check for illegal code, e.g. , etc -checkIllegalCode - -# Ensure code conforms to 80 columns max -checkLineLengthNonDirective - -# Check for non-standard code patterns -checkNonStandardCodePatterns - -# Check if #ifndef/#define bounds are named correctly -checkHeaderIfndefNames - -# Check banner -checkBanner - -# Check copyright -checkCopyright - -exit 0 +# Do checks +checkAll --cached true "${files[@]}" && exit 0 || exit 1 #------------------------------------------------------------------------------ diff --git a/bin/tools/pre-receive-hook b/bin/tools/pre-receive-hook index 2ecb836ac8..a5f6791642 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 | Website: https://openfoam.org -# \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation +# \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation # \\/ M anipulation | #------------------------------------------------------------------------------ # License @@ -26,10 +26,8 @@ # pre-receive-hook # # Description -# pre-receive hook for git. -# Copy or link this file as ".git/hooks/pre-receive" -# -# Eg, +# pre-receive hook for git. Copy or link this file to +# ".git/hooks/pre-receive"; e.g., # ( # cd $WM_PROJECT_DIR/.git/hooks && # ln -sf ../../bin/tools/pre-receive-hook pre-receive @@ -37,54 +35,48 @@ # # Hook receives: # -# Checks for -# - illegal code, e.g. -# - columns greater than 80 for *.[CH] files +# Checks for: +# - tabs +# - trailing whitespace and non-standard line endings +# - lines longer that than 80 characters +# - non-standard code patterns, > > and NULL +# - mismatched header #ifndef/#define names +# - incorrect copyright statements # #------------------------------------------------------------------------------ . bin/tools/HookFunctions || exit 1 -hookName="pre-receive" - - -#------------------------------------------------------------------------------ -# Main code. Do all checks. -# - -while read oldSHA1 newSHA1 refName +while read -r oldSHA1 newSHA1 refName do - unset fileList rawFileList + unset rawFiles files + # Get the list of changed files if [ "$newSHA1" = 0 ] then - # Ref to be deleted continue elif [ "$oldSHA1" = 0 ] then - # Ref to be created - rawFileList=$(git diff-tree --root $newSHA1) + readarray -t rawFiles < <(git diff-tree --root "$newSHA1") else - # Normal changes - rawFileList=$(git diff --name-only $oldSHA1..$newSHA1) + readarray -t rawFiles < <(git diff --name-only "$oldSHA1".."$newSHA1") fi - # No files have changed, so the checks are not necessary - [ -n "$rawFileList" ] || continue + # If no files have changed then the checks are not necessary + [ "${#rawFiles[@]}" -gt 0 ] || continue - fileList=$( - for f in $rawFileList + # Filter the file list + files=() + for file in "${rawFiles[@]}" do - git cat-file -e $newSHA1:$f > /dev/null 2>&1 && echo "$f" + if git cat-file -e "$newSHA1":"$file" > /dev/null 2>&1 + then + files+=("$file") + fi done - ) - - # check for illegal code, e.g. , etc - checkIllegalCode $newSHA1 - - # ensure code conforms to 80 columns max - checkLineLengthNonDirective $newSHA1 + # Do the checks + checkAllNoCopyright "$newSHA1" false "${files[@]}" || exit 1 done exit 0