phplaravelgitpre-commit-hookphpcs

Git Pre-Commit hook for PHPCS is giving me error in Windows for Laravel


I have installed PHPCS from composer.json

"require-dev": {
    "phpstan/phpstan": "^0.12.93",
    "squizlabs/php_codesniffer": "^3.6"
},

I am using laravel 8 so I have added below code for pre-commit file in .git/hooks/pre-commit file:

#!/bin/sh

# get bash colors and styles here: 
# http://misc.flogisoft.com/bash/tip_colors_and_formatting
C_RESET='\e[0m'
C_RED='\e[31m'
C_GREEN='\e[32m'
C_YELLOW='\e[33m'

function __run() #(step, name, cmd)
{
    local color output exitcode

    printf "${C_YELLOW}[%s]${C_RESET} %-20s" "$1" "$2"
    output=$(eval "$3" 2>&1)
    exitcode=$?

    if [[ 0 == $exitcode || 130 == $exitcode ]]; then
        echo -e "${C_GREEN}OK!${C_RESET}"
    else
        echo -e "${C_RED}NOK!${C_RESET}\n\n$output"
        exit 1
    fi
}

modified="git diff --diff-filter=M --name-only --cached  | grep \".php$\""
ignore="resources/lang,resources/views,bootstrap/helpers,database/migrations,bin"
phpcs="./vendor/bin/phpcs ./app --report=code --colors --report-width=80 --standard=PSR2 --ignore=${ignore}"

__run "1/3" "php lint" "${modified} | xargs -r php -l"
__run "2/3" "code sniffer" "${modified} | xargs -r ${phpcs}"
__run "3/3" "phpstan" "${modified} | xargs -r vendor/bin/phpstan analyse"

But this is giving me below error:

[2/3] code sniffer        NOK!

xargs: ./vendor/bin/phpcs: No such file or directory

EDIT:

Need to add below code


PROJECT=`php -r "echo dirname(dirname(dirname(realpath('$0'))));"`
STAGED_FILES_CMD=`git diff --cached --name-only --diff-filter=ACMR HEAD | grep \\\\.php`

# Determine if a file list is passed
if [ "$#" -eq 1 ]
then
    oIFS=$IFS
    IFS='
    '
    SFILES="$1"
    IFS=$oIFS
fi
SFILES=${SFILES:-$STAGED_FILES_CMD}

echo "Checking PHP Lint..."
echo $FILES;exit 1;
for FILE in $SFILES
do
    php -l -d display_errors=0 $PROJECT/$FILE
    if [ $? != 0 ]
    then
        echo "Fix the error before commit."
        exit 1
    fi
    FILES="$FILES $PROJECT/$FILE"
done

if [ "$FILES" != "" ]
then

Solution

  • Worked code so that it would be useful to others:

    #!C:/Program\ Files/Git/usr/bin/sh.exe
    
    PROJECT=`php -r "echo dirname(dirname(realpath('$0')));"`
    
    STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".php\{0,1\}$")
    
    if [[ "$STAGED_FILES" = "" ]]; then
      exit 0
    fi
    
    PASS=true
    
    echo " Validating PHPCS:"
    
    #doesnt matter where git was ran...just get absolute path to the .git folder
    gitBase=`git rev-parse --absolute-git-dir`
    
    
    # Check for phpcs
    which ${gitBase}/../<path>/vendor/bin/phpcs &> /dev/null
    if [[ "$?" == 1 ]]; then
      echo " Please install PHPCS "
      exit 1
    fi
    
    RULESET="$PROJECT/.githooks/ruleset.xml"
    
    for FILE in $STAGED_FILES
    do
      ${gitBase}/../<path>/vendor/bin/phpcs --colors --standard="$RULESET"  -n -p "$FILE"
    
      if [[ "$?" == 0 ]]; then
        echo "PHPCS Passed: $FILE "
      else
        echo "PHPCS Failed: $FILE "
        PASS=false
      fi
    done
    
    echo " PHPCS validation completed! "
    
    if ! $PASS; then
      echo " COMMIT FAILED:  Your commit contains files that should pass PHPCS but do not. Please fix the PHPCS errors and try again. "
      exit 1
    else
      echo " COMMIT SUCCEEDED "
    fi
    
    exit $?
    

    and ruleset.xml is

    <?xml version="1.0"?>
    <ruleset name="PHP_CodeSniffer">
        <description>The coding standard for our project.</description>
        <rule ref="PSR2" />
    
        <file>app</file>
        <file>bootstrap</file>
        <file>config</file>
        <file>database</file>
        <file>resources</file>
        <file>routes</file>
        <file>tests</file>
    
        <exclude-pattern>bootstrap/cache/*</exclude-pattern>
        <exclude-pattern>bootstrap/autoload.php</exclude-pattern>
        <exclude-pattern>*/migrations/*</exclude-pattern>
        <exclude-pattern>*/seeds/*</exclude-pattern>
        <exclude-pattern>*.blade.php</exclude-pattern>
        <exclude-pattern>*.js</exclude-pattern>
        <exclude-pattern>tests/*</exclude-pattern>
        <!-- Show progression -->
        <arg value="p"/>
    </ruleset>