diff --git a/.githooks/pre-commit/test b/.githooks/pre-commit/test index 9b40d8b..80fb4a8 100755 --- a/.githooks/pre-commit/test +++ b/.githooks/pre-commit/test @@ -1,9 +1,10 @@ #!/usr/bin/env node -var spawn = require('child_process').spawn; -var exec = require('child_process').execSync; -var gitCachedFiles = exec('git diff --cached --name-only --diff-filter=ACMR').toString().trim(); +var CP = require('child_process'); +var gitCachedFiles = CP.execSync('git diff --cached --name-only --diff-filter=ACMR').toString().trim(); +var opts = {stdio: 'inherit'}; if (gitCachedFiles) { - spawn('npm', ['test'], {stdio: 'inherit'}).on('close', process.exit.bind(process)); + (process.platform === 'win32' ? + CP.exec('npm test', opts) : CP.spawn('npm', ['test'], opts)).on('close', process.exit.bind(process)); } diff --git a/lib/git-hooks.js b/lib/git-hooks.js old mode 100644 new mode 100755 index afd6dc0..28dd204 --- a/lib/git-hooks.js +++ b/lib/git-hooks.js @@ -3,6 +3,7 @@ var util = require('util'); var spawn = require('child_process').spawn; var fs = require('fs'); var fsHelpers = require('./fs-helpers'); +var isWin32 = process.platform === 'win32'; var HOOKS_DIRNAME = 'hooks'; var HOOKS_OLD_DIRNAME = 'hooks.old'; @@ -51,7 +52,12 @@ module.exports = { } var hookTemplate = fs.readFileSync(__dirname + '/' + HOOKS_TEMPLATE_FILE_NAME); - var pathToGitHooks = path.relative(hooksPath, __dirname); + var pathToGitHooks = path.join(path.relative(hooksPath, __dirname), 'git-hooks'); + + if (isWin32) { + pathToGitHooks = pathToGitHooks.replace(/\\/g, '\\\\'); + } + var hook = util.format(hookTemplate.toString(), pathToGitHooks); fsHelpers.makeDir(hooksPath); @@ -160,11 +166,22 @@ function isExecutable(stats) { */ function spawnHook(hookName, args) { var stats = fs.statSync(hookName); - var isHookExecutable = stats && stats.isFile() && isExecutable(stats); - if (!isHookExecutable) { + var command = hookName; + var opts = args; + var hook; + + if (isWin32) { + hook = fs.readFileSync(hookName).toString(); + if (!require('shebang-regex').test(hook)) { + throw new Error('Cannot find shebang in hook: ' + hookName + '.'); + } + command = require('shebang-command')(require('shebang-regex').exec(hook)[0]); + opts = [hookName].concat(opts); + } else if (!(stats && stats.isFile() && isExecutable(stats))) { throw new Error('Cannot execute hook: ' + hookName + '. Please check file permissions.'); } - return spawn(hookName, args, {stdio: 'inherit'}); + + return spawn(command, opts, {stdio: 'inherit'}); } /** diff --git a/lib/hook-template.js b/lib/hook-template.js old mode 100644 new mode 100755 index 3b852df..561cccc --- a/lib/hook-template.js +++ b/lib/hook-template.js @@ -1,7 +1,7 @@ #!/usr/bin/env node try { - require('%s/git-hooks').run(__filename, process.argv[2], function (code) { + require('%s').run(__filename, process.argv[2], function (code) { process.exit(code); }); } catch (e) { diff --git a/package.json b/package.json old mode 100644 new mode 100755 index a4ca7cd..2a9c71e --- a/package.json +++ b/package.json @@ -50,6 +50,10 @@ "examples", "lib" ], + "dependencies": { + "shebang-command": "1.0.0", + "shebang-regex": "2.0.0" + }, "devDependencies": { "chai": "2.3.0", "istanbul": "0.3.17", diff --git a/tests/run.test.js b/tests/run.test.js old mode 100644 new mode 100755 index 5a5d81c..ab120ea --- a/tests/run.test.js +++ b/tests/run.test.js @@ -2,6 +2,7 @@ require('chai').should(); var fs = require('fs'); var gitHooks = require('../lib/git-hooks'); var fsHelpers = require('../lib/fs-helpers'); +var isWin32 = process.platform === 'win32'; var SANDBOX_PATH = __dirname + '/tmp-sandbox/'; var GIT_ROOT = SANDBOX_PATH + '.git/'; @@ -39,7 +40,8 @@ describe('git-hook runner', function () { describe('and a hook is unexecutable', function () { beforeEach(function () { var logFile = SANDBOX_PATH + 'hello.log'; - fs.writeFileSync(PROJECT_PRECOMMIT_HOOK + 'hello', '#!/bin/bash\n' + 'echo hello > ' + logFile); + var hook = (isWin32 ? '' : '#!/bin/bash\n') + 'echo hello > ' + logFile; + fs.writeFileSync(PROJECT_PRECOMMIT_HOOK + 'hello', hook); }); it('should return an error', function () { @@ -55,6 +57,9 @@ describe('git-hook runner', function () { beforeEach(function () { hooks.forEach(function (name) { var logFile = SANDBOX_PATH + name + '.log'; + if (isWin32) { + logFile = logFile.replace(/\\/g, '\\\\'); + } createHook(PROJECT_PRECOMMIT_HOOK + name, 'echo ' + name + '> ' + logFile); }); }); @@ -73,6 +78,9 @@ describe('git-hook runner', function () { describe('and works without errors', function () { var logFile = SANDBOX_PATH + 'hello.log'; + if (isWin32) { + logFile = logFile.replace(/\\/g, '\\\\'); + } beforeEach(function () { createHook(PROJECT_PRECOMMIT_HOOK + 'hello', 'echo Hello, world! > ' + logFile); });