code prettify

Showing posts with label github. Show all posts
Showing posts with label github. Show all posts

Saturday, 13 February 2016

Using git pre-commit hook for php and js syntax check

This is a followup from my two previous posts on php and js git pre-commit syntax check where I had mentioned how to check for php and js syntax independently using pre-commit with git.



But what if we wanted to check for both php and js syntax at same time while committing. So, I used the scripts used for both and combined them. Below is the final result.

#!/bin/bash

commit_error=false

ROOT_DIR="$(pwd)/"
LIST=$(git diff-index --cached --name-only --diff-filter=ACMR HEAD)
ERRORS_BUFFER=""
for file in $LIST
do
    EXTENSION=$(echo "$file" | grep ".php$")
    if [ "$EXTENSION" != "" ]; then
        ERRORS=$(php -l "$ROOT_DIR$file" 2>&1 | grep "Parse error")
        if [ "$ERRORS" != "" ]; then
            if [ "$ERRORS_BUFFER" != "" ]; then
                ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
            else
                ERRORS_BUFFER="$ERRORS"
            fi
            echo "Syntax errors found in file: $file "
        fi

        # Check for xdebug statments
        ERRORS=$(grep -nH xdebug_ "$ROOT_DIR$file" | \
                 sed -e 's/^/Found XDebug Statment : /')
        if [ "$ERRORS" != "" ]; then
            if [ "$ERRORS_BUFFER" != "" ]; then
                ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
            else
                ERRORS_BUFFER="$ERRORS"
            fi
        fi
    fi
done
if [ "$ERRORS_BUFFER" != "" ]; then
    echo
    echo "Found PHP parse errors: "
    echo -e $ERRORS_BUFFER
    echo
    echo "PHP parse errors found. Fix errors and commit again."
    commit_error=true
else
    echo "No PHP parse errors found. Committed successfully."
fi

files=$(git diff --cached --name-only --diff-filter=ACM | grep "\.js$")
if [ "$files" = "" ]; then
    exit 0
fi

pass=true

JS_ERRORS_BUFFER=""

echo -e "\nValidating JavaScript:\n"

for file in ${files}; do
    result=$(jslint ${file} | grep "${file} is OK")

    if [ "$result" != "" ]; then
        echo -e "\t\033[32mJSLint Passed: ${file}\033[0m"
    else
        JS_ERRORS=$(jslint ${file})
        JS_ERRORS_BUFFER="$JS_ERRORS_BUFFER\n$JS_ERRORS"
        echo -e "\t\033[31mJSLint Failed: ${file}\033[0m"
        pass=false
    fi
done

echo -e "\nJavaScript validation complete\n"

if ! $pass; then
    echo -e "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again."
    echo -e $JS_ERRORS_BUFFER
    echo
    commit_error=true
else
    echo -e "\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi

if $commit_error; then
    exit 1
fi

Store it in .git/hooks/pre-commit
Give it execute permission: $ chmod +x .git/hooks/pre-commit and it should be good to go :)

Sample output when I try to commit two php files and two js files with syntax errors:

Filenames with code content:

error.php


<?php
$
array = ;

another_error.php

<?php
var_dump(');

error.js

i =

another_error.js

i = k;

$ git commit -m 'Error Commit' error.php another_error.php error.js another_error.js
Output from above error commit:

Syntax errors found in file: another_error.php 
Syntax errors found in file: error.php 

Found PHP parse errors: 
PHP Parse error: syntax error, unexpected ';' in /var/www/html/error.php on line 2
PHP Parse error: syntax error, unexpected '');' (T_ENCAPSED_AND_WHITESPACE) in /var/www/html/another_error.php on line 2

PHP parse errors found. Fix errors and commit again.

Validating JavaScript:

JSLint Failed: error.js
JSLint Failed: another_error.js

JavaScript validation complete

COMMIT FAILED: Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again.

error.js #1 'i' was used before it was defined. i = // Line 1, Pos 1 #2 Unexpected character '(space)'. i = // Line 1, Pos 4 #3 Unexpected '(end)'. i = // Line 1, Pos 3 #4 Stopping. (50% scanned). // Line 1, Pos 3
another_error.js #1 'i' was used before it was defined. i = k; // Line 1, Pos 1 #2 'k' was used before it was defined. i = k; // Line 1, Pos 5

Above script can be further modified to format the output better but is helpful for basic php and js syntax issues and js standard checks in code :)

Friday, 12 February 2016

Associating git hooks with js syntax check

This is a followup article from my previous post.


Here we will be using git pre-commit to check for syntax error while committing in JavaScript files.

We will need nodejs in our system. Please check https://nodejs.org/en/ for downloading and install steps.

Note: I am using ubuntu 14.04 for this setup.

Steps to add pre-commit JavaScript syntax check with git:

1. Use npm to install jslint package globally in your system.

https://www.npmjs.com/package/jslint

$ npm install -g jslint

This should globally install jslint in your system and can be referenced as below to check syntax error for any js file.

$ jslint sample.js

for (i = 0; i < 10; i++)
{
        sum += i;
}

Sample output from above command:
sample.js
 #1 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 6
 #2 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 13
 #3 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 21
 #4 Unexpected '++'.
    for (i = 0; i < 10; i++) // Line 1, Pos 22
 #5 Expected exactly one space between ')' and '{'.
    { // Line 2, Pos 1
 #6 Use spaces, not tabs.
    sum += i; // Line 3, Pos 1
 #7 Expected 'sum' at column 9, not column 2.
    sum += i; // Line 3, Pos 2
 #8 'i' was used before it was defined.
    sum += i; // Line 3, Pos 9
 #9 Expected '}' at column 5, not column 1.
    } // Line 4, Pos 1

Above info is quite informative and helpful to fix basic syntax errors, missing semi-colons, indentation etc.

Correcting the above errors to below code and running jslint again:

var i, sum = 0;

for (i = 0; i < 10; i = i + 1) {
    sum += i;
}

Output from jslint:

sample.js is OK.

Note: Please also refer rules and standards being followed by jslint for checking here. Makes a nice read. :)

2. Now that jslint is globally available, let us use it and create a pre-commit file.
I found below links which highlight the use of it in a script:

http://stackoverflow.com/questions/15703065/setup-pre-commit-hook-jshint
http://dev.venntro.com/2012/11/maintaining-consistent-javascript-with-jslint/

The only disadvantage I see in the script is that it only highlights passed and failed JavaScript files with names and does not specify the error in each.

So, I made a few changes to the script as below (highlighted in blue):

#!/bin/sh

files=$(git diff --cached --name-only --diff-filter=ACM | grep "\.js$")
if [ "$files" = "" ]; then
    exit 0
fi

pass=true

ERRORS_BUFFER=""

echo -e "\nValidating JavaScript:\n"

for file in ${files}; do
    result=$(jslint ${file} | grep "${file} is OK")
    if [ "$result" != "" ]; then
        echo -e "\t\033[32mJSLint Passed: ${file}\033[0m"
    else
        ERRORS=$(jslint ${file})
        ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
        echo -e "\t\033[31mJSLint Failed: ${file}\033[0m"
        pass=false
    fi
done

echo -e "\nJavaScript validation complete\n"

if ! $pass; then
    echo -e "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again."
    echo -e $ERRORS_BUFFER
    echo 
    exit 1
else
    echo -e "\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi

3. Save the above script in your git pre-commit file as below:

$ cd /project/directory/
$ vim .git/hooks/pre-commit

Paste the above content and save it. Then give execute permission to it.

$ chmod +x .git/hooks/pre-commit

And we are done and ready :)

Trying a sample case:

I have two js files named sample.js and another.js with below content:

sample.js:

var i = j;

for (key in names) {
    echo names[key];

}

another.js:

var i = []

Lets try to commit them:

$ git commit -m 'Error Commit' sample.js another.js

Below is the pre-commit check output:

Validating JavaScript:

JSLint Failed: sample.js
JSLint Failed: true.js

JavaScript validation complete

COMMIT FAILED: Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again.

 sample.js #1 'j' was used before it was defined. var i = j; // Line 1, Pos 9 #2 'key' was used before it was defined. for (key in names) { // Line 3, Pos 6 #3 Cannot read property 'kind' of undefined // Line 3, Pos 10

 true.js #1 Expected ';' and instead saw '(end)'. var i = [] // Line 1, Pos 11

The output can be formatted a little bit better to place each line error in a new line of its own. But this simple tool is pretty handy for checking js errors while committing :)