Skip to content

Instantly share code, notes, and snippets.

@mklabs
Created November 15, 2011 17:28
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mklabs/1367701 to your computer and use it in GitHub Desktop.
Save mklabs/1367701 to your computer and use it in GitHub Desktop.
run jshint as git/hg hooks, NO COMMIT IF NO LINT FREE.

Run jshint on changed files in the working directory, and prevent commits if no lint free.

git

To enable this hook, make this file executable by chmod +x .git/hooks/pre-commit.

http://progit.org/book/ch7-3.html

git init
curl https://raw.github.com/gist/1367701/pre-commit >> .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
git commit

hg

http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#sec:hook:simple

hg init
mkdir .hg/hooks
curl https://raw.github.com/gist/1367701/pre-commit >> .hg/hooks/pre-commit
chmod +x .hg/hooks/pre-commit

echo '[hooks]' >> .hg/hgrc
echo 'pre-commit = .hg/hooks/pre-commit' >> .hg/hgrc
cat .hg/hgrc

hg commit

note: the hg hook for precommit is actually pre-commit, not precommit.

NO COMMIT IF NO LINT FREE.

#!/usr/bin/env node
// todo: try to require jshint here, instead of spawning process, then fallback to spawning process.
var jshint = nrequire('jshint');
if (jshint) return process.exit(0);
// jshint not installed locally, spawn process instead.
// basically the same, but less pretty.
var exec = require('child_process').exec;
// Get the list of changed files in working dir. command depends on __dirname
// where a path with `.git/` triggers the git command. otherwise hg.
// git: git status -s
// hg: hg status
var cmd = /\.git\//.test(__dirname) ? 'git status -s' : 'hg status'
exec(cmd, function(err, stdout) {
if(err) return error(err);
// parse the command line results, searching for any files marked as `M` or `A`
var changed = (stdout.match(/^\s?[MA]\s(.+)/gim) || []).map(function(file) {
return file.trim().replace(/^[MA]\s?/, '');
});
if(!changed.length) return process.exit(0);
console.log('Running jshint on', changed.length, 'files');
exec('jshint ' + changed.join(' '), function(err, stdout) {
if(err) return error(stdout);
console.log(stdout);
process.exit(0);
});
});
function nrequire(m) {
var n;
try { n = require(m); }
catch(e) { console.log('please, install ' + m + ' locally to be able to use it programmatically. will spawn process instead. \n'); }
return n;
}
function error(err) {
if(!(err instanceof Error)) err = new Error(err);
console.error(err.message || err.stack);
process.exit(1);
}
@alanhussey
Copy link

If I'm understanding this correctly, line 5 means that this script will silently pass if JSHint was installed using npm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment