diff --git a/files/pre-commit b/files/pre-commit new file mode 100755 index 0000000..81fb02c --- /dev/null +++ b/files/pre-commit @@ -0,0 +1,113 @@ +#!/usr/bin/env node +var exec = require('child_process').exec; +var cwd = process.cwd(); +var fail = '\x1B[31mfailed!\x1B[39m'; +var ok = '\x1B[32mok\x1B[39m'; +var notfound = '\x1B[33mn/a\x1B[39m (no script found)'; +var exists = require('fs').existsSync; +var path = require('path'); +path.resolve("app/"); + +function getRoot() { + exec('git rev-parse --show-toplevel', function (err, stderr, stdout) { + if (err) { + console.log('failed to find git root'); + process.exit(1); + } + var path = stderr.trim(), + config = require(path + '/app/package.json'), + myconfig = config.config && config.config.precommit ? config.config.precommit : undefined; + runJshint(stdout, config, myconfig); + }); +} + +function runJshint(path, config, myconfig) { + var cmd; + if (myconfig && myconfig.hasOwnProperty('lint')) { + if (myconfig.lint && myconfig.lint !== true) { + cmd = myconfig.lint; + } else if (myconfig.lint === false) { + return runValidator(path, config, myconfig); + } + } + if (!cmd) { + if (exists('./node_modules/precommit-hook/node_modules/.bin/jshint')) { + cmd = '"./node_modules/precommit-hook/node_modules/.bin/jshint" .'; + } else if (exists('./node_modules/.bin/jshint')) { + cmd = '"./node_modules/.bin/jshint" .'; + } else { + console.log('jshint: ' + notfound); + return runValidator(path, config, myconfig); + } + } + exec(cmd, { cwd: path }, function (err, stdout, stderr) { + if (err) { + console.log('jshint: ' + fail); + console.log(stdout); + console.log(stderr); + process.exit(1); + } else { + console.log('jshint: ' + ok); + runValidator(path, config, myconfig); + } + }); +} + +function runValidator(path, config, myconfig) { + var cmd; + if (myconfig && myconfig.hasOwnProperty('validate')) { + if (myconfig.validate && myconfig.validate !== true) { + cmd = myconfig.validate; + } else if (myconfig.validate === false) { + return runTests(path, config, myconfig); + } + } + if (!cmd && config.scripts && config.scripts.validate) cmd = config.scripts.validate; + if (cmd) { + exec(cmd, { cwd: path }, function (err, stdout, stderr) { + if (err) { + console.log('validation: ' + fail); + console.log(stdout); + console.log(stderr); + process.exit(1); + } else { + console.log('validation: ' + ok); + runTests(path, config, myconfig); + } + }); + } else { + console.log('validation: ' + notfound); + runTests(path, config, myconfig); + } +} + +function runTests(path, config, myconfig) { + var cmd; + if (myconfig && myconfig.hasOwnProperty('test')) { + if (myconfig.test && myconfig.test !== true) { + cmd = myconfig.test; + } else if (myconfig.test === false) { + return process.exit(0); + } + } + if (!cmd && config.scripts && config.scripts.test) cmd = config.scripts.test; + if (cmd) { + exec(cmd, { cwd: path }, function (err, stdout, stderr) { + if (err) { + console.log('tests: ' + fail); + console.log(stdout); + console.log(stderr); + process.exit(1); + } else { + console.log('tests: ' + ok); + process.exit(0); + } + }); + } else { + console.log('tests: ' + notfound); + process.exit(0); + } +} + +console.log('running pre-commit checks...'); +getRoot(); diff --git a/install.js b/install.js new file mode 100644 index 0000000..0170b18 --- /dev/null +++ b/install.js @@ -0,0 +1,47 @@ +var fs = require('fs'); +var path = require('path'); + +var existsSync = fs.existsSync || path.existsSync; + +var projectPath = path.resolve(__dirname, '../../../'); +var packagePath = path.join(projectPath, 'package.json'); +var projectName = path.basename(projectPath); +var filePath = path.join(__dirname, 'files'); +var gitPath = path.join(projectPath, '.git'); +var pcPath = path.join(gitPath, 'hooks', 'pre-commit'); +var jsiPath = path.join(projectPath, '.jshintignore'); +var jsrcPath = path.join(projectPath, '.jshintrc'); +var pcModulePath = path.join(projectPath, '../', '.git', 'modules', projectName, 'hooks'); + + +if (existsSync(gitPath)) { + var stats = fs.lstatSync(path.join(projectPath, '.git')); + if (stats.isDirectory()) { + if (existsSync(pcPath)) fs.unlinkSync(pcPath); + if (!existsSync(path.dirname(pcPath))) fs.mkdirSync(path.dirname(pcPath)); + console.log('Found .git directory, adding pre-commit hook'); + var pcHook = fs.readFileSync(path.join(filePath, 'pre-commit')); + fs.writeFileSync(pcPath, pcHook); + fs.chmodSync(pcPath, '755'); + } +} else if (existsSync(pcModulePath)){ + console.log('Found submodule .git directory, adding pre-commit hook'); + var pcHook = fs.readFileSync(path.join(filePath, 'pre-commit')); + var pcModuleFullPath = path.join(pcModulePath, 'pre-commit'); + fs.writeFileSync(pcModuleFullPath, pcHook); + fs.chmodSync(pcModuleFullPath, '755'); +} else { + console.error('This project doesn\'t appear to be a git repository. JSHint configuration will be created anyway. To enable the pre-commit hook, run `git init` and reinstall precommit-hook.'); +} + +if (!existsSync(jsiPath)) { + console.log('Did not find a .jshintignore, creating one'); + var jsiFile = fs.readFileSync(path.join(filePath, 'jshintignore')); + fs.writeFileSync(jsiPath, jsiFile); +} + +if (!existsSync(jsrcPath) && (!existsSync(packagePath) || !require(packagePath).hasOwnProperty('jshintConfig'))) { + console.log('Did not find a .jshintrc and package.json does not contain jshintConfig, creating .jshintrc'); + var jsrcFile = fs.readFileSync(path.join(filePath, 'jshintrc')); + fs.writeFileSync(jsrcPath, jsrcFile); +}