17

I want to run JSLint before a commit into either a Mercurial or Git repo is done.

I want this as an automatic step that is set up instead of relying on the developer (mainly me) remembering to run JSLint before-hand. I normally run JSLint while developing, but want to specify a contract on JS files that they pass JSLint before being committed to the repo.

For Mercurial, this page spells out the precommit syntax, but the only variables that seem to be available are the parent1 and parent2 changeset IDs involved in the commit. What I really want are a list of file names that are involved with the commit, so that I can then choose the .js file and run jslint over them.

Similar issue for GIT, the default info available as part of the precommit script seems limited.

What might work is calling hg status/git status as part of the precommit script, parse that output to find JS files then do the work that way. I was hoping for something easier though, and I am not sure if calling status as part of a precommit hook reflect the correct information. For instance in Git if the changes files have not been added yet, but the git commit uses -a, would the files show up in the correct section of the git status output as being part of the commit set?

Update: I got something working, it is visible here: http://github.com/jrburke/dvcs_jslint/

jrburke
  • 6,776
  • 1
  • 32
  • 23
  • 1
    Just for completeness, here are some instructions for setting up [JSLint as a Subversion Commit Hook](http://www.amaxus.com/cms-blog/jslint-as-subversion-hook). –  Mar 24 '10 at 08:17
  • Had the same need so I wrote this http://bitbucket.org/robmadole/hgjslint/ –  May 13 '10 at 20:34

3 Answers3

12

The following is a variation of @Bitbieger's Git solution that works with Node.js and a local copy of node-jslint (i.e. you need to npm install jslint in your root repository directory).

Additionally the script:

  • Runs jslint over all .html and .json files as well as .js
  • Only runs jslint over files that have been added, copied or modified. This prevents jslint from erroring on files that have been renamed or deleted.
  • Replicates any jslint errors for the user to see
  • Uses the --indent 4 --white true jslint options to ensure source code consistency

To get it to work copy the following to .git/hooks/pre-commit and don't forget to chmod +x .git/hooks/pre-commit

# Pre-commit hook passing files through jslint
#
# This ensures that all js, html and json files are valid and conform
# to expectations.

ROOT_DIR=$(git rev-parse --show-toplevel)
JSLINT="${ROOT_DIR}/node_modules/.bin/jslint --indent 4 --white true"

for file in $(git diff-index --name-only --diff-filter=ACM --cached HEAD -- | grep -P '\.((js)|(html)|(json))$'); do
    if node $JSLINT $file 2>&1 | grep 'No errors found' ; then
        echo "jslint passed ${file}"
        exit 0
    else
        node $JSLINT $file
        exit 1
    fi  
done
Homme Zwaagstra
  • 11,713
  • 2
  • 17
  • 14
  • 1
    should the "exit 0" be outside the loop? That way the loop will actually check each file, instead of returning on the first one that passed. – Errol Fitzgerald Sep 07 '12 at 05:12
  • 2
    I get the following trying to use this `grep: invalid option -- P Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information.` any ideas? I am not familiar with grep but `-P` does appear to be a valid [option](http://unixhelp.ed.ac.uk/CGI/man-cgi?grep). – James Dec 04 '13 at 16:48
2

For git, there are examples in the .git/hooks directory. If you just need the file names for JSLint, you could use git diff --name-only, which in my example will list the names of the files that differ from the current HEAD.

Mike Ashley
  • 156
  • 1
  • 6
  • Thanks for the hint on the git command. So it still seems that I'll need to use a dvcs command to get the list of files and parse out the files to feed to jslint. At least git diff --name-only will make parsing fairly easy. – jrburke Dec 03 '09 at 19:17
1

JSLint with SpiderMonkey

for js in $(git diff-index --name-only --cached HEAD -- | grep '\.js$'); do
    if jslint.sh $js 2>&1 | grep 'Lint at line' ; then
        echo $js
        exit 1
    else
        echo "js files validated"
        exit 0
    fi  
done
Bitbieger
  • 11
  • 1