Skip to content

Commit 490addd

Browse files
author
Nikita Korotkih
committed
use git ignore rules to skip hooks
1 parent 690aff0 commit 490addd

File tree

4 files changed

+60
-16
lines changed

4 files changed

+60
-16
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ git commit -m "Add git-hooks"
4646

4747
See also [hooks examples](examples).
4848

49+
It's worth to mention that our library checks for gitignore rules while executing scripts in .githooks/ directories.
50+
4951
## Related projects
5052
* Original [git-hooks](https://github.com/icefox/git-hooks) project
5153
* [pre-commit](https://github.com/observing/pre-commit)

lib/git-hooks.js

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var util = require('util');
33
var spawn = require('child_process').spawn;
44
var fs = require('fs');
55
var fsHelpers = require('./fs-helpers');
6+
var exec = require('child_process').exec;
67

78
var HOOKS_DIRNAME = 'hooks';
89
var HOOKS_OLD_DIRNAME = 'hooks.old';
@@ -25,6 +26,19 @@ var HOOKS = [
2526
'update'
2627
];
2728

29+
/**
30+
* @param {String[]} hooks List of hook's paths with possible excludes(.gitignore files)
31+
* @param {function} callback Filtered hooks will be passed in the callback
32+
*/
33+
function excludeIgnoredPaths(hooks, callback) {
34+
exec('git check-ignore ' + hooks.join(' '), function (error, output) {
35+
// intentionally ignore errors
36+
callback(hooks.filter(function (hookName) {
37+
return output.indexOf(hookName) === -1;
38+
}));
39+
});
40+
}
41+
2842
module.exports = {
2943
/**
3044
* Installs git hooks.
@@ -112,8 +126,9 @@ module.exports = {
112126
var hooks = list.map(function (hookName) {
113127
return path.resolve(hooksDirname, hookName);
114128
});
115-
116-
runHooks(hooks, [arg], callback);
129+
excludeIgnoredPaths(hooks, function (filteredHooks) {
130+
runHooks(filteredHooks, [arg], callback);
131+
});
117132
} else {
118133
callback(0);
119134
}
@@ -133,14 +148,18 @@ function runHooks(hooks, args, callback) {
133148
return;
134149
}
135150

136-
var hook = spawnHook(hooks.shift(), args);
137-
hook.on('close', function (code) {
138-
if (code === 0) {
139-
runHooks(hooks, args, callback);
140-
} else {
141-
callback(code);
142-
}
143-
});
151+
try {
152+
var hook = spawnHook(hooks.shift(), args);
153+
hook.on('close', function (code) {
154+
if (code === 0) {
155+
runHooks(hooks, args, callback);
156+
} else {
157+
callback(code);
158+
}
159+
});
160+
} catch (e) {
161+
callback(1, e);
162+
}
144163
}
145164

146165
/**

lib/hook-template.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ try {
88
* www
99
* node_modules
1010
*/
11-
require('%s/git-hooks').run(__filename, process.argv[2], function (code) {
11+
require('%s/git-hooks').run(__filename, process.argv[2], function (code, error) {
12+
if (error) {
13+
console.error('[GIT-HOOKS ERROR] ' + error.message);
14+
}
1215
process.exit(code);
1316
});
1417
} catch (e) {

tests/run.test.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var GIT_ROOT = SANDBOX_PATH + '.git/';
88
var GIT_HOOKS = GIT_ROOT + 'hooks';
99
var PRECOMMIT_HOOK_PATH = GIT_HOOKS + '/pre-commit';
1010
var PROJECT_PRECOMMIT_HOOK = SANDBOX_PATH + '.githooks/pre-commit/';
11+
var GIT_IGNORE = SANDBOX_PATH + '.gitignore';
1112

1213
function createHook(path, content) {
1314
fs.writeFileSync(path, '#!/bin/bash\n' + content);
@@ -42,11 +43,12 @@ describe('git-hook runner', function () {
4243
fs.writeFileSync(PROJECT_PRECOMMIT_HOOK + 'hello', '#!/bin/bash\n' + 'echo hello > ' + logFile);
4344
});
4445

45-
it('should return an error', function () {
46-
var fn = function () {
47-
gitHooks.run(PRECOMMIT_HOOK_PATH);
48-
};
49-
fn.should.throw(Error);
46+
it('should return an error', function (done) {
47+
gitHooks.run(PRECOMMIT_HOOK_PATH, null, function (code, error) {
48+
code.should.equal(1);
49+
error.should.be.ok;
50+
done();
51+
});
5052
});
5153
});
5254

@@ -98,5 +100,23 @@ describe('git-hook runner', function () {
98100
});
99101
});
100102
});
103+
104+
describe('do not run git-ignored scripts from hooks directory', function () {
105+
var ignoreFilename = 'ignore-me';
106+
var ignoreContent = ignoreFilename + '\n*.swp';
107+
108+
beforeEach(function () {
109+
fs.writeFileSync(GIT_IGNORE, ignoreContent);
110+
fs.writeFileSync(PROJECT_PRECOMMIT_HOOK + ignoreFilename, 'exit -1');
111+
fs.writeFileSync(PROJECT_PRECOMMIT_HOOK + 'test.swp', 'exit -1');
112+
});
113+
114+
it('should ignore file with wrong permissions in hooks directory', function (done) {
115+
gitHooks.run(PRECOMMIT_HOOK_PATH, null, function (code) {
116+
code.should.equal(0);
117+
done();
118+
});
119+
});
120+
});
101121
});
102122
});

0 commit comments

Comments
 (0)