From bf7d4dae27b626655d3f9ed190b2a9df85b61211 Mon Sep 17 00:00:00 2001 From: 3rd-Eden Date: Tue, 17 Jun 2014 10:34:57 +0200 Subject: [PATCH 001/127] [minor] Code cleanup --- hook | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hook b/hook index 8eedfed..90f590c 100755 --- a/hook +++ b/hook @@ -108,11 +108,14 @@ function run(status, err, output) { hasPreCommit = true; run = pkg['pre-commit']; } - //configure commit.template in git if we are asked to do so + // + // configure commit.template in git if we are asked to do so + // commit_template = pkg['pre-commit.commit-template']; + if (commit_template) { commit_template_cmd = 'git config commit.template "' + commit_template + '"'; - child.exec(commit_template_cmd, [], function(error, stdout, stderr) { + child.exec(commit_template_cmd, [], function exec(error, stdout, stderr) { if (error) { //it is better to write this even if we are 'silent' stderr.write('pre-commit: ' + commit_template_cmd + ' failed\n'); } @@ -163,9 +166,9 @@ function run(status, err, output) { // Check if we have tasks to be executed or if we are complete. task = run.shift(); if (!task) return done(); - + var args = ['run', task]; - + if (silent) { args.push('--silent'); } From 1e039fefb1ab41ab12e78287f02eb05a182e40e8 Mon Sep 17 00:00:00 2001 From: 3rd-Eden Date: Tue, 17 Jun 2014 10:35:18 +0200 Subject: [PATCH 002/127] [dist] 0.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75c995f..2e88f57 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "0.0.7", + "version": "0.0.8", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 190f838bc62f4ad9da8938b5daedb63b0e86eee0 Mon Sep 17 00:00:00 2001 From: 3rd-Eden Date: Thu, 26 Jun 2014 10:07:08 +0200 Subject: [PATCH 003/127] [minor] Add uninstall hook, fixes #11 --- package.json | 10 +++++++--- uninstall.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 uninstall.js diff --git a/package.json b/package.json index 2e88f57..44d0a10 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,22 @@ "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { - "install": "node install" + "install": "node install.js", + "uninstall": "node uninstall.js" }, "repository": { "type": "git", "url": "git://github.com/observing/pre-commit.git" }, "keywords": [ + "git", + "hooks", + "npm", "pre-commit", "precommit", + "run", "test", - "npm", - "run" + "development" ], "author": "Arnout Kazemier ", "license": "MIT", diff --git a/uninstall.js b/uninstall.js new file mode 100644 index 0000000..4a87c62 --- /dev/null +++ b/uninstall.js @@ -0,0 +1,31 @@ +'use strict'; + +var path = require('path') + , fs = require('fs'); + +// +// Compatibility with older node.js. +// +var existsSync = fs.existsSync || path.existsSync; + +// +// The location of the pre-commit hook. +// +var precommit = path.resolve(__dirname, '../..', '.git', 'hooks', 'pre-commit'); + +// +// Bail out if we don't have pre-commit file, it might be removed manually. +// +if (!existsSync(precommit)) return; + +// +// If we don't have an old file, we should just remove the pre-commit hook. But +// if we do have an old precommit file we want to restore that. +// +if (!existsSync(precommit +'.old')) { + fs.unlinkSync(precommit); +} else { + fs.writeFileSync(precommit, fs.readFileSync(precommit +'.old')); + fs.chmodSync(precommit, '755'); + fs.unlinkSync(precommit +'.old'); +} From e54dc12fbe8ed4cf4dbbfc3e46adf0460a420bcd Mon Sep 17 00:00:00 2001 From: 3rd-Eden Date: Thu, 26 Jun 2014 10:20:39 +0200 Subject: [PATCH 004/127] [doc] Updated changelogs --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3649b3b..f16685a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## 0.0.9 +- Added missing uninstall hook to remove and restore old scripts. + +## 0.0.8 +- Added support for installing custom commit templates using `pre-commit.commit-template` + +## 0.0.7 +- Fixes regression introduced in 0.0.6 + +## 0.0.6 +- Also silence `npm` output when the silent flag has been given. + +## 0.0.5 +- Allow silencing of the pre-commit output by setting a `precommit.silent: true` + in your `package.json` + ## 0.0.4 - Added a better error message when you fucked up your `package.json`. - Only run tests if there are changes. From 6427ef261abeaea14ecc282cd03e3837dfdd0d45 Mon Sep 17 00:00:00 2001 From: 3rd-Eden Date: Thu, 26 Jun 2014 10:54:32 +0200 Subject: [PATCH 005/127] [dist] 0.0.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 44d0a10..df6917a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "0.0.8", + "version": "0.0.9", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 06571d377162e8a0d3f170be9c46b5dc0ebf283d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Mon, 24 Nov 2014 05:20:51 +0000 Subject: [PATCH 006/127] added hook windows support using 'which' lib --- hook | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/hook b/hook index 90f590c..7d23046 100755 --- a/hook +++ b/hook @@ -3,6 +3,7 @@ 'use strict'; var child = require('child_process'); +var which = require('which'); // // Get the root of the repository. @@ -172,21 +173,26 @@ function run(status, err, output) { if (silent) { args.push('--silent'); } - - var npm = child.spawn('npm', args, { - cwd: root, // Make sure that we spawn it in the root of repo. - env: process.env, // Give them the same ENV variables. - stdio: [0, 1, 2] // Pipe all the things. - }); - - // - // Check the close code to see if we passed or failed. - // - npm.on('close', function close(code) { - if (code !== 0) return next(new Error(task +' closed with code '+ code), task); - - next(undefined, task); - }); + + which('npm', function(error, path){ + if(error){ + console.log('Failed to find npm') + } + var npm = child.spawn(path, args, { + cwd: root, // Make sure that we spawn it in the root of repo. + env: process.env, // Give them the same ENV variables. + stdio: [0, 1, 2] // Pipe all the things. + }); + + // + // Check the close code to see if we passed or failed. + // + npm.on('close', function close(code) { + if (code !== 0) return next(new Error(task +' closed with code '+ code), task); + + next(undefined, task); + }); + } })(); })(function ready(err) { if (err) return failure(err); From b2f6163eb23f50ae3e2ef6d54f52b2b57a5461ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Mon, 24 Nov 2014 05:23:27 +0000 Subject: [PATCH 007/127] addded which dependency --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index df6917a..4198b12 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ ], "author": "Arnout Kazemier ", "license": "MIT", + "dependencies"; { + "which": "^1.0.5" + } "devDependencies": { "pre-commit": "git://github.com/observing/pre-commit.git" } From e35cd76fb84ec5bfbea6509ef3ecc6beecfa5390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Mon, 24 Nov 2014 05:24:40 +0000 Subject: [PATCH 008/127] typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4198b12..404b68e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "author": "Arnout Kazemier ", "license": "MIT", - "dependencies"; { + "dependencies": { "which": "^1.0.5" } "devDependencies": { From 15bb315a99f02bf5ff2725fa8cbc8ff09c7811d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Mon, 24 Nov 2014 05:24:57 +0000 Subject: [PATCH 009/127] typo --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 404b68e..f28b1f6 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "license": "MIT", "dependencies": { "which": "^1.0.5" - } + }, "devDependencies": { "pre-commit": "git://github.com/observing/pre-commit.git" } From 6f981f10f8b54e064fc0fb307344190f2fb18bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Antunes?= Date: Mon, 24 Nov 2014 05:32:32 +0000 Subject: [PATCH 010/127] solving require bug --- hook | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hook b/hook index 7d23046..bf41e68 100755 --- a/hook +++ b/hook @@ -3,7 +3,7 @@ 'use strict'; var child = require('child_process'); -var which = require('which'); +var which = require('node_modules/pre-commit/node_modules/which'); // // Get the root of the repository. @@ -192,7 +192,7 @@ function run(status, err, output) { next(undefined, task); }); - } + }); })(); })(function ready(err) { if (err) return failure(err); From acd97ae27df0e938a0e7e4e3270ea86bb818f666 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Mon, 24 Nov 2014 05:44:03 +0000 Subject: [PATCH 011/127] which require problem --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index bf41e68..12d72ad 100755 --- a/hook +++ b/hook @@ -3,7 +3,7 @@ 'use strict'; var child = require('child_process'); -var which = require('node_modules/pre-commit/node_modules/which'); +var which = require('node_modules/pre-commit/node_modules/which/which'); // // Get the root of the repository. From 4c142e9a2768b53d953441c10a6d21907f9810f6 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Mon, 24 Nov 2014 05:53:32 +0000 Subject: [PATCH 012/127] which problem solved --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index 12d72ad..e76f089 100755 --- a/hook +++ b/hook @@ -3,7 +3,7 @@ 'use strict'; var child = require('child_process'); -var which = require('node_modules/pre-commit/node_modules/which/which'); +var which = require('pre-commit/node_modules/which'); // // Get the root of the repository. From 4b7289ff8902d7de6ca6fccdc5b58f2a0ae625a8 Mon Sep 17 00:00:00 2001 From: JGAntunes Date: Mon, 24 Nov 2014 15:24:56 +0000 Subject: [PATCH 013/127] solving dependency issue --- hook | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hook b/hook index e76f089..0236fc5 100755 --- a/hook +++ b/hook @@ -3,7 +3,7 @@ 'use strict'; var child = require('child_process'); -var which = require('pre-commit/node_modules/which'); +var which = require('which'); // // Get the root of the repository. diff --git a/package.json b/package.json index f28b1f6..16a7fc1 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "author": "Arnout Kazemier ", "license": "MIT", - "dependencies": { + "peerDependencies": { "which": "^1.0.5" }, "devDependencies": { From 294341e96541cbf826587ded55bdc286d6ad039a Mon Sep 17 00:00:00 2001 From: Ben Regenspan Date: Mon, 29 Dec 2014 18:35:57 -0500 Subject: [PATCH 014/127] Correct a typo in hook failure error message --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index 0236fc5..9f89983 100755 --- a/hook +++ b/hook @@ -43,7 +43,7 @@ function failure(err) { console.error('pre-commit:'); console.error('pre-commit: git commit -n (--no-verify)'); console.error('pre-commit:'); - console.error('pre-commit: But this is not adviced as your tests are obviously failing.'); + console.error('pre-commit: But this is not advised as your tests are obviously failing.'); console.error(''); process.exit(1); } From 9200953fe23f1947cbae104691413655d5f837ef Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 15 Jan 2015 09:18:34 +0100 Subject: [PATCH 015/127] [dist] 0.0.10 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 16a7fc1..449b59d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "0.0.9", + "version": "0.0.10", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { @@ -24,7 +24,7 @@ "author": "Arnout Kazemier ", "license": "MIT", "peerDependencies": { - "which": "^1.0.5" + "which": "1.0.*" }, "devDependencies": { "pre-commit": "git://github.com/observing/pre-commit.git" From e217197ce1f8fdfca25cf863f33f38b15bdf28b2 Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Fri, 16 Jan 2015 10:30:08 -0800 Subject: [PATCH 016/127] Fix broken semver string for "which" dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 449b59d..99ba1f9 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "author": "Arnout Kazemier ", "license": "MIT", "peerDependencies": { - "which": "1.0.*" + "which": "1.0.x" }, "devDependencies": { "pre-commit": "git://github.com/observing/pre-commit.git" From 7e2af499e6081dc07c65c68f282954ce2e4d0a16 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 16 Jan 2015 19:37:17 +0100 Subject: [PATCH 017/127] [dist] 0.0.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99ba1f9..329e3b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "0.0.10", + "version": "0.0.11", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From dbc6c5ac855d0ab91b743563fac3c94332dae876 Mon Sep 17 00:00:00 2001 From: "Raynos (Jake Verbaten)" Date: Mon, 19 Jan 2015 14:45:01 -0800 Subject: [PATCH 018/127] peerDependencies are stupid --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 329e3b5..2ceb104 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ ], "author": "Arnout Kazemier ", "license": "MIT", - "peerDependencies": { + "dependencies": { "which": "1.0.x" }, "devDependencies": { From 248d18c43105dfc2d97e6466e5f29a9386d66764 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:27:10 +0100 Subject: [PATCH 019/127] [major] Create symlinks instead of copy of files to ensure correct module resolving --- install.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/install.js b/install.js index 19414df..7a6ad62 100644 --- a/install.js +++ b/install.js @@ -4,19 +4,11 @@ var path = require('path') , fs = require('fs'); // -// Compatibility with older node.js. +// Compatibility with older node.js as path.exists got moved to `fs`. // -var existsSync = fs.existsSync || path.existsSync; - -// -// Our own pre-commit hook runner. -// -var hook = fs.readFileSync('./hook'); - -// -// The root of repository. -// -var root = path.resolve(__dirname, '../..'); +var existsSync = fs.existsSync || path.existsSync + , root = path.resolve(__dirname, '../..') + , hook = path.join(__dirname, './hook'); // // The location .git and it's hooks @@ -40,10 +32,7 @@ if (!existsSync(hooks)) fs.mkdirSync(hooks); // If there's an existing `pre-commit` hook we want to back it up instead of // overriding it and losing it completely // -if ( - existsSync(precommit) - && fs.readFileSync(precommit).toString('utf8') !== hook.toString('utf8') -) { +if (existsSync(precommit)) { console.log(''); console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); @@ -55,5 +44,4 @@ if ( // Everything is ready for the installation of the pre-commit hook. Write it and // make it executable. // -fs.writeFileSync(precommit, hook); -fs.chmodSync(precommit, '755'); +fs.symlinkSync(precommit, hook, 'file'); From a82648955184974e7cba3e4d636a3ac4dda3ef2d Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:30:25 +0100 Subject: [PATCH 020/127] [minor] Remove old file so we can link --- install.js | 1 + 1 file changed, 1 insertion(+) diff --git a/install.js b/install.js index 7a6ad62..f669b67 100644 --- a/install.js +++ b/install.js @@ -37,6 +37,7 @@ if (existsSync(precommit)) { console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); console.log('pre-commit: Old pre-commit hook backuped to pre-commit.old'); + fs.unlinkSync(precommit); console.log(''); } From ed5a372d6b27d7682bf08ea0564c0afd71203650 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:31:25 +0100 Subject: [PATCH 021/127] [fix] Force unlinking --- install.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/install.js b/install.js index f669b67..97c4e87 100644 --- a/install.js +++ b/install.js @@ -37,7 +37,6 @@ if (existsSync(precommit)) { console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); console.log('pre-commit: Old pre-commit hook backuped to pre-commit.old'); - fs.unlinkSync(precommit); console.log(''); } @@ -45,4 +44,7 @@ if (existsSync(precommit)) { // Everything is ready for the installation of the pre-commit hook. Write it and // make it executable. // +try { fs.unlinkSync(precommit); } +catch (e) {} + fs.symlinkSync(precommit, hook, 'file'); From 3f01b9592cce1d66312d2df8fcf6836a84f0ec94 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:32:21 +0100 Subject: [PATCH 022/127] [fix] LOLZ wrong argument order. --- install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.js b/install.js index 97c4e87..dd37c33 100644 --- a/install.js +++ b/install.js @@ -47,4 +47,4 @@ if (existsSync(precommit)) { try { fs.unlinkSync(precommit); } catch (e) {} -fs.symlinkSync(precommit, hook, 'file'); +fs.symlinkSync(hook, precommit, 'file'); From be046cd4d9be37a516f8ad6bcc58e892f5b2a540 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:48:23 +0100 Subject: [PATCH 023/127] [refactor] Cleanup some of the comments and re-organizing the code --- install.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/install.js b/install.js index dd37c33..af2f74c 100644 --- a/install.js +++ b/install.js @@ -1,38 +1,37 @@ 'use strict'; -var path = require('path') - , fs = require('fs'); - // // Compatibility with older node.js as path.exists got moved to `fs`. // -var existsSync = fs.existsSync || path.existsSync +var fs = require('fs') + , path = require('path') + , hook = path.join(__dirname, './hook') , root = path.resolve(__dirname, '../..') - , hook = path.join(__dirname, './hook'); + , exists = fs.existsSync || path.existsSync; // -// The location .git and it's hooks +// Gather the location of the possible hidden .git directory, the hooks +// directory which contains all git hooks and the absolute location of the +// `pre-commit` file. The path needs to be absolute in order for the symlinking +// to work correctly. // var git = path.resolve(root, '.git') , hooks = path.resolve(git, 'hooks') , precommit = path.resolve(hooks, 'pre-commit'); // -// Check if we are in a git repository so we can bail out early when this is not -// the case. -// -if (!existsSync(git) || !fs.lstatSync(git).isDirectory()) return; - -// -// Create a hooks directory if it's missing. +// Bail out if we don't have an `.git` directory as the hooks will not get +// triggered. If we do have directory create a hooks folder if it doesn't exist. // -if (!existsSync(hooks)) fs.mkdirSync(hooks); +if (!exists(git) || !fs.lstatSync(git).isDirectory()) return; +if (!exists(hooks)) fs.mkdirSync(hooks); // // If there's an existing `pre-commit` hook we want to back it up instead of -// overriding it and losing it completely +// overriding it and losing it completely as it might contain something +// important. // -if (existsSync(precommit)) { +if (exists(precommit)) { console.log(''); console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); @@ -41,8 +40,8 @@ if (existsSync(precommit)) { } // -// Everything is ready for the installation of the pre-commit hook. Write it and -// make it executable. +// We cannot create a symlink over an existing file so make sure it's gone and +// finish the installation process. // try { fs.unlinkSync(precommit); } catch (e) {} From c45c00639153843bfb5b84caacdf32f0519251ba Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 29 Jan 2015 21:54:06 +0100 Subject: [PATCH 024/127] [minor] Check if pre-commit isn't already symlink before we backup --- install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.js b/install.js index af2f74c..aa378ca 100644 --- a/install.js +++ b/install.js @@ -31,7 +31,7 @@ if (!exists(hooks)) fs.mkdirSync(hooks); // overriding it and losing it completely as it might contain something // important. // -if (exists(precommit)) { +if (exists(precommit) && !fs.lstatSync(precommit).isSymbolicLink()) { console.log(''); console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); From a02a6237ba0e1ab459741e914e9b13cc8b338c6b Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:05:59 +0100 Subject: [PATCH 025/127] [refactor] Make the hook test-able through tests. --- hook | 297 ++++++++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 128 insertions(+), 171 deletions(-) diff --git a/hook b/hook index 9f89983..6e0ae75 100755 --- a/hook +++ b/hook @@ -2,204 +2,161 @@ 'use strict'; -var child = require('child_process'); -var which = require('which'); +var child = require('child_process') + , format = require('util').format + , shell = require('shelljs') + , hook = module.exports = {} + , path = require('path'); -// -// Get the root of the repository. -// -child.exec('git status --porcelain', function changes(err, status) { - if (err) { - console.error('pre-commit: Failed to find git root. Cannot run the tests.'); - return process.exit(1); - } +/** + * The contents of the `package.json` + * + * @type {Object} + * @public + */ +hook.json = {}; - child.exec('git rev-parse --show-toplevel', run.bind(null, status)); -}); +/** + * Location of the `npm` binary. Will be set to the `absolute` path during + * initialization. + * + * @type {String} + * @public + */ +hook.npm = ''; /** - * You've failed on some of the scripts, output how much you've sucked today. + * Location of the `git` binary. Will be set to the `absolute` path during + * initialization. * - * @param {Error} err The actual error. - * @api private + * @type {String} + * @public */ -function failure(err) { - console.error(''); - console.error('pre-commit: You\'ve failed to pass all the hooks.'); - console.error('pre-commit:'); - - if (err.ran) { - console.error('pre-commit: The "npm run '+ err.ran +'" script failed.'); - } else { - var stack = err.stack.split('\n') - console.error('pre-commit: An Error was thrown: '+ stack.shift()); - console.error('pre-commit:'); - stack.forEach(function trace(line) { - console.error('pre-commit: '+ line.trim()); - }); - } - console.error('pre-commit:'); - console.error('pre-commit: You can skip the git pre-commit hook by running:'); - console.error('pre-commit:'); - console.error('pre-commit: git commit -n (--no-verify)'); - console.error('pre-commit:'); - console.error('pre-commit: But this is not advised as your tests are obviously failing.'); - console.error(''); - process.exit(1); -} +hook.git = ''; /** - * Run the set pre-commit hooks. + * Helper log function which will prefix all output with the name of our module + * so the users know which module is responsible for the output. * - * @param {Error} err The error that happend while executing the command. - * @param {Error} output The output of rev-parse. - * @api private + * @param {Array} lines The lines that needs to be logged to the user. + * @param {Number} exit Exit code. + * @api public */ -function run(status, err, output) { - if (err) { - console.error(''); - console.error('pre-commit: Failed to find git root. Cannot run the tests.'); - console.error(''); - return process.exit(1); - } +hook.log = function log(lines, exit) { + if (!Array.isArray(lines)) lines = lines.split('\n'); + if ('number' !== typeof exit) exit = 1; - // - // Check if there are scripts specified that we need to run. - // - var root = output.trim() - , run = [] - , hasPreCommit = false - , silent - , pkg - , commit_template - , commit_template_cmd; + lines = lines.map(function map(line) { + return 'pre-commit: '+ line; + }); + + lines.push(''); // Whitespace at the end of the log. + lines.unshift(''); // Whitespace at the beginning. + + if (!hook.json['pre-commit.silent']) lines.forEach(function output(line) { + if (exit) console.error(line); + else console.log(line); + }); + + process.exit(exit); +}; + +hook.initialize = function initialize() { + var failure = 'Failed to locate the `%s` binary due to an error: %s' + , template + , status + , root; + + try { hook.git = shell.which('git'); } + catch (e) { return hook.log(format(failure, 'git', e.message)); } + + try { hook.npm = shell.which('npm'); } + catch (e) { return hook.log(format(failure, 'npm', e.message)); } + + root = shell.exec(hook.git +' rev-parse --show-toplevel', { silent: true }); + status = shell.exec(hook.git +' status --porcelain', { silent: true }); // - // Bail-out when we failed to parse the package.json, there is probably a some - // funcky chars in there. + // Process the output of the git hook's. // - try { pkg = require(root +'/package.json'); } - catch (e) { return failure(e); } - - silent = pkg['pre-commit.silent'] || false; - - if (!status.trim().length) { - if (!silent) { - console.log(''); - console.log('pre-commit: No changes detected, bailing out.'); - console.log(''); - } - return; - } + if (root.code) return hook.log('Failed to get `.git` root: '+ root.output); + if (status.code) return hook.log('Failed to get `get status`: '+ status.output); - if (!pkg.scripts) { - if (!silent) { - console.log(''); - console.log('pre-commit: No scripts detected in the package.json, bailing out.'); - console.log(''); - } - return; - } + hook.root = root.output.trim(); + hook.status = status.output.trim(); + + try { hook.json = require(path.join(hook.root, 'package.json')); } + catch (e) { return hook.log('Failed to parse `package.json`: '+ e.message); } // - // If there's a `pre-commit` property in the package.json we should use that - // array. + // Check for changes to ensure that we don't run our hooks for nothing. // - if (pkg['pre-commit'] && Array.isArray(pkg['pre-commit'])) { - hasPreCommit = true; - run = pkg['pre-commit']; + if (!hook.status.length) { + return hook.log('No changes detected. Stopping.', 0); } + // - // configure commit.template in git if we are asked to do so + // If we have a git template we should configure it before checking for + // scripts so it will still be applied even if we don't have anything to + // execute. // - commit_template = pkg['pre-commit.commit-template']; - - if (commit_template) { - commit_template_cmd = 'git config commit.template "' + commit_template + '"'; - child.exec(commit_template_cmd, [], function exec(error, stdout, stderr) { - if (error) { //it is better to write this even if we are 'silent' - stderr.write('pre-commit: ' + commit_template_cmd + ' failed\n'); - } + if (template = hook.json['pre-commit.commit-template']) { + shell.exec(hook.git +' config commit.template "'+ template +'"', { + silent: true }); } + if (!hook.json.scripts) { + return hook.log('Missing `scripts` in `package.json`. Stopping.', 0); + } + + hook.run(); +}; + +/** + * Run the hooks. + * + * @api private + */ +hook.run = function runner() { + var silent = !!hook.json['pre-commit.silent'] + , pre = hook.json['pr-commit'] + , run = []; + + if ('string' === typeof pre) pre = pre.split(/[, ]+/); + // - // If we don't have any run processes to run try to see if there's a `test` - // property which we should run instead. But we should check if it's not the - // default value that `npm` adds when your run the `npm init` command. + // If we have scripts set in our `pre-commit` field we should run those. If + // they are not available we need to check if `test` is set to something + // sensible so we can use that as default fallback. // - if ( - !hasPreCommit - && !run.length - && pkg.scripts.test - && pkg.scripts.test !== 'echo "Error: no test specified" && exit 1' + if (Array.isArray(pre)) { + Array.prototype.push.apply(run, pre); + } else if ( + hook.json.scripts + && hook.json.scripts.test !== 'echo "Error: no test specified" && exit 1' ) { run.push('test'); } - // - // Bailout if we don't have anything to run. - // - if (!run.length) { - if (!silent) { - console.log(''); - console.log('pre-commit: Nothing to run. Bailing out.'); - console.log(''); - } - return; - } + if (!run.length) return hook.log('No scripts to run. Stopping.', 0); - // - // Behold, a lazy man's async flow control library; - // - (function runner(done) { - (function next(err, task) { - // - // Bailout when we received an error. This will make sure that we don't - // run the rest of the tasks. - // - if (err) { - err = new Error(err.message); - err.ran = task; - return done(err); - } - - // Check if we have tasks to be executed or if we are complete. - task = run.shift(); - if (!task) return done(); - - var args = ['run', task]; - - if (silent) { - args.push('--silent'); - } - - which('npm', function(error, path){ - if(error){ - console.log('Failed to find npm') - } - var npm = child.spawn(path, args, { - cwd: root, // Make sure that we spawn it in the root of repo. - env: process.env, // Give them the same ENV variables. - stdio: [0, 1, 2] // Pipe all the things. - }); - - // - // Check the close code to see if we passed or failed. - // - npm.on('close', function close(code) { - if (code !== 0) return next(new Error(task +' closed with code '+ code), task); - - next(undefined, task); - }); - }); - })(); - })(function ready(err) { - if (err) return failure(err); - - // - // Congratulation young padawan, all hooks passed. - // - process.exit(0); - }); -} + if (run.every(function execute(script) { + return shell.exec(hook.npm +' run '+ script, { silent: silent }).code === 0; + })) return process.exit(0); + + hook.log([ + 'You\'ve failed to pass all the the git pre-commit hooks.', + '', + 'If you\'re feeling adventurous you can skip the hooks using:', + '', + ' git commit -n (or --no-verify)', + '', + 'But this is obviously not advised as your clearly broke something.' + ]); +}; + +// +// Run the hook if we are not required. +// +if (module === require.main) hook.initialize(); diff --git a/package.json b/package.json index 2ceb104..4db14c0 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "author": "Arnout Kazemier ", "license": "MIT", "dependencies": { - "which": "1.0.x" + "shelljs": "0.3.x" }, "devDependencies": { "pre-commit": "git://github.com/observing/pre-commit.git" From 1afc81b9ba0978952516682c94a4f203f93e8d90 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:11:44 +0100 Subject: [PATCH 026/127] [fix] Check for hook.json.scripts.test [minor] Dont' state `stopped` but `continuing` as we're not stopping the commit. --- hook | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hook b/hook index 6e0ae75..9565bfc 100755 --- a/hook +++ b/hook @@ -92,7 +92,7 @@ hook.initialize = function initialize() { // Check for changes to ensure that we don't run our hooks for nothing. // if (!hook.status.length) { - return hook.log('No changes detected. Stopping.', 0); + return hook.log('No changes detected. Continuing.', 0); } // @@ -107,7 +107,7 @@ hook.initialize = function initialize() { } if (!hook.json.scripts) { - return hook.log('Missing `scripts` in `package.json`. Stopping.', 0); + return hook.log('Missing `scripts` in `package.json`. Continuing.', 0); } hook.run(); @@ -134,12 +134,13 @@ hook.run = function runner() { Array.prototype.push.apply(run, pre); } else if ( hook.json.scripts + && hook.json.scripts.test && hook.json.scripts.test !== 'echo "Error: no test specified" && exit 1' ) { run.push('test'); } - if (!run.length) return hook.log('No scripts to run. Stopping.', 0); + if (!run.length) return hook.log('No scripts to run. All good.', 0); if (run.every(function execute(script) { return shell.exec(hook.npm +' run '+ script, { silent: silent }).code === 0; From 0b85343dd7d348ff7eb12326f1cd6b0a7b01ba53 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:12:15 +0100 Subject: [PATCH 027/127] [minor] Clean-up the uninstall script --- uninstall.js | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/uninstall.js b/uninstall.js index 4a87c62..a0d2fd0 100644 --- a/uninstall.js +++ b/uninstall.js @@ -1,28 +1,20 @@ 'use strict'; -var path = require('path') - , fs = require('fs'); - -// -// Compatibility with older node.js. -// -var existsSync = fs.existsSync || path.existsSync; - -// -// The location of the pre-commit hook. -// -var precommit = path.resolve(__dirname, '../..', '.git', 'hooks', 'pre-commit'); +var fs = require('fs') + , path = require('path') + , exists = fs.existsSync || path.existsSync + , precommit = path.resolve(__dirname, '../..', '.git', 'hooks', 'pre-commit'); // // Bail out if we don't have pre-commit file, it might be removed manually. // -if (!existsSync(precommit)) return; +if (!exists(precommit)) return; // // If we don't have an old file, we should just remove the pre-commit hook. But // if we do have an old precommit file we want to restore that. // -if (!existsSync(precommit +'.old')) { +if (!exists(precommit +'.old')) { fs.unlinkSync(precommit); } else { fs.writeFileSync(precommit, fs.readFileSync(precommit +'.old')); From 8723f7ca9000f67fca4664261ce59e9c650feffb Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:14:31 +0100 Subject: [PATCH 028/127] [copy] No `the the` --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index 9565bfc..8f93fe5 100755 --- a/hook +++ b/hook @@ -147,7 +147,7 @@ hook.run = function runner() { })) return process.exit(0); hook.log([ - 'You\'ve failed to pass all the the git pre-commit hooks.', + 'You\'ve failed to pass all the git pre-commit hooks.', '', 'If you\'re feeling adventurous you can skip the hooks using:', '', From acb4d9737f8e600f6b52519da12efab7d976b8bb Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:27:13 +0100 Subject: [PATCH 029/127] [minor] Formatting --- hook | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hook b/hook index 8f93fe5..2de7312 100755 --- a/hook +++ b/hook @@ -143,7 +143,9 @@ hook.run = function runner() { if (!run.length) return hook.log('No scripts to run. All good.', 0); if (run.every(function execute(script) { - return shell.exec(hook.npm +' run '+ script, { silent: silent }).code === 0; + return shell.exec(hook.npm +' run '+ script, { + silent: silent + }).code === 0; })) return process.exit(0); hook.log([ From 2c918d9db89a99f38578a5576f35fcf96e383452 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:28:43 +0100 Subject: [PATCH 030/127] [ignore] ignore npm-debug.log --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3c3629e..93f1361 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +npm-debug.log From 637608af466d2acca02cc305815e71c046291501 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:29:21 +0100 Subject: [PATCH 031/127] [test] Started on tests. --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4db14c0..8809ba8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "install": "node install.js", - "uninstall": "node uninstall.js" + "uninstall": "node uninstall.js", + "test": "mocha test.js" }, "repository": { "type": "git", @@ -27,6 +28,8 @@ "shelljs": "0.3.x" }, "devDependencies": { + "assume": "1.1.x", + "mocha": "2.1.x", "pre-commit": "git://github.com/observing/pre-commit.git" } } From d8adcbfea81b53b48de54ae9315bc4c6bb192e0c Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:29:54 +0100 Subject: [PATCH 032/127] [test] Minimal test --- test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test.js diff --git a/test.js b/test.js new file mode 100644 index 0000000..b77859b --- /dev/null +++ b/test.js @@ -0,0 +1,10 @@ +describe('pre-commit', function () { + 'use strict'; + + var assume = require('assume') + , pre = require('./hook'); + + it('is exported as an object', function () { + assume(pre).is.a('object'); + }); +}); From 5717b30280c638f00a836242e8fc1eab2e6b90a9 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 00:32:58 +0100 Subject: [PATCH 033/127] [travis] Adding missing travis.yml --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..37579d9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "0.8" + - "0.10" + - "0.11" +before_install: + - "npm install -g npm@1.4.x" From b23b2deb10b2db4bd139a405caef19ef33fddb39 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 13:15:32 +0100 Subject: [PATCH 034/127] [ignore] coverage report --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 93f1361..801e184 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules npm-debug.log +coverage From 324b504e191bd0216b5c4462d4afa08f482c42e7 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:15:08 +0100 Subject: [PATCH 035/127] [ignore] .tern-port --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 801e184..8c24345 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules npm-debug.log coverage +.tern-port From 6c24f14f1fce7d008aeb359b677f88ad2bc2f917 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:17:55 +0100 Subject: [PATCH 036/127] [major] Overhauled to create a proper library out of it --- index.js | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..f245cd0 --- /dev/null +++ b/index.js @@ -0,0 +1,256 @@ +'use strict'; + +var shelly = require('shelljs') + , path = require('path') + , util = require('util') + , tty = require('tty'); + +/** + * Representation of a hook runner. + * + * @constructor + * @api public + */ +function Hook(fn) { + if (!this) return new Hook(fn); + + this.config = {}; // pre-commit configuration from the `package.json`. + this.json = {}; // Actual content of the `package.json`. + this.npm = ''; // The location of the `npm` binary. + this.git = ''; // The location of the `git` binary. + this.root = ''; // The root location of the .git folder. + this.status = ''; // Contents of the `git status`. + this.exit = fn; // Exit function. + + this.initialize(); +} + +/** + * Boolean indicating if we're allowed to output progress information into the + * terminal. + * + * @type {Boolean} + * @public + */ +Object.defineProperty(Hook.prototype, 'silent', { + get: function silent() { + return !!this.config.silent; + } +}); + +/** + * Boolean indicating if we're allowed and capable of outputting colors into the + * terminal. + * + * @type {Boolean} + * @public + */ +Object.defineProperty(Hook.prototype, 'colors', { + get: function colors() { + return this.config.colors !== false && tty.isatty(process.stdout.fd); + } +}); + +/** + * Parse the package.json so we can create an normalize it's contents to + * a usable configuration structure. + * + * @api private + */ +Hook.prototype.parse = function parse() { + var pre = this.json['pre-commit'] || this.json.precommit + , config = !Array.isArray(pre) && 'object' === typeof pre ? pre : {}; + + ['silent', 'colors', 'template'].forEach(function each(flag) { + var value; + + if (flag in config) value = config[flag]; + else if ('precommit.'+ flag in this.json) value = this.json['precommit.'+ flag]; + else if ('pre-commit.'+ flag in this.json) value = this.json['pre-commit.'+ flag]; + else return; + + config[flag] = value; + }, this); + + // + // The scripts we need to run can be set under the `run` property. + // + config.run = config.run || pre; + + if ('string' === typeof config.run) config.run = config.run.split(/[, ]+/); + if ( + !Array.isArray(config.run) + && this.json.scripts + && this.json.scripts.test + && this.json.scripts.test !== 'echo "Error: no test specified" && exit 1' + ) { + config.run = ['test']; + } + + this.config = config; +}; + +/** + * Write messages to the terminal, for feedback purposes. + * + * @param {Array} lines The messages that need to be written. + * @param {Number} exit Exit code for the process.exit. + * @api public + */ +Hook.prototype.log = function log(lines, exit) { + if (!Array.isArray(lines)) lines = lines.split('\n'); + if ('number' !== typeof exit) exit = 1; + + var prefix = this.colors + ? '\u001b[38;5;166mpre-commit:\u001b[39;49m ' + : 'pre-commit: '; + + lines.push(''); // Whitespace at the end of the log. + lines.unshift(''); // Whitespace at the beginning. + + lines = lines.map(function map(line) { + return prefix + line; + }); + + if (!this.silent) lines.forEach(function output(line) { + if (exit) console.error(line); + else console.log(line); + }); + + this.exit(exit, lines); + return exit === 0; +}; + +/** + * Initialize all the values of the constructor to see if we can run as an + * pre-commit hook. + * + * @api private + */ +Hook.prototype.initialize = function initialize() { + ['git', 'npm'].forEach(function each(binary) { + try { this[binary] = this.shelly.which(binary); } + catch (e) { return this.log(this.format(Hook.log.binary, binary), 0); } + }, this); + + this.root = this.shelly.exec(this.git +' rev-parse --show-toplevel', { + silent: true + }); + + this.status = this.shelly.exec(this.git +' status --porcelain', { + silent: true + }); + + if (this.status.code) return this.log(Hook.log.status, 0); + if (this.root.code) return this.log(Hook.log.root, 0); + + this.status = this.status.output.trim(); + this.root = this.root.output.trim(); + + // + // If there are no changes in the status we should just simply bail out here. + // There's no need to continue with parsing of the `package.json` + // + if (!this.status.length) return this.log(Hook.log.empty, 0); + + try { + this.json = require(path.join(this.root, 'package.json')); + this.parse(); + } catch (e) { return this.log(this.format(Hook.log.json, e.message), 0); } + + // + // If we have a git template we should configure it before checking for + // scripts so it will still be applied even if we don't have anything to + // execute. + // + if (this.config.template) { + this.shell.exec(this.git +' config commit.template "'+ this.config.template +'"', { + silent: true + }); + } + + if (!this.config.run) return this.log(Hook.log.run, 0); +}; + +/** + * Run the specified hooks. + * + * @api public + */ +Hook.prototype.run = function runner() { + if (this.config.run.every(function execute(script) { + var result = this.shelly.exec(this.npm +' --silent run '+ script, { + silent: this.silent + }); + + if (result.code) return this.log(this.format(Hook.log.failure, script, result.code)); + return result.code === 0; + }, this)) return this.exit(0); +}; + +/** + * Expose some of our internal tools so plugins can also re-use them for their + * own processing. + * + * @type {Function} + * @public + */ +Hook.prototype.format = util.format; +Hook.prototype.shelly = shelly; + +/** + * The various of error and status messages that we can output. + * + * @type {Object} + * @private + */ +Hook.log = { + binary: [ + 'Failed to locate the `%s` binary, make sure it\'s installed in your $PATH.', + 'Skipping the pre-commit hook.' + ].join('\n'), + + status: [ + 'Failed to retrieve the `git status` from the project.', + 'Skipping the pre-commit hook.' + ].join('\n'), + + root: [ + 'Failed to find the root of this git repository, cannot locate the `package.json`.', + 'Skipping the pre-commit hook.' + ].join('\n'), + + empty: [ + 'No changes detected.', + 'Skipping the pre-commit hook.' + ].join('\n'), + + json: [ + 'Received an error while parsing or locating the `package.json` file:', + '', + ' %s', + '', + 'Skipping the pre-commit hook.' + ].join('\n'), + + run: [ + 'We have nothing pre-commit hooks to run. Either you\'re missing the `scripts`', + 'in your `package.json` or have configured pre-commit to run nothing.', + 'Skipping the pre-commit hook.' + ].join('\n'), + + failure: [ + 'We\'ve failed to pass the specified git pre-commit hooks as the `%s`', + 'hook returned an exit code (%d). If you\'re feeling adventurous you can', + 'skip the git pre-commit hooks by commiting using:', + '', + ' git commit -n (or --no-verify)', + '', + 'Obviously this is not advised as you clearly broke things..' + ].join('\n') +}; + +// +// Expose the Hook instance so we can use it for testing purposes. +// +module.exports = Hook; From f9a0cb5c2148d823602cd0e8192177d0f5da9d29 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:19:38 +0100 Subject: [PATCH 037/127] [major] Use the absolutely minimal hook --- hook | 165 +++-------------------------------------------------------- 1 file changed, 6 insertions(+), 159 deletions(-) diff --git a/hook b/hook index 2de7312..4662079 100755 --- a/hook +++ b/hook @@ -2,164 +2,11 @@ 'use strict'; -var child = require('child_process') - , format = require('util').format - , shell = require('shelljs') - , hook = module.exports = {} - , path = require('path'); +var Hook = require('./') + , hook; -/** - * The contents of the `package.json` - * - * @type {Object} - * @public - */ -hook.json = {}; +hook = new Hook(function cli(code) { + process.exit(code); +}); -/** - * Location of the `npm` binary. Will be set to the `absolute` path during - * initialization. - * - * @type {String} - * @public - */ -hook.npm = ''; - -/** - * Location of the `git` binary. Will be set to the `absolute` path during - * initialization. - * - * @type {String} - * @public - */ -hook.git = ''; - -/** - * Helper log function which will prefix all output with the name of our module - * so the users know which module is responsible for the output. - * - * @param {Array} lines The lines that needs to be logged to the user. - * @param {Number} exit Exit code. - * @api public - */ -hook.log = function log(lines, exit) { - if (!Array.isArray(lines)) lines = lines.split('\n'); - if ('number' !== typeof exit) exit = 1; - - lines = lines.map(function map(line) { - return 'pre-commit: '+ line; - }); - - lines.push(''); // Whitespace at the end of the log. - lines.unshift(''); // Whitespace at the beginning. - - if (!hook.json['pre-commit.silent']) lines.forEach(function output(line) { - if (exit) console.error(line); - else console.log(line); - }); - - process.exit(exit); -}; - -hook.initialize = function initialize() { - var failure = 'Failed to locate the `%s` binary due to an error: %s' - , template - , status - , root; - - try { hook.git = shell.which('git'); } - catch (e) { return hook.log(format(failure, 'git', e.message)); } - - try { hook.npm = shell.which('npm'); } - catch (e) { return hook.log(format(failure, 'npm', e.message)); } - - root = shell.exec(hook.git +' rev-parse --show-toplevel', { silent: true }); - status = shell.exec(hook.git +' status --porcelain', { silent: true }); - - // - // Process the output of the git hook's. - // - if (root.code) return hook.log('Failed to get `.git` root: '+ root.output); - if (status.code) return hook.log('Failed to get `get status`: '+ status.output); - - hook.root = root.output.trim(); - hook.status = status.output.trim(); - - try { hook.json = require(path.join(hook.root, 'package.json')); } - catch (e) { return hook.log('Failed to parse `package.json`: '+ e.message); } - - // - // Check for changes to ensure that we don't run our hooks for nothing. - // - if (!hook.status.length) { - return hook.log('No changes detected. Continuing.', 0); - } - - // - // If we have a git template we should configure it before checking for - // scripts so it will still be applied even if we don't have anything to - // execute. - // - if (template = hook.json['pre-commit.commit-template']) { - shell.exec(hook.git +' config commit.template "'+ template +'"', { - silent: true - }); - } - - if (!hook.json.scripts) { - return hook.log('Missing `scripts` in `package.json`. Continuing.', 0); - } - - hook.run(); -}; - -/** - * Run the hooks. - * - * @api private - */ -hook.run = function runner() { - var silent = !!hook.json['pre-commit.silent'] - , pre = hook.json['pr-commit'] - , run = []; - - if ('string' === typeof pre) pre = pre.split(/[, ]+/); - - // - // If we have scripts set in our `pre-commit` field we should run those. If - // they are not available we need to check if `test` is set to something - // sensible so we can use that as default fallback. - // - if (Array.isArray(pre)) { - Array.prototype.push.apply(run, pre); - } else if ( - hook.json.scripts - && hook.json.scripts.test - && hook.json.scripts.test !== 'echo "Error: no test specified" && exit 1' - ) { - run.push('test'); - } - - if (!run.length) return hook.log('No scripts to run. All good.', 0); - - if (run.every(function execute(script) { - return shell.exec(hook.npm +' run '+ script, { - silent: silent - }).code === 0; - })) return process.exit(0); - - hook.log([ - 'You\'ve failed to pass all the git pre-commit hooks.', - '', - 'If you\'re feeling adventurous you can skip the hooks using:', - '', - ' git commit -n (or --no-verify)', - '', - 'But this is obviously not advised as your clearly broke something.' - ]); -}; - -// -// Run the hook if we are not required. -// -if (module === require.main) hook.initialize(); +hook.run(); From cdca5e9fea9e02e7410b656b90fb1012c8f56978 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:19:54 +0100 Subject: [PATCH 038/127] [test] 90%~ coverage, initialization is imposibru to test --- test.js | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 3 deletions(-) diff --git a/test.js b/test.js index b77859b..09343d1 100644 --- a/test.js +++ b/test.js @@ -1,10 +1,253 @@ +/* istanbul ignore next */ describe('pre-commit', function () { 'use strict'; var assume = require('assume') - , pre = require('./hook'); + , Hook = require('./'); - it('is exported as an object', function () { - assume(pre).is.a('object'); + it('is exported as a function', function () { + assume(Hook).is.a('function'); + }); + + it('can be initialized without a `new` keyword', function () { + var hook = Hook(function () {}); + + assume(hook).is.instanceOf(Hook); + assume(hook.parse).is.a('function'); + }); + + describe('#parse', function () { + var hook; + + beforeEach(function () { + hook = new Hook(function () {}); + }); + + it('extracts configuration values from precommit.', function () { + hook.json = { + 'precommit.silent': true + }; + + assume(hook.silent).is.false(); + + hook.parse(); + + assume(hook.config.silent).is.true(); + assume(hook.silent).is.true(); + }); + + it('extracts configuration values from pre-commit.', function () { + hook.json = { + 'pre-commit.silent': true, + 'pre-commit.colors': false + }; + + assume(hook.silent).is.false(); + assume(hook.colors).is.true(); + + hook.parse(); + + assume(hook.config.silent).is.true(); + assume(hook.silent).is.true(); + assume(hook.colors).is.false(); + }); + + it('normalizes the `pre-commit` to an array', function () { + hook.json = { + 'pre-commit': 'test, cows, moo' + }; + + hook.parse(); + + assume(hook.config.run).is.length(3); + assume(hook.config.run).contains('test'); + assume(hook.config.run).contains('cows'); + assume(hook.config.run).contains('moo'); + }); + + it('normalizes the `precommit` to an array', function () { + hook.json = { + 'precommit': 'test, cows, moo' + }; + + hook.parse(); + + assume(hook.config.run).is.length(3); + assume(hook.config.run).contains('test'); + assume(hook.config.run).contains('cows'); + assume(hook.config.run).contains('moo'); + }); + + it('allows `pre-commit` object based syntax', function () { + hook.json = { + 'pre-commit': { + run: 'test scripts go here', + silent: true, + colors: false + } + }; + + hook.parse(); + + assume(hook.config.run).is.length(4); + assume(hook.config.run).contains('test'); + assume(hook.config.run).contains('scripts'); + assume(hook.config.run).contains('go'); + assume(hook.config.run).contains('here'); + assume(hook.silent).is.true(); + assume(hook.colors).is.false(); + }); + + it('defaults to `test` if nothing is specified', function () { + hook.json = { + scripts: { + test: 'mocha test.js' + } + }; + + hook.parse(); + assume(hook.config.run).deep.equals(['test']); + }); + + it('ignores the default npm.script.test placeholder', function () { + hook.json = { + scripts: { + test: 'echo "Error: no test specified" && exit 1' + } + }; + + hook.parse(); + assume(hook.config.run).has.length(0); + }); + }); + + describe('#log', function () { + it('prefixes the logs with `pre-commit`', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(1); + assume(lines).is.a('array'); + + assume(lines[0]).includes('pre-commit'); + assume(lines[1]).includes('pre-commit'); + assume(lines[1]).includes('foo'); + assume(lines).has.length(3); + + // color prefix check + lines.forEach(function (line) { + assume(line).contains('\u001b'); + }); + + next(); + }); + + hook.config.silent = true; + hook.log(['foo']); + }); + + it('allows for a custom error code', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(0); + + next(); + }); + + hook.config.silent = true; + hook.log(['foo'], 0); + }); + + it('allows strings to be split \\n', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(0); + + assume(lines).has.length(4); + assume(lines[1]).contains('foo'); + assume(lines[2]).contains('bar'); + + next(); + }); + + hook.config.silent = true; + hook.log('foo\nbar', 0); + }); + + it('does not output colors when configured to do so', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(0); + + lines.forEach(function (line) { + assume(line).does.not.contain('\u001b'); + }); + + next(); + }); + + hook.config.silent = true; + hook.config.colors = false; + + hook.log('foo\nbar', 0); + }); + + it('output lines to stderr if error code 1', function (next) { + var err = console.error; + next = assume.plan(4, next); + + var hook = new Hook(function (code, lines) { + console.error = err; + next(); + }); + + console.error = function (line) { + assume(line).contains('pre-commit: '); + }; + + hook.config.colors = false; + hook.log('foo\nbar', 1); + }); + + it('output lines to stdout if error code 0', function (next) { + var log = console.log; + next = assume.plan(4, next); + + var hook = new Hook(function (code, lines) { + console.log = log; + next(); + }); + + console.log = function (line) { + assume(line).contains('pre-commit: '); + }; + + hook.config.colors = false; + hook.log('foo\nbar', 0); + }); + }); + + describe('#run', function () { + it('runs the specified scripts and exit with 0 on no error', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(0); + assume(lines).is.undefined(); + + next(); + }); + + hook.config.run = ['example-pass']; + hook.run(); + }); + + it('runs the specified test and exits with 1 on error', function (next) { + var hook = new Hook(function (code, lines) { + assume(code).equals(1); + + assume(lines).is.a('array'); + assume(lines[1]).contains('`example-fail`'); + assume(lines[2]).contains('code (1)'); + + next(); + }); + + hook.config.run = ['example-fail']; + hook.run(); + }); }); }); From 73c70ee6c2fac4c7ee7f6221e15a0bd2c1e9bae7 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:20:13 +0100 Subject: [PATCH 039/127] [pkg] Adding test coverage and fixture hooks. --- package.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8809ba8..372195d 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,13 @@ "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { + "coverage": "istanbul cover ./node_modules/.bin/_mocha -- test.js", + "example-fail": "echo \"This is the example hook, I exit with 1\" && exit 1", + "example-pass": "echo \"This is the example hook, I exit with 0\" && exit 0", "install": "node install.js", - "uninstall": "node uninstall.js", - "test": "mocha test.js" + "test": "mocha test.js", + "test-travis": "istanbul cover node_modules/.bin/_mocha --report lcovonly -- test.js", + "uninstall": "node uninstall.js" }, "repository": { "type": "git", @@ -29,6 +33,7 @@ }, "devDependencies": { "assume": "1.1.x", + "istanbul": "0.3.x", "mocha": "2.1.x", "pre-commit": "git://github.com/observing/pre-commit.git" } From fba9a47182d29220df8744db033be3d5b9341eec Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:25:45 +0100 Subject: [PATCH 040/127] [fix] Read config before output --- index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index f245cd0..be387fb 100644 --- a/index.js +++ b/index.js @@ -147,17 +147,17 @@ Hook.prototype.initialize = function initialize() { this.status = this.status.output.trim(); this.root = this.root.output.trim(); - // - // If there are no changes in the status we should just simply bail out here. - // There's no need to continue with parsing of the `package.json` - // - if (!this.status.length) return this.log(Hook.log.empty, 0); - try { this.json = require(path.join(this.root, 'package.json')); this.parse(); } catch (e) { return this.log(this.format(Hook.log.json, e.message), 0); } + // + // We can only check for changes after we've parsed the package.json as it + // contains information if we need to suppress the empty message or not. + // + if (!this.status.length) return this.log(Hook.log.empty, 0); + // // If we have a git template we should configure it before checking for // scripts so it will still be applied even if we don't have anything to From 9ca3fd74fba294b0611e64ededa411f80ae4f25d Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:33:29 +0100 Subject: [PATCH 041/127] [test] Ignore current repo status to prevent early calling of fn This generated false positives in our test suite as the test suite is ran against an empty status on travis-ci and most likely on a full git status in development --- index.js | 28 +++++++++++++++++----------- test.js | 24 ++++++++++++++---------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/index.js b/index.js index be387fb..1591424 100644 --- a/index.js +++ b/index.js @@ -9,18 +9,22 @@ var shelly = require('shelljs') * Representation of a hook runner. * * @constructor + * @param {Function} fn Function to be called when we want to exit + * @param {Object} options Optional configuration, primarily used for testing. * @api public */ -function Hook(fn) { - if (!this) return new Hook(fn); - - this.config = {}; // pre-commit configuration from the `package.json`. - this.json = {}; // Actual content of the `package.json`. - this.npm = ''; // The location of the `npm` binary. - this.git = ''; // The location of the `git` binary. - this.root = ''; // The root location of the .git folder. - this.status = ''; // Contents of the `git status`. - this.exit = fn; // Exit function. +function Hook(fn, options) { + if (!this) return new Hook(fn, options); + options = options || {}; + + this.options = options; // Used for testing only. Ignore this. Don't touch. + this.config = {}; // pre-commit configuration from the `package.json`. + this.json = {}; // Actual content of the `package.json`. + this.npm = ''; // The location of the `npm` binary. + this.git = ''; // The location of the `git` binary. + this.root = ''; // The root location of the .git folder. + this.status = ''; // Contents of the `git status`. + this.exit = fn; // Exit function. this.initialize(); } @@ -156,7 +160,9 @@ Hook.prototype.initialize = function initialize() { // We can only check for changes after we've parsed the package.json as it // contains information if we need to suppress the empty message or not. // - if (!this.status.length) return this.log(Hook.log.empty, 0); + if (!this.status.length && !this.options.ignorestatus) { + return this.log(Hook.log.empty, 0); + } // // If we have a git template we should configure it before checking for diff --git a/test.js b/test.js index 09343d1..829e17f 100644 --- a/test.js +++ b/test.js @@ -10,7 +10,9 @@ describe('pre-commit', function () { }); it('can be initialized without a `new` keyword', function () { - var hook = Hook(function () {}); + var hook = Hook(function () {}, { + ignorestatus: true + }); assume(hook).is.instanceOf(Hook); assume(hook.parse).is.a('function'); @@ -20,7 +22,9 @@ describe('pre-commit', function () { var hook; beforeEach(function () { - hook = new Hook(function () {}); + hook = new Hook(function () {}, { + ignorestatus: true + }); }); it('extracts configuration values from precommit.', function () { @@ -138,7 +142,7 @@ describe('pre-commit', function () { }); next(); - }); + }, { ignorestatus: true }); hook.config.silent = true; hook.log(['foo']); @@ -149,7 +153,7 @@ describe('pre-commit', function () { assume(code).equals(0); next(); - }); + }, { ignorestatus: true }); hook.config.silent = true; hook.log(['foo'], 0); @@ -164,7 +168,7 @@ describe('pre-commit', function () { assume(lines[2]).contains('bar'); next(); - }); + }, { ignorestatus: true }); hook.config.silent = true; hook.log('foo\nbar', 0); @@ -179,7 +183,7 @@ describe('pre-commit', function () { }); next(); - }); + }, { ignorestatus: true }); hook.config.silent = true; hook.config.colors = false; @@ -194,7 +198,7 @@ describe('pre-commit', function () { var hook = new Hook(function (code, lines) { console.error = err; next(); - }); + }, { ignorestatus: true }); console.error = function (line) { assume(line).contains('pre-commit: '); @@ -211,7 +215,7 @@ describe('pre-commit', function () { var hook = new Hook(function (code, lines) { console.log = log; next(); - }); + }, { ignorestatus: true }); console.log = function (line) { assume(line).contains('pre-commit: '); @@ -229,7 +233,7 @@ describe('pre-commit', function () { assume(lines).is.undefined(); next(); - }); + }, { ignorestatus: true }); hook.config.run = ['example-pass']; hook.run(); @@ -244,7 +248,7 @@ describe('pre-commit', function () { assume(lines[2]).contains('code (1)'); next(); - }); + }, { ignorestatus: true }); hook.config.run = ['example-fail']; hook.run(); From 8c6d6e1551505036927c976ca0e72e076ffb08d6 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:37:37 +0100 Subject: [PATCH 042/127] [doc] Adding badges --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 822d64a..d5809ad 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # pre-commit +[![Version npm][version]](http://browsenpm.org/package/pre-commit)[![Build Status][build]](https://travis-ci.org/observing/pre-commit)[![Dependencies][david]](https://david-dm.org/observing/pre-commit)[![Coverage Status][cover]](https://coveralls.io/r/observing/pre-commit?branch=master) + +[version]: http://img.shields.io/npm/v/pre-commit.svg?style=flat-square +[build]: http://img.shields.io/travis/observing/pre-commit/master.svg?style=flat-square +[david]: https://img.shields.io/david/observing/pre-commit.svg?style=flat-square +[cover]: http://img.shields.io/coveralls/observing/pre-commit/master.svg?style=flat-square + A simple `pre-commit` hook installer for `git`. This will ensure that your test suite passes before you can commit your changes. In addition to running your `npm test` it also has the option to run custom scripts that you have From b9d23686be7100e6a2238d1a7762f6ea89686fbb Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 14:37:44 +0100 Subject: [PATCH 043/127] [travis] barf coverall information --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 37579d9..b532c0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,7 @@ node_js: - "0.11" before_install: - "npm install -g npm@1.4.x" +script: + - "npm run test-travis" +after_script: + - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls" From 7a4ac49c30c47ca250a5575180dea70ec08e8db9 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 15:12:13 +0100 Subject: [PATCH 044/127] [fix] Allow index.js to run as hook --- index.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/index.js b/index.js index 1591424..236c9f7 100644 --- a/index.js +++ b/index.js @@ -260,3 +260,14 @@ Hook.log = { // Expose the Hook instance so we can use it for testing purposes. // module.exports = Hook; + +// +// Run directly if we're required executed directly through the CLI +// +if (module !== require.main) return; + +var hook = new Hook(function cli(code) { + process.exit(code); +}); + +hook.run(); From ceaf03eb62bbf259778887f2bab6e97450089dd8 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 15:12:26 +0100 Subject: [PATCH 045/127] [fix] Use pure bash for finding things. The `git` binary of windows ships with a modified port of bash so we can safely execute this on windows. The `which` will help make the hooks run under: - Nodejs. - Linux's namespaced `nodejs` binary. - And iojs when no nodejs symlink exists. In addition to that it should also fix #13 #12 --- hook | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/hook b/hook index 4662079..6095b34 100755 --- a/hook +++ b/hook @@ -1,12 +1,13 @@ -#!/usr/bin/env node - -'use strict'; - -var Hook = require('./') - , hook; - -hook = new Hook(function cli(code) { - process.exit(code); -}); - -hook.run(); +#!/bin/bash + +NODE=`which node` +NODEJS=`which nodejs` +IOJS=`which iojs` + +if [[ -n $NODE ]]; then + $NODE ./index.js +elif [[ -n $NODEJS ]]; then + $NODEJS ./index.js +elif [[ -n $IOJS ]]; then + $IOJS ./index.js +fi From 8712ce6eda5144eb5f81bf8c264b3f93d5d3eee1 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 16:08:00 +0100 Subject: [PATCH 046/127] [minor] Use async spawns so the stdout of the scripts is the same. This is important so we can show the same colors and output of the scripts that we're currently running. The `--silent` flag is enabled by default to disable npm bullshit that is barfed in to the console otherwise. --- index.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 236c9f7..bd9fd67 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ 'use strict'; -var shelly = require('shelljs') +var spawn = require('child_process').spawn + , shelly = require('shelljs') , path = require('path') , util = require('util') , tty = require('tty'); @@ -184,14 +185,23 @@ Hook.prototype.initialize = function initialize() { * @api public */ Hook.prototype.run = function runner() { - if (this.config.run.every(function execute(script) { - var result = this.shelly.exec(this.npm +' --silent run '+ script, { - silent: this.silent - }); + var hooked = this; + + (function again(scripts) { + if (!scripts.length) return hooked.exit(0); + + var script = scripts.shift(); - if (result.code) return this.log(this.format(Hook.log.failure, script, result.code)); - return result.code === 0; - }, this)) return this.exit(0); + spawn(hooked.npm, ['run', script, '--silent'], { + env: process.env, + cwd: hooked.root, + stdio: [0, 1, 2] + }).once('close', function closed(code) { + if (code) return hooked.log(hooked.format(Hook.log.failure, script, code)); + + again(scripts); + }); + })(hooked.config.run.slice(0)); }; /** From 0eace6225d5a9518d592d35dba4b3227849b707e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 16:11:29 +0100 Subject: [PATCH 047/127] [copy] wording --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index bd9fd67..d759667 100644 --- a/index.js +++ b/index.js @@ -258,7 +258,7 @@ Hook.log = { failure: [ 'We\'ve failed to pass the specified git pre-commit hooks as the `%s`', 'hook returned an exit code (%d). If you\'re feeling adventurous you can', - 'skip the git pre-commit hooks by commiting using:', + 'skip the git pre-commit hooks by adding the following flags to your commit:', '', ' git commit -n (or --no-verify)', '', From bb0a487e3b40bcde43bd599174377222a9e5d61e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 16:22:47 +0100 Subject: [PATCH 048/127] [minor] Adding code comments --- index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/index.js b/index.js index d759667..9b6a958 100644 --- a/index.js +++ b/index.js @@ -192,6 +192,14 @@ Hook.prototype.run = function runner() { var script = scripts.shift(); + // + // There's a reason on why we're using an async `spawn` here instead of the + // `shelly.exec`. The sync `exec` is a hack that writes writes a file to + // disk and they poll with sync fs calls to see for results. The problem is + // that the way they capture the output which us using input redirection and + // this doesn't have the required `isAtty` information that libraries use to + // output colors resulting in script output that doesn't have any color. + // spawn(hooked.npm, ['run', script, '--silent'], { env: process.env, cwd: hooked.root, From 9e4131dc7780ab5af7b9e36df66a89e55526988b Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 21:29:45 +0100 Subject: [PATCH 049/127] [doc] Rework documentation --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index d5809ad..97659a8 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,18 @@ [david]: https://img.shields.io/david/observing/pre-commit.svg?style=flat-square [cover]: http://img.shields.io/coveralls/observing/pre-commit/master.svg?style=flat-square -A simple `pre-commit` hook installer for `git`. This will ensure that your -test suite passes before you can commit your changes. In addition to running -your `npm test` it also has the option to run custom scripts that you have -specified in your `package.json`. +**pre-commit** is a pre-commit hook installer for `git`. It will ensure that +your `npm test` (or other specified scripts) passes before you can commit your +changes. This all conveniently configured in your package.json. + +But don't worry, you can still force a commit by telling `git` to skip the +`pre-commit` hooks by simply committing using `--no-verify`. ### Installation -It's advised to install this module as `devDependency` in your `package.json` -file so it doesn't get installed on production servers. Run: +It's advised to install the **pre-commit** module as a `devDependencies` in your +`package.json` as you only need this for development purposes. To install the +module simply run: ``` npm install --save-dev pre-commit @@ -23,20 +26,26 @@ npm install --save-dev pre-commit To install it as `devDependency`. When this module is installed it will override the existing `pre-commit` file in your `.git/hooks` folder. Existing -`pre-commit` hooks will be backed up. +`pre-commit` hooks will be backed up as `pre-commit.old` in the same repository. ### Configuration -`pre-commit` will try to run your `npm test` command by default. It does this by -running `npm run test` in the root of your git repository. It will only run that -command if it's not the default values that are entered when you issue an `npm -init`. +`pre-commit` will try to run your `npm test` command in the root of the git +repository by default unless it's the default value that is set by the `npm +init` script. But `pre-commit` is not limited to just running your `npm test`'s during the commit hook. It's also capable of running every other script that you've -specified in your `package.json` "scripts" field. The only thing you need to do -is add a `pre-commit` array to your `package.json` that specifies which scripts -you want to have ran and in which order: +specified in your `package.json` "scripts" field. So before people commit you +could ensure that: + +- You have 100% coverage +- All stying passes. +- JSHint passes. +- Contribution licenses signed etc. + +The only thing you need to do is add a `pre-commit` array to your `package.json` +that specifies which scripts you want to have ran and in which order: ```js { @@ -45,33 +54,74 @@ you want to have ran and in which order: "description": "ERROR: No README.md file found!", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "echo \"Error: I SHOULD FAIL LOLOLOLOLOL \" && exit 1", "foo": "echo \"fooo\" && exit 0", "bar": "echo \"bar\" && exit 0" }, - "repository": { - "type": "git", - "url": "https://gist.github.com/437464d0899504fb6b7b.git" - }, "pre-commit": [ "foo", "bar", "test" - ], - "author": "", - "license": "BSD", - "gitHead": "6637d0771c3a89c4a60be087859dee5130f7a104" + ] } ``` In the example above, it will first run: `npm run foo` then `npm run bar` and finally `npm run test` which will make the commit fail as it returns the error -code `1`. +code `1`. If you prefer strings over arrays or `precommit` without a middle +dash, that also works: + +```js +{ + "precommit": "foo, bar, test" + "pre-commit": "foo, bar, test" + "pre-commit": ["foo", "bar", "test"] + "precommit": ["foo", "bar", "test"], + "precommit": { + "run": "foo, bar, test", + }, + "pre-commit": { + "run": ["foo", "bar", "test"], + }, + "precommit": { + "run": ["foo", "bar", "test"], + }, + "pre-commit": { + "run": "foo, bar, test", + } +} +``` + +The examples above are all the same. In addition to configuring which scripts +should be ran you can also configure the following options: + +- **silent** Don't output the prefixed `pre-commit:` messages when things fail + or when we have nothing to run. Should a boolean. +- **colors** Don't output colors when we write messages. Should be a boolean. +- **template** Path to a file who's content should be used as template for the + git commit body. -To learn more about the scripts, please read the official `npm` documentation: +These options can either be added in the `pre-commit`/`precommit` object as keys +or as `"pre-commit.{key}` key properties in the `package.json`: + +```js +{ + "precommit.silent": true, + "pre-commit": { + "silent": true + } +} +``` + +It's all the same. Different styles so use what matches your project. To learn +more about the scripts, please read the official `npm` documentation: https://npmjs.org/doc/scripts.html +And to learn more about git hooks read: + +http://githooks.com + ### License MIT From 94ea620a159c7a7ef3752e646693fd6ef829920e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 21:36:36 +0100 Subject: [PATCH 050/127] [dist] 1.0.0 --- CHANGELOG.md | 14 +++++++++++++- package.json | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f16685a..38c0987 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 1.0 +- Create symlinks instead of a copying the hook file so we can depend on + modules. +- More readable output messages. +- Lookup git and npm using `which`. +- Allow nodejs, node and iojs to call the the hook. +- Refactored the way options can be passed in to pre-commit, we're now allowing + objects. +- The refactor made it possible to test most of the internals so we now have + 90%+ coverage. +- And the list goes on. + ## 0.0.9 - Added missing uninstall hook to remove and restore old scripts. @@ -20,7 +32,7 @@ - Improved output formatting. ## 0.0.3 -- Added compatiblity for Node.js 0.6 by falling back to path.existsSync. +- Added compatibility for Node.js 0.6 by falling back to path.existsSync. ## 0.0.2 - Fixed a typo in the output, see #1. diff --git a/package.json b/package.json index 372195d..e3d8c03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "0.0.11", + "version": "1.0.0", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From e6baa507eb7370eee3eb97e7dd555804918b06f3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 22:14:29 +0100 Subject: [PATCH 051/127] [fix] `./index` pointed to your own `index.js` file instead of the pre-commit index --- hook | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hook b/hook index 6095b34..e466263 100755 --- a/hook +++ b/hook @@ -5,9 +5,9 @@ NODEJS=`which nodejs` IOJS=`which iojs` if [[ -n $NODE ]]; then - $NODE ./index.js + $NODE $($NODE -e "console.log(require.resolve('pre-commit'))") elif [[ -n $NODEJS ]]; then - $NODEJS ./index.js + $NODEJS $($NODEJS -e "console.log(require.resolve('pre-commit'))") elif [[ -n $IOJS ]]; then - $IOJS ./index.js + $IOJS $($IOJS -e "console.log(require.resolve('pre-commit'))") fi From 1f744a07f023ab4129b5bbe29dc45fa41c11f045 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 22:16:20 +0100 Subject: [PATCH 052/127] [doc] 1.0.1 change log --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38c0987..3dae6ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 +- Corrected the `hook` file so it doesn't attempt to run **your** index.js but + **ours** instead. + ## 1.0 - Create symlinks instead of a copying the hook file so we can depend on modules. From 35f1a48fab15a4cf1ce72d4c12bc8a64b16c2f8a Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 30 Jan 2015 22:16:38 +0100 Subject: [PATCH 053/127] [dist] 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3d8c03..ee79e82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.0", + "version": "1.0.1", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From cefaa08c96889462e4f6eb3bc21fcc56bbdc1c17 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 2 Feb 2015 12:40:07 +0100 Subject: [PATCH 054/127] [minor] Check against `/usr/local/bin` if nothing in the path exists. Fixes #13 --- hook | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hook b/hook index e466263..fdb7b3c 100755 --- a/hook +++ b/hook @@ -3,6 +3,7 @@ NODE=`which node` NODEJS=`which nodejs` IOJS=`which iojs` +LOCAL="/usr/local/bin/node" if [[ -n $NODE ]]; then $NODE $($NODE -e "console.log(require.resolve('pre-commit'))") @@ -10,4 +11,6 @@ elif [[ -n $NODEJS ]]; then $NODEJS $($NODEJS -e "console.log(require.resolve('pre-commit'))") elif [[ -n $IOJS ]]; then $IOJS $($IOJS -e "console.log(require.resolve('pre-commit'))") +elif [[ -x $LOCAL ]]; then + $LOCAL $($LOCAL -e "console.log(require.resolve('pre-commit'))") fi From b534291a221f13ab6b111eed8f733b07d006e01c Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 2 Feb 2015 12:54:53 +0100 Subject: [PATCH 055/127] [dist] 1.0.2 --- CHANGELOG.md | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dae6ff..8ebb32d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.0.2 +- Check `/usr/local/bin/node` if we cannot find the binaries in the PATH. + ## 1.0.1 - Corrected the `hook` file so it doesn't attempt to run **your** index.js but **ours** instead. diff --git a/package.json b/package.json index ee79e82..4be5011 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.1", + "version": "1.0.2", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From ee54523213893291205ffd091fae7613a680c0df Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 9 Feb 2015 16:31:49 +0100 Subject: [PATCH 056/127] [fix] Adding missing license file --- LICENSE | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b68d272 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + From 9caf9fb7d32399790016579b0ba123555a2553a9 Mon Sep 17 00:00:00 2001 From: Alex Indigo Date: Thu, 12 Feb 2015 20:47:34 -0800 Subject: [PATCH 057/127] Make it work when node or npm not in the PATH --- index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/index.js b/index.js index 9b6a958..0802be7 100644 --- a/index.js +++ b/index.js @@ -138,6 +138,18 @@ Hook.prototype.initialize = function initialize() { catch (e) { return this.log(this.format(Hook.log.binary, binary), 0); } }, this); + // in GUI clients node and npm are not in the PATH + // so get node binery PATH, add it to the PATH list + // and try again + if (!this.npm) { + try { + process.env.PATH += ':' + path.dirname(process.env['_']); + this.npm = this.shelly.which('npm'); + } catch (e) { + return this.log(this.format(Hook.log.binary, 'npm'), 0); + } + } + this.root = this.shelly.exec(this.git +' rev-parse --show-toplevel', { silent: true }); From 2920d120eb93c2b6a042371b72ebc01081c18e2b Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 13 Feb 2015 09:39:27 +0100 Subject: [PATCH 058/127] [fix] Use path.delimiter for modifying the evn.PATH so it works on all systems. [fix] Also bailout if we cannot find the binary. [fix] Only output the npm error once. --- index.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 0802be7..a4cad21 100644 --- a/index.js +++ b/index.js @@ -135,21 +135,27 @@ Hook.prototype.log = function log(lines, exit) { Hook.prototype.initialize = function initialize() { ['git', 'npm'].forEach(function each(binary) { try { this[binary] = this.shelly.which(binary); } - catch (e) { return this.log(this.format(Hook.log.binary, binary), 0); } + catch (e) {} }, this); - // in GUI clients node and npm are not in the PATH - // so get node binery PATH, add it to the PATH list - // and try again + // + // in GUI clients node and npm are not in the PATH so get node binary PATH, + // add it to the PATH list and try again. + // if (!this.npm) { try { - process.env.PATH += ':' + path.dirname(process.env['_']); + process.env.PATH += path.delimiter + path.dirname(process.env._); this.npm = this.shelly.which('npm'); } catch (e) { return this.log(this.format(Hook.log.binary, 'npm'), 0); } } + // + // Also bail out if we cannot find the git binary. + // + if (!this.git) return this.log(this.format(Hook.log.binary, 'git'), 0); + this.root = this.shelly.exec(this.git +' rev-parse --show-toplevel', { silent: true }); From aec21f600221e976574a3e0f9e79c76469c385c6 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 13 Feb 2015 09:40:32 +0100 Subject: [PATCH 059/127] [dist] 1.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4be5011..1b77e34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.2", + "version": "1.0.3", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From a9220ee8f0a44497a08146dc9f30329e80bde4b7 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sat, 14 Feb 2015 18:45:08 +0100 Subject: [PATCH 060/127] [fix] Don't mess up installation because we failed to add a hook. --- install.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/install.js b/install.js index aa378ca..3624b25 100644 --- a/install.js +++ b/install.js @@ -32,11 +32,11 @@ if (!exists(hooks)) fs.mkdirSync(hooks); // important. // if (exists(precommit) && !fs.lstatSync(precommit).isSymbolicLink()) { - console.log(''); + console.log('pre-commit:'); console.log('pre-commit: Detected an existing git pre-commit hook'); fs.writeFileSync(precommit +'.old', fs.readFileSync(precommit)); console.log('pre-commit: Old pre-commit hook backuped to pre-commit.old'); - console.log(''); + console.log('pre-commit:'); } // @@ -46,4 +46,16 @@ if (exists(precommit) && !fs.lstatSync(precommit).isSymbolicLink()) { try { fs.unlinkSync(precommit); } catch (e) {} -fs.symlinkSync(hook, precommit, 'file'); +// +// It could be that we do not have rights to this folder which could cause the +// installation of this module to completely fail. We should just output the +// error instead destroying the whole npm install process. +// +try { fs.symlinkSync(hook, precommit, 'file'); } +catch (e) { + console.error('pre-commit:'); + console.error('pre-commit: Failed to symlink the hook file in your .git/hooks folder because:'); + console.error('pre-commit: '+ e.message); + console.error('pre-commit: The hook was not installed.'); + console.error('pre-commit:'); +} From d60c708f57ac0e62df54b03b4bfc0fb35f955519 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sat, 14 Feb 2015 18:46:46 +0100 Subject: [PATCH 061/127] [dist] 1.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b77e34..5006b3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.3", + "version": "1.0.4", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From d306234121ac0c931fcbf4dc33f30a786dd58751 Mon Sep 17 00:00:00 2001 From: Akiva Levy Date: Tue, 24 Feb 2015 13:53:22 -0800 Subject: [PATCH 062/127] Silence noise from `which` test commands output The current hook causes a lot of unnecessary noise when the hook tries to assign the output of the `which` command to `NODE`, `NODEJS`, `IOJS`, and `LOCAL`: ``` which: no nodejs in (/usr/lib/git-core:/usr/local/sbin:/usr/local/bin:/home/akiva/.nvm/v0.11.16/bin:/home/akiva/.rbenv/bin:/home/akiva/bin:/usr/local/sbin:/usr/local/bin:/home/akiva/.rbenv/shims:/home/akiva/.rbenv/bin:/home/akiva/bin:/usr/local/sbin:/usr/local/bin[33/2763] :/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl) which: no iojs in (/usr/lib/git-core:/usr/local/sbin:/usr/local/bin:/home/akiva/.nvm/v0.11.16/bin:/home/akiva/.rbenv/bin:/home/akiva/bin:/usr/local/sbin:/usr/local/bin:/home/akiva/.rbenv/shims:/home/akiva/.rbenv/bin:/home/akiva/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/ usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl) ``` This silences the results from directly spamming the terminal while still assigning to the `var`s in question. --- hook | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hook b/hook index fdb7b3c..504e1ef 100755 --- a/hook +++ b/hook @@ -1,8 +1,8 @@ #!/bin/bash -NODE=`which node` -NODEJS=`which nodejs` -IOJS=`which iojs` +NODE=`which node 2> /dev/null` +NODEJS=`which nodejs 2> /dev/null` +IOJS=`which iojs 2> /dev/null` LOCAL="/usr/local/bin/node" if [[ -n $NODE ]]; then From afee4aba131096705282ad6b46115841db92d3da Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 24 Feb 2015 15:20:53 -0800 Subject: [PATCH 063/127] [dist] 1.0.5 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5006b3e..fc115cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.4", + "version": "1.0.5", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { @@ -27,6 +27,7 @@ "development" ], "author": "Arnout Kazemier ", + "homepage": "https://github.com/observing/pre-commit", "license": "MIT", "dependencies": { "shelljs": "0.3.x" From 6ecf02c42c55545186784352d06774655e9432cf Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Fri, 27 Feb 2015 14:11:45 -0800 Subject: [PATCH 064/127] This is obviously subjective --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index a4cad21..24890ad 100644 --- a/index.js +++ b/index.js @@ -288,7 +288,7 @@ Hook.log = { '', ' git commit -n (or --no-verify)', '', - 'Obviously this is not advised as you clearly broke things..' + 'This is ill-advised since the commit is broken.' ].join('\n') }; From 06aa0e7e0f3a1d71f4491cd09a0c7f9cd477ff6a Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 27 Feb 2015 14:23:53 -0800 Subject: [PATCH 065/127] [dist] 1.0.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc115cd..afbcf96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.5", + "version": "1.0.6", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From fe9760e6590319434d01ae596d438e7d4dc21ec4 Mon Sep 17 00:00:00 2001 From: Mordy Tikotzky Date: Mon, 27 Apr 2015 22:22:47 -0400 Subject: [PATCH 066/127] fix git templates --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 24890ad..1a41928 100644 --- a/index.js +++ b/index.js @@ -189,7 +189,7 @@ Hook.prototype.initialize = function initialize() { // execute. // if (this.config.template) { - this.shell.exec(this.git +' config commit.template "'+ this.config.template +'"', { + this.shelly.exec(this.git +' config commit.template "'+ this.config.template +'"', { silent: true }); } From 2d405d3fc262e4b6097fce05586322b766c63d38 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 28 Apr 2015 09:01:10 +0200 Subject: [PATCH 067/127] [dist] 1.0.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afbcf96..4178e3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.6", + "version": "1.0.7", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 0c3cadf7ed4524c3a1e2add9f124a56d3e3c0344 Mon Sep 17 00:00:00 2001 From: Donatas Bacius Date: Fri, 1 May 2015 20:07:15 +0100 Subject: [PATCH 068/127] Fixed a bug with runtime paths where the hook would fail to run when there is a space in the path. --- hook | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hook b/hook index 504e1ef..cc6c0b4 100755 --- a/hook +++ b/hook @@ -6,11 +6,11 @@ IOJS=`which iojs 2> /dev/null` LOCAL="/usr/local/bin/node" if [[ -n $NODE ]]; then - $NODE $($NODE -e "console.log(require.resolve('pre-commit'))") + "$NODE" $("$NODE" -e "console.log(require.resolve('pre-commit'))") elif [[ -n $NODEJS ]]; then - $NODEJS $($NODEJS -e "console.log(require.resolve('pre-commit'))") + "$NODEJS" $("$NODEJS" -e "console.log(require.resolve('pre-commit'))") elif [[ -n $IOJS ]]; then - $IOJS $($IOJS -e "console.log(require.resolve('pre-commit'))") + "$IOJS" $("$IOJS" -e "console.log(require.resolve('pre-commit'))") elif [[ -x $LOCAL ]]; then - $LOCAL $($LOCAL -e "console.log(require.resolve('pre-commit'))") + "$LOCAL" $("$LOCAL" -e "console.log(require.resolve('pre-commit'))") fi From 4fdc2927e7a75c8336a71d57fd7bcf314779c9da Mon Sep 17 00:00:00 2001 From: Joseph Lokahi Podwys Date: Tue, 9 Jun 2015 09:39:16 -0600 Subject: [PATCH 069/127] Adding path so pre-commit works well with source tree. --- hook | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hook b/hook index cc6c0b4..695d902 100755 --- a/hook +++ b/hook @@ -1,5 +1,7 @@ #!/bin/bash +source ~/.bash_profile + NODE=`which node 2> /dev/null` NODEJS=`which nodejs 2> /dev/null` IOJS=`which iojs 2> /dev/null` From f0d27fbc2e064645a5df169ee57bdb40cb8e27f5 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 9 Jun 2015 17:59:19 +0200 Subject: [PATCH 070/127] [dist] 1.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4178e3d..b68082d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.7", + "version": "1.0.8", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From cb253345664757b081b52da9cfa0ad35c8067692 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Wed, 10 Jun 2015 11:47:29 +0200 Subject: [PATCH 071/127] [fix] Don't show a warning if there isn't a profile. Fixes #32 --- hook | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hook b/hook index 695d902..0dd8f06 100755 --- a/hook +++ b/hook @@ -1,6 +1,14 @@ #!/bin/bash -source ~/.bash_profile +# +# There are some issues with Source Tree because paths are not set correctly for +# the given environment. Sourcing the bash_profile seems to resolve this for users +# +# https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly +# +if [ -f ~/.bash_profile ]; then + source ~/.bash_profile +fi NODE=`which node 2> /dev/null` NODEJS=`which nodejs 2> /dev/null` From 6bc2bcf46e9d8cd29098355b11b4b783a43c2fe9 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Wed, 10 Jun 2015 11:49:05 +0200 Subject: [PATCH 072/127] [dist] 1.0.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b68082d..04520e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.8", + "version": "1.0.9", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 5b83734862569bb9126dbef21efd8a51dc86e7a3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Wed, 10 Jun 2015 11:54:33 +0200 Subject: [PATCH 073/127] [deps] Bump dependencies for reasons. --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 04520e7..387b0ec 100644 --- a/package.json +++ b/package.json @@ -30,12 +30,12 @@ "homepage": "https://github.com/observing/pre-commit", "license": "MIT", "dependencies": { - "shelljs": "0.3.x" + "shelljs": "0.5.x" }, "devDependencies": { - "assume": "1.1.x", + "assume": "1.2.x", "istanbul": "0.3.x", - "mocha": "2.1.x", + "mocha": "2.2.x", "pre-commit": "git://github.com/observing/pre-commit.git" } } From 4ca372367b73410f78ec31636e2be6716a7e0f5d Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Wed, 10 Jun 2015 12:41:15 +0200 Subject: [PATCH 074/127] Restore support for NVM Fixes #33. --- hook | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hook b/hook index 0dd8f06..89db75d 100755 --- a/hook +++ b/hook @@ -1,12 +1,14 @@ #!/bin/bash +HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> /dev/null` + # # There are some issues with Source Tree because paths are not set correctly for # the given environment. Sourcing the bash_profile seems to resolve this for users # # https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly # -if [ -f ~/.bash_profile ]; then +if [ -z $HAS_NODE ] && [ -f ~/.bash_profile ]; then source ~/.bash_profile fi From d853587531c10c50435287b7fc56f91438312f7a Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Wed, 10 Jun 2015 14:45:01 +0200 Subject: [PATCH 075/127] [dist] 1.0.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 387b0ec..5c36961 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.9", + "version": "1.0.10", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From b30363d1ba8661371181bf047736d29c4c5bae30 Mon Sep 17 00:00:00 2001 From: Swaagie Date: Thu, 30 Jul 2015 11:08:47 +0200 Subject: [PATCH 076/127] [fix] allow whitespace characters --- hook | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hook b/hook index 89db75d..b849890 100755 --- a/hook +++ b/hook @@ -8,7 +8,7 @@ HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> # # https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly # -if [ -z $HAS_NODE ] && [ -f ~/.bash_profile ]; then +if [ -z "$HAS_NODE" ] && [ -f ~/.bash_profile ]; then source ~/.bash_profile fi @@ -17,12 +17,12 @@ NODEJS=`which nodejs 2> /dev/null` IOJS=`which iojs 2> /dev/null` LOCAL="/usr/local/bin/node" -if [[ -n $NODE ]]; then +if [[ -n "$NODE" ]]; then "$NODE" $("$NODE" -e "console.log(require.resolve('pre-commit'))") -elif [[ -n $NODEJS ]]; then +elif [[ -n "$NODEJS" ]]; then "$NODEJS" $("$NODEJS" -e "console.log(require.resolve('pre-commit'))") -elif [[ -n $IOJS ]]; then +elif [[ -n "$IOJS" ]]; then "$IOJS" $("$IOJS" -e "console.log(require.resolve('pre-commit'))") -elif [[ -x $LOCAL ]]; then +elif [[ -x "$LOCAL" ]]; then "$LOCAL" $("$LOCAL" -e "console.log(require.resolve('pre-commit'))") fi From 07e77f6309af42af913e9861d5a15a09e2b0d158 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 11:55:22 +0200 Subject: [PATCH 077/127] [minor] Use cross-spawn instead of spawn to resolve windows issues. Fixes #36 --- index.js | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 1a41928..e399c2e 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ 'use strict'; -var spawn = require('child_process').spawn +var spawn = require('cross-spawn') , shelly = require('shelljs') , path = require('path') , util = require('util') diff --git a/package.json b/package.json index 5c36961..e3339e0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "homepage": "https://github.com/observing/pre-commit", "license": "MIT", "dependencies": { + "cross-spawn": "2.0.x", "shelljs": "0.5.x" }, "devDependencies": { From 21e2d35117d842c46f74d27f3c602cee13457fb4 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 12:01:57 +0200 Subject: [PATCH 078/127] [travis] Added Node 0.12 and iojs --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b532c0c..8f4f8e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,14 @@ language: node_js node_js: - - "0.8" + - "0.12" - "0.10" - - "0.11" + - "0.8" + - "iojs" before_install: - "npm install -g npm@1.4.x" script: - "npm run test-travis" after_script: - "npm install coveralls@2.11.x && cat coverage/lcov.info | coveralls" +matrix: + fast_finish: true From 0260c2095c6498b44fae2ed6f76990f37a16058e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 14:17:18 +0200 Subject: [PATCH 079/127] [minor] Added support for a `--dry-run` to see if the hook can execute without any sideaffects --- hook | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/hook b/hook index b849890..66debda 100755 --- a/hook +++ b/hook @@ -16,13 +16,29 @@ NODE=`which node 2> /dev/null` NODEJS=`which nodejs 2> /dev/null` IOJS=`which iojs 2> /dev/null` LOCAL="/usr/local/bin/node" +BINARY= +# +# Figure out which binary we need to use for our script execution. +# if [[ -n "$NODE" ]]; then - "$NODE" $("$NODE" -e "console.log(require.resolve('pre-commit'))") + BINARY="$NODE" elif [[ -n "$NODEJS" ]]; then - "$NODEJS" $("$NODEJS" -e "console.log(require.resolve('pre-commit'))") + BINARY="$NODEJS" elif [[ -n "$IOJS" ]]; then - "$IOJS" $("$IOJS" -e "console.log(require.resolve('pre-commit'))") + BINARY="$IOJS" elif [[ -x "$LOCAL" ]]; then - "$LOCAL" $("$LOCAL" -e "console.log(require.resolve('pre-commit'))") + BINARY="$LOCAL" +fi + +# +# Add --dry-run cli flag support so we can execute this hook without side affects +# and see if it works in the current environment +# +if [[ $* == *--dry-run* ]]; then + if [[ -z "$BINARY" ]]; then + exit 1 + fi +else + "$BINARY" $("$BINARY" -e "console.log(require.resolve('pre-commit'))") fi From 321f947e682240f5a7b085366582a8757826e496 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 14:24:12 +0200 Subject: [PATCH 080/127] [minor] Execute the `--dry-run` of the hook before installation to ensure operation --- install.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/install.js b/install.js index 3624b25..323753b 100644 --- a/install.js +++ b/install.js @@ -5,6 +5,7 @@ // var fs = require('fs') , path = require('path') + , shelly = require('shelljs') , hook = path.join(__dirname, './hook') , root = path.resolve(__dirname, '../..') , exists = fs.existsSync || path.existsSync; @@ -19,6 +20,18 @@ var git = path.resolve(root, '.git') , hooks = path.resolve(git, 'hooks') , precommit = path.resolve(hooks, 'pre-commit'); +// +// Make sure that we can execute the hook without any issues before continuing. +// +if (shelly.exec(hook +' --dry-run', { silent: true }).code !== 0) { + console.error('pre-commit:'); + console.error('pre-commit: The --dry-run of the pre-commit hook failed to execute.'); + console.error('pre-commit:'); + console.error('pre-commit: The hook was not installed.'); + console.error('pre-commit:'); + return; +} + // // Bail out if we don't have an `.git` directory as the hooks will not get // triggered. If we do have directory create a hooks folder if it doesn't exist. From 6ebf3b65186ce2d5fb9956ddec5c902f020a987e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 14:54:16 +0200 Subject: [PATCH 081/127] [ci] Adding appveyor support for windows testing --- .appveyor.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..d5f8a30 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,15 @@ +environment: + matrix: + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.12" + - nodejs_version: "1.0" + +install: + - ps: Install-Product node $env:nodejs_version + - npm install + +test_script: + - node --version + - npm --version + - npm test From 62cd0cbe522f531762ee09527f7d716864f3eced Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 14:55:26 +0200 Subject: [PATCH 082/127] [ci] Added support for multiple platforms --- .appveyor.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index d5f8a30..a49c746 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -5,8 +5,12 @@ environment: - nodejs_version: "0.12" - nodejs_version: "1.0" +platform: + - x86 + - x64 + install: - - ps: Install-Product node $env:nodejs_version + - ps: Install-Product node $env:nodejs_version $env:platform - npm install test_script: From 75befe19c5b8d289bd1f63cda9ee557ebdfe85d8 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:02:20 +0200 Subject: [PATCH 083/127] [ci] Don't build -- Seems like this is hard requirement in the file --- .appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index a49c746..925632b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -17,3 +17,5 @@ test_script: - node --version - npm --version - npm test + +build: off From 6b72414e276b38c58279a3cdc5304d2a982219e2 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:15:03 +0200 Subject: [PATCH 084/127] [ci][fix] Lose the .dot prefix, this requires one without it. --- .appveyor.yml => appveyor.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .appveyor.yml => appveyor.yml (100%) diff --git a/.appveyor.yml b/appveyor.yml similarity index 100% rename from .appveyor.yml rename to appveyor.yml From a85af6ccee82dbfbe6514b0e43967c4d8f72ba7c Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:26:31 +0200 Subject: [PATCH 085/127] [ci] Install a newer npm --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 925632b..639a172 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,6 +11,7 @@ platform: install: - ps: Install-Product node $env:nodejs_version $env:platform + - npm install -g npm@2.x.x - npm install test_script: From ec153b166e0fb6af6c3ec79176a519608eef15c3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:40:16 +0200 Subject: [PATCH 086/127] [ci] Allow windows to fail for now as it should not block pull requests until we resolve windows issues --- appveyor.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 639a172..e2c59b3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,10 @@ environment: matrix: - - nodejs_version: "0.8" - - nodejs_version: "0.10" - - nodejs_version: "0.12" - - nodejs_version: "1.0" + allow_failures: + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.12" + - nodejs_version: "1.0" platform: - x86 From d4e4e3fe5bc13bf818832e6b3f76f5b8218aa62c Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:41:43 +0200 Subject: [PATCH 087/127] [ci] indent, deeper --- appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index e2c59b3..5bc3c1d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,10 @@ environment: matrix: - allow_failures: - - nodejs_version: "0.8" - - nodejs_version: "0.10" - - nodejs_version: "0.12" - - nodejs_version: "1.0" + allow_failures: + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.12" + - nodejs_version: "1.0" platform: - x86 From 6a84d427bacf1a848e2857c677c5d1b8bdd0ac96 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 15:52:11 +0200 Subject: [PATCH 088/127] [ci] Use a separate matrix section --- appveyor.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5bc3c1d..a82ea4a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,15 @@ environment: matrix: - allow_failures: - - nodejs_version: "0.8" - - nodejs_version: "0.10" - - nodejs_version: "0.12" - - nodejs_version: "1.0" + - nodejs_version: "0.8" + - nodejs_version: "0.10" + - nodejs_version: "0.12" + - nodejs_version: "1.0" + +matrix: + fast_finish: true + allow_failures: + - platform: x86 + - platform: x64 platform: - x86 From 6908e819f76e6aefbabe0a91a74d2246c9e3b2ac Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 17:11:36 +0200 Subject: [PATCH 089/127] [fix] use `which` for lookups instead of the shell version --- index.js | 5 +++-- package.json | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index e399c2e..17c7e5c 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ var spawn = require('cross-spawn') , shelly = require('shelljs') + , which = require('which') , path = require('path') , util = require('util') , tty = require('tty'); @@ -134,7 +135,7 @@ Hook.prototype.log = function log(lines, exit) { */ Hook.prototype.initialize = function initialize() { ['git', 'npm'].forEach(function each(binary) { - try { this[binary] = this.shelly.which(binary); } + try { this[binary] = which.sync(binary); } catch (e) {} }, this); @@ -145,7 +146,7 @@ Hook.prototype.initialize = function initialize() { if (!this.npm) { try { process.env.PATH += path.delimiter + path.dirname(process.env._); - this.npm = this.shelly.which('npm'); + this.npm = which.sync('npm'); } catch (e) { return this.log(this.format(Hook.log.binary, 'npm'), 0); } diff --git a/package.json b/package.json index e3339e0..4bb554b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,8 @@ "license": "MIT", "dependencies": { "cross-spawn": "2.0.x", - "shelljs": "0.5.x" + "shelljs": "0.5.x", + "which": "1.1.x" }, "devDependencies": { "assume": "1.2.x", From fa474c7cfa14ae41d269533b62047b63618c18f3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 17:33:52 +0200 Subject: [PATCH 090/127] [ci] Limit to 1.4.x as other dependencies also use ^ based semver ranges in npm 2 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a82ea4a..49df9ba 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,7 +17,7 @@ platform: install: - ps: Install-Product node $env:nodejs_version $env:platform - - npm install -g npm@2.x.x + - npm install -g npm@1.4.x - npm install test_script: From d570d16abd132001d87373cc701c850ae96791b1 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 30 Jul 2015 18:50:37 +0200 Subject: [PATCH 091/127] [ci][fix] Fuck it, Node 0.8 on windows is not worth 4 hours of my life. --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 49df9ba..a1f17e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,5 @@ environment: matrix: - - nodejs_version: "0.8" - nodejs_version: "0.10" - nodejs_version: "0.12" - nodejs_version: "1.0" From cf5bddd177f4718e127aa3a75238114dc6550f41 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 31 Jul 2015 11:12:34 +0200 Subject: [PATCH 092/127] [dist] 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4bb554b..dd9065b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.0.10", + "version": "1.1.0", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From d63deca46e7928a3a0c56da90ae0e87043293973 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 31 Jul 2015 13:33:57 +0200 Subject: [PATCH 093/127] [fix] Remove shelljs's exec - it breaks on windows --- index.js | 35 ++++++++++++++++++++--------------- install.js | 4 ++-- package.json | 1 - 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index 17c7e5c..a20646d 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,6 @@ 'use strict'; var spawn = require('cross-spawn') - , shelly = require('shelljs') , which = require('which') , path = require('path') , util = require('util') @@ -57,6 +56,20 @@ Object.defineProperty(Hook.prototype, 'colors', { } }); +/** + * Execute a binary. + * + * @param {String} bin Binary that needs to be executed + * @param {Array} args Arguments for the binary + * @returns {Object} + * @api private + */ +Hook.prototype.exec = function exec(bin, args) { + return spawn.sync(bin, args, { + stdio: 'pipe' + }); +}; + /** * Parse the package.json so we can create an normalize it's contents to * a usable configuration structure. @@ -157,19 +170,14 @@ Hook.prototype.initialize = function initialize() { // if (!this.git) return this.log(this.format(Hook.log.binary, 'git'), 0); - this.root = this.shelly.exec(this.git +' rev-parse --show-toplevel', { - silent: true - }); - - this.status = this.shelly.exec(this.git +' status --porcelain', { - silent: true - }); + this.root = this.exec(this.git, ['rev-parse', '--show-toplevel']); + this.status = this.exec(this.git, ['status', '--porcelain']); if (this.status.code) return this.log(Hook.log.status, 0); if (this.root.code) return this.log(Hook.log.root, 0); - this.status = this.status.output.trim(); - this.root = this.root.output.trim(); + this.status = this.status.stdout.toString().trim(); + this.root = this.root.stdout.toString().trim(); try { this.json = require(path.join(this.root, 'package.json')); @@ -190,9 +198,7 @@ Hook.prototype.initialize = function initialize() { // execute. // if (this.config.template) { - this.shelly.exec(this.git +' config commit.template "'+ this.config.template +'"', { - silent: true - }); + this.exec(this.git, ['config', 'commit.template', '"'+ this.config.template +'"']); } if (!this.config.run) return this.log(Hook.log.run, 0); @@ -213,7 +219,7 @@ Hook.prototype.run = function runner() { // // There's a reason on why we're using an async `spawn` here instead of the - // `shelly.exec`. The sync `exec` is a hack that writes writes a file to + // `shelljs.exec`. The sync `exec` is a hack that writes writes a file to // disk and they poll with sync fs calls to see for results. The problem is // that the way they capture the output which us using input redirection and // this doesn't have the required `isAtty` information that libraries use to @@ -239,7 +245,6 @@ Hook.prototype.run = function runner() { * @public */ Hook.prototype.format = util.format; -Hook.prototype.shelly = shelly; /** * The various of error and status messages that we can output. diff --git a/install.js b/install.js index 323753b..02eded8 100644 --- a/install.js +++ b/install.js @@ -5,7 +5,7 @@ // var fs = require('fs') , path = require('path') - , shelly = require('shelljs') + , spawn = require('cross-spawn') , hook = path.join(__dirname, './hook') , root = path.resolve(__dirname, '../..') , exists = fs.existsSync || path.existsSync; @@ -23,7 +23,7 @@ var git = path.resolve(root, '.git') // // Make sure that we can execute the hook without any issues before continuing. // -if (shelly.exec(hook +' --dry-run', { silent: true }).code !== 0) { +if (spawn.sync('sh', [hook, '--dry-run'], { stdio: 'ignore' }).code !== 0) { console.error('pre-commit:'); console.error('pre-commit: The --dry-run of the pre-commit hook failed to execute.'); console.error('pre-commit:'); diff --git a/package.json b/package.json index dd9065b..ae5537f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "license": "MIT", "dependencies": { "cross-spawn": "2.0.x", - "shelljs": "0.5.x", "which": "1.1.x" }, "devDependencies": { From 9cb52b4ea4d7ffae80d3e2ed397faeadc7ff964d Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 31 Jul 2015 13:44:32 +0200 Subject: [PATCH 094/127] [fix] Remove the dry run. Fixes #42 --- install.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/install.js b/install.js index 02eded8..703bf79 100644 --- a/install.js +++ b/install.js @@ -20,18 +20,6 @@ var git = path.resolve(root, '.git') , hooks = path.resolve(git, 'hooks') , precommit = path.resolve(hooks, 'pre-commit'); -// -// Make sure that we can execute the hook without any issues before continuing. -// -if (spawn.sync('sh', [hook, '--dry-run'], { stdio: 'ignore' }).code !== 0) { - console.error('pre-commit:'); - console.error('pre-commit: The --dry-run of the pre-commit hook failed to execute.'); - console.error('pre-commit:'); - console.error('pre-commit: The hook was not installed.'); - console.error('pre-commit:'); - return; -} - // // Bail out if we don't have an `.git` directory as the hooks will not get // triggered. If we do have directory create a hooks folder if it doesn't exist. From f642801aab5b382fa06864bbbb50bff74f00b1c6 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 31 Jul 2015 14:14:57 +0200 Subject: [PATCH 095/127] [dist] 1.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae5537f..4f2fabe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.1.0", + "version": "1.1.1", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 886496a1c22150b77b742afa724f5299e5e363d3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 31 Jul 2015 14:58:16 +0200 Subject: [PATCH 096/127] [minor] Clean up path.join --- install.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.js b/install.js index 703bf79..7e03cf0 100644 --- a/install.js +++ b/install.js @@ -6,8 +6,8 @@ var fs = require('fs') , path = require('path') , spawn = require('cross-spawn') - , hook = path.join(__dirname, './hook') - , root = path.resolve(__dirname, '../..') + , hook = path.join(__dirname, 'hook') + , root = path.resolve(__dirname, '..', '..') , exists = fs.existsSync || path.existsSync; // From bbf3105c20bfe7f29247bff38f37093e790771e4 Mon Sep 17 00:00:00 2001 From: Sergej Leibenzon Date: Wed, 12 Aug 2015 15:43:57 +0200 Subject: [PATCH 097/127] Source also zshrc --- hook | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hook b/hook index 66debda..9cd2385 100755 --- a/hook +++ b/hook @@ -4,12 +4,13 @@ HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> # # There are some issues with Source Tree because paths are not set correctly for -# the given environment. Sourcing the bash_profile seems to resolve this for users +# the given environment. Sourcing the bash_profile seems to resolve this for bash users, +# sourcing the zshrc for zshell users. # # https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly # -if [ -z "$HAS_NODE" ] && [ -f ~/.bash_profile ]; then - source ~/.bash_profile +if [[ -z "$HAS_NODE" ]]; then + source ~/.bash_profile || source ~/.zshrc || true fi NODE=`which node 2> /dev/null` From e44e864b2850fbadfb69fa0d3ba4b5886c8d5d66 Mon Sep 17 00:00:00 2001 From: Sergej Leibenzon Date: Thu, 13 Aug 2015 12:49:35 +0200 Subject: [PATCH 098/127] Use -f file checks before sourcing --- hook | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hook b/hook index 9cd2385..e61d175 100755 --- a/hook +++ b/hook @@ -9,8 +9,13 @@ HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> # # https://answers.atlassian.com/questions/140339/sourcetree-hook-failing-because-paths-don-t-seem-to-be-set-correctly # +function source_home_file { + file="$HOME/$1" + [[ -f "${file}" ]] && source "${file}" +} + if [[ -z "$HAS_NODE" ]]; then - source ~/.bash_profile || source ~/.zshrc || true + source_home_file ".bash_profile" || source_home_file ".zshrc" || true fi NODE=`which node 2> /dev/null` From 8c7f0fd66c47d8380c9637685e96bdabbcc8486d Mon Sep 17 00:00:00 2001 From: Chris Van Date: Mon, 14 Sep 2015 12:51:30 -0700 Subject: [PATCH 099/127] fix typo in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97659a8..23e4891 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ **pre-commit** is a pre-commit hook installer for `git`. It will ensure that your `npm test` (or other specified scripts) passes before you can commit your -changes. This all conveniently configured in your package.json. +changes. This all conveniently configured in your `package.json`. But don't worry, you can still force a commit by telling `git` to skip the `pre-commit` hooks by simply committing using `--no-verify`. @@ -40,7 +40,7 @@ specified in your `package.json` "scripts" field. So before people commit you could ensure that: - You have 100% coverage -- All stying passes. +- All styling passes. - JSHint passes. - Contribution licenses signed etc. From 2bba3084aa1a0713c8e1eb1c55fc752b0d7f9a76 Mon Sep 17 00:00:00 2001 From: Jose Talens Date: Mon, 12 Oct 2015 20:53:01 +0100 Subject: [PATCH 100/127] Added quotes to allow spaces in directory names --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index e61d175..8d53465 100755 --- a/hook +++ b/hook @@ -46,5 +46,5 @@ if [[ $* == *--dry-run* ]]; then exit 1 fi else - "$BINARY" $("$BINARY" -e "console.log(require.resolve('pre-commit'))") + "$BINARY" "$("$BINARY" -e "console.log(require.resolve('pre-commit'))")" fi From 741ceecb462effe613722b0cf3cea2659dd24e50 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 20 Oct 2015 11:19:11 +0200 Subject: [PATCH 101/127] [dist] 1.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f2fabe..cf5c827 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.1.1", + "version": "1.1.2", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From eb7ac2421a75504973a32d9f5ca6be728f89bb5c Mon Sep 17 00:00:00 2001 From: Frederic Hemberger Date: Tue, 20 Oct 2015 11:19:53 +0200 Subject: [PATCH 102/127] [travis] Add Node@4.x, use new container infrastructure --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8f4f8e5..8f8b41a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,10 @@ +sudo: false language: node_js node_js: - "0.12" - "0.10" - "0.8" + - "4" - "iojs" before_install: - "npm install -g npm@1.4.x" From 53ec6e91273498aec0c0d63eac1d9ba309646578 Mon Sep 17 00:00:00 2001 From: Frederic Hemberger Date: Tue, 20 Oct 2015 11:21:58 +0200 Subject: [PATCH 103/127] Update dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 4f2fabe..dbcb194 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "license": "MIT", "dependencies": { "cross-spawn": "2.0.x", - "which": "1.1.x" + "which": "1.2.x" }, "devDependencies": { - "assume": "1.2.x", - "istanbul": "0.3.x", - "mocha": "2.2.x", + "assume": "1.3.x", + "istanbul": "0.4.x", + "mocha": "2.3.x", "pre-commit": "git://github.com/observing/pre-commit.git" } } From 4510f4559e8d8217a06a508559519f70d9449187 Mon Sep 17 00:00:00 2001 From: blacksonic Date: Fri, 30 Oct 2015 22:10:32 +0100 Subject: [PATCH 104/127] [fix] add .bashrc to supported home files --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index 8d53465..62436f3 100755 --- a/hook +++ b/hook @@ -15,7 +15,7 @@ function source_home_file { } if [[ -z "$HAS_NODE" ]]; then - source_home_file ".bash_profile" || source_home_file ".zshrc" || true + source_home_file ".bash_profile" || source_home_file ".zshrc" || source_home_file ".bashrc" || true fi NODE=`which node 2> /dev/null` From b6e63d708bb23e97cf637bc1369649d9dd78225d Mon Sep 17 00:00:00 2001 From: Saiichi Hashimoto Date: Tue, 22 Dec 2015 01:08:38 -0800 Subject: [PATCH 105/127] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 23e4891..137671e 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ The examples above are all the same. In addition to configuring which scripts should be ran you can also configure the following options: - **silent** Don't output the prefixed `pre-commit:` messages when things fail - or when we have nothing to run. Should a boolean. + or when we have nothing to run. Should be a boolean. - **colors** Don't output colors when we write messages. Should be a boolean. - **template** Path to a file who's content should be used as template for the git commit body. From 1a044306eeb5743ba7b171a6708aa9e30db720e9 Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Fri, 5 Feb 2016 23:03:27 -0800 Subject: [PATCH 106/127] Make pre-commit hook symlink relative Renaming or moving the project directory (the one containing .git) causes absolute links to break and the pre-commit hook to be silently ignored. Instead, make the link relative so that it is preserved across directory rename/move. Signed-off-by: Kevin Locke --- install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.js b/install.js index 7e03cf0..2aa0dcb 100644 --- a/install.js +++ b/install.js @@ -52,7 +52,7 @@ catch (e) {} // installation of this module to completely fail. We should just output the // error instead destroying the whole npm install process. // -try { fs.symlinkSync(hook, precommit, 'file'); } +try { fs.symlinkSync(path.relative(hooks, hook), precommit, 'file'); } catch (e) { console.error('pre-commit:'); console.error('pre-commit: Failed to symlink the hook file in your .git/hooks folder because:'); From 0f0833ab2df4884b8cbaf721ed5b6b6fe922dc4b Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 10 May 2016 15:31:15 +0200 Subject: [PATCH 107/127] [dist] 1.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 163d339..3009fe9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.1.2", + "version": "1.1.3", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 18da6681a1316aaf783bb3cb66546abb6e67638d Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 10 May 2016 15:35:36 +0200 Subject: [PATCH 108/127] [deps] Fix npmgate --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3009fe9..f166b47 100644 --- a/package.json +++ b/package.json @@ -34,9 +34,9 @@ "which": "1.2.x" }, "devDependencies": { - "assume": "1.3.x", + "assume": "1.4.x", "istanbul": "0.4.x", - "mocha": "2.3.x", + "mocha": "2.4.x", "pre-commit": "git://github.com/observing/pre-commit.git" } } From fec48cb4e642dfcd62bbdae144f2496a4e43fd0f Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 10 May 2016 15:37:12 +0200 Subject: [PATCH 109/127] [ci] Remove NPM hack and old npm --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f8b41a..064309e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,8 @@ language: node_js node_js: - "0.12" - "0.10" - - "0.8" - "4" - "iojs" -before_install: - - "npm install -g npm@1.4.x" script: - "npm run test-travis" after_script: From ead948402e2f91cbb1851930602305135dc3091c Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Sat, 23 Jul 2016 12:01:57 -0700 Subject: [PATCH 110/127] cross-spawn@4 (#77) --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f166b47..8ac7b58 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "homepage": "https://github.com/observing/pre-commit", "license": "MIT", "dependencies": { - "cross-spawn": "2.0.x", + "cross-spawn": "^4.0.0", + "spawn-sync": "^1.0.15", "which": "1.2.x" }, "devDependencies": { From 7154dee93f2c38ef46f807f21cc9ce73848d7396 Mon Sep 17 00:00:00 2001 From: Luan Muniz Date: Mon, 25 Jul 2016 06:03:29 -0300 Subject: [PATCH 111/127] Update dep to remove warn about cross-spaw (#76) * Update dep to remove warn about cross-spaw * fix backwards compatibility From 3cf4cf781fe0e3fe362b408ed43590007803c340 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 17 Nov 2016 09:25:17 -0800 Subject: [PATCH 112/127] chore(package): update dependencies (#85) https://greenkeeper.io/ --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8ac7b58..0d0eac6 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,14 @@ "homepage": "https://github.com/observing/pre-commit", "license": "MIT", "dependencies": { - "cross-spawn": "^4.0.0", + "cross-spawn": "^5.0.1", "spawn-sync": "^1.0.15", "which": "1.2.x" }, "devDependencies": { "assume": "1.4.x", "istanbul": "0.4.x", - "mocha": "2.4.x", + "mocha": "~3.1.2", "pre-commit": "git://github.com/observing/pre-commit.git" } } From 4167676bb1cb9b0addef81bf889da60951ba505d Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Sun, 27 Nov 2016 03:04:38 +0100 Subject: [PATCH 113/127] chore(package): update mocha to version 3.2.0 (#86) https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d0eac6..1f61ee7 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "devDependencies": { "assume": "1.4.x", "istanbul": "0.4.x", - "mocha": "~3.1.2", + "mocha": "~3.2.0", "pre-commit": "git://github.com/observing/pre-commit.git" } } From a9c973224a299a03aef66b5fd1a3b5d566edfee6 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 27 Nov 2016 03:04:47 +0100 Subject: [PATCH 114/127] solves the windows issue (with symlinks) (#84) * solved the windows issue with symlinks Instead of symlinking to the hook in node-modules/pre-commit, this injects a new pre-commit hook (in .git/hooks) that takes care of launching the hook in node-modules/pre-commit. In addition it stashes the unstaged changes and applies them again after running the pre-commit hook, so that you only run your pre-commit scripts on the commit actual codebase. * removed stashing Stashing automatically is actually a bad idea, it's better to for the user to have control over doing it or not (manually then). --- install.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/install.js b/install.js index 2aa0dcb..b903bcc 100644 --- a/install.js +++ b/install.js @@ -5,7 +5,7 @@ // var fs = require('fs') , path = require('path') - , spawn = require('cross-spawn') + , os = require('os') , hook = path.join(__dirname, 'hook') , root = path.resolve(__dirname, '..', '..') , exists = fs.existsSync || path.existsSync; @@ -47,15 +47,28 @@ if (exists(precommit) && !fs.lstatSync(precommit).isSymbolicLink()) { try { fs.unlinkSync(precommit); } catch (e) {} +// Create generic precommit hook that launches this modules hook (as well +// as stashing - unstashing the unstaged changes) +// TODO: we could keep launching the old pre-commit scripts +var hookRelativeUnixPath = hook.replace(root, '.'); +if(os.platform() === 'win32') { + hookRelativeUnixPath = hookRelativeUnixPath.replace(/[\\\/]+/g, '/'); +} +var precommitContent = '#!/bin/bash' + os.EOL + + hookRelativeUnixPath + os.EOL + + 'RESULT=$?' + os.EOL + + '[ $RESULT -ne 0 ] && exit 1' + os.EOL + + 'exit 0' + os.EOL; + // // It could be that we do not have rights to this folder which could cause the // installation of this module to completely fail. We should just output the // error instead destroying the whole npm install process. // -try { fs.symlinkSync(path.relative(hooks, hook), precommit, 'file'); } +try { fs.writeFileSync(precommit, precommitContent); } catch (e) { console.error('pre-commit:'); - console.error('pre-commit: Failed to symlink the hook file in your .git/hooks folder because:'); + console.error('pre-commit: Failed to create the hook file in your .git/hooks folder because:'); console.error('pre-commit: '+ e.message); console.error('pre-commit: The hook was not installed.'); console.error('pre-commit:'); From 1689e3e87ca2c73dc75a260e2fba472a345b5d5b Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Fri, 9 Dec 2016 13:07:44 +0100 Subject: [PATCH 115/127] [dist] 1.2.0 - Better windows support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f61ee7..3ffa2c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.1.3", + "version": "1.2.0", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 3ecafe09d222c6f97b67fb2f1224f23e094a8d82 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 12 Dec 2016 01:13:01 +0100 Subject: [PATCH 116/127] [fix] chmod 0777 the newly created file; Fixes #88 --- install.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/install.js b/install.js index b903bcc..3d2e69e 100644 --- a/install.js +++ b/install.js @@ -51,9 +51,11 @@ catch (e) {} // as stashing - unstashing the unstaged changes) // TODO: we could keep launching the old pre-commit scripts var hookRelativeUnixPath = hook.replace(root, '.'); + if(os.platform() === 'win32') { hookRelativeUnixPath = hookRelativeUnixPath.replace(/[\\\/]+/g, '/'); } + var precommitContent = '#!/bin/bash' + os.EOL + hookRelativeUnixPath + os.EOL + 'RESULT=$?' + os.EOL @@ -73,3 +75,11 @@ catch (e) { console.error('pre-commit: The hook was not installed.'); console.error('pre-commit:'); } + +try { fs.chmodSync(precommit, 777); } +catch (e) { + console.error('pre-commit:'); + console.error('pre-commit: chmod 0777 the pre-commit file in your .git/hooks folder because:'); + console.error('pre-commit: '+ e.message); + console.error('pre-commit:'); +} From 7d6feb19648e8d60cab50917b42f08f12d89482e Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 12 Dec 2016 01:17:56 +0100 Subject: [PATCH 117/127] [dist] 1.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ffa2c5..e090ece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.2.0", + "version": "1.2.1", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From 675560c16d5d5fe81f419c526b210dc56759e853 Mon Sep 17 00:00:00 2001 From: josegal Date: Tue, 13 Dec 2016 13:52:44 +0200 Subject: [PATCH 118/127] Use string instead of int 777 in fs.chmodSync so it gets correctly interpreted as octal (#90) --- install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.js b/install.js index 3d2e69e..e761ba9 100644 --- a/install.js +++ b/install.js @@ -76,7 +76,7 @@ catch (e) { console.error('pre-commit:'); } -try { fs.chmodSync(precommit, 777); } +try { fs.chmodSync(precommit, '777'); } catch (e) { console.error('pre-commit:'); console.error('pre-commit: chmod 0777 the pre-commit file in your .git/hooks folder because:'); From bf393adbf5de842b6286dc1d12d024fb2784d1f5 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Tue, 13 Dec 2016 12:56:32 +0100 Subject: [PATCH 119/127] [dist] 1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e090ece..28ba177 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pre-commit", - "version": "1.2.1", + "version": "1.2.2", "description": "Automatically install pre-commit hooks for your npm modules.", "main": "index.js", "scripts": { From f55b66b9c75b73a903f5b77c7c511a13e0c7edff Mon Sep 17 00:00:00 2001 From: "Brian R. Bondy" Date: Wed, 21 Dec 2016 09:43:12 -0500 Subject: [PATCH 120/127] Fix pre-commit template (#80) Without this, it actually looks for a file with quotes around it on macOS and probably other platforms too. The path is already escaped because it is part of an args array. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index a20646d..89f5a9d 100644 --- a/index.js +++ b/index.js @@ -198,7 +198,7 @@ Hook.prototype.initialize = function initialize() { // execute. // if (this.config.template) { - this.exec(this.git, ['config', 'commit.template', '"'+ this.config.template +'"']); + this.exec(this.git, ['config', 'commit.template', this.config.template]); } if (!this.config.run) return this.log(Hook.log.run, 0); From a7c824781bca0b17e846878e2a727fd20fedb80f Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 3 Apr 2017 19:46:26 +0200 Subject: [PATCH 121/127] chore(package): update assume to version 1.5.0 (#98) https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 28ba177..72cdaeb 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "which": "1.2.x" }, "devDependencies": { - "assume": "1.4.x", + "assume": "~1.5.0", "istanbul": "0.4.x", "mocha": "~3.2.0", "pre-commit": "git://github.com/observing/pre-commit.git" From 66b95fd83859406b38859280dda1569c214ac760 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 24 Apr 2017 16:03:33 +0200 Subject: [PATCH 122/127] chore(package): update mocha to version 3.3.0 (#101) https://greenkeeper.io/ --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72cdaeb..dc1ff70 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "devDependencies": { "assume": "~1.5.0", "istanbul": "0.4.x", - "mocha": "~3.2.0", + "mocha": "~3.3.0", "pre-commit": "git://github.com/observing/pre-commit.git" } } From 5eb7b9bf35e9d0322564ea2e28fc8c640590f3f1 Mon Sep 17 00:00:00 2001 From: Brendan Warkentin Date: Fri, 5 May 2017 03:44:33 -0600 Subject: [PATCH 123/127] Support for git repos as submodules (#96) --- install.js | 15 +++++++++++++++ uninstall.js | 21 ++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/install.js b/install.js index e761ba9..ba9d65b 100644 --- a/install.js +++ b/install.js @@ -20,6 +20,21 @@ var git = path.resolve(root, '.git') , hooks = path.resolve(git, 'hooks') , precommit = path.resolve(hooks, 'pre-commit'); +// +// Resolve git directory for submodules +// +if (exists(git) && fs.lstatSync(git).isFile()) { + var gitinfo = fs.readFileSync(git).toString() + , gitdirmatch = /gitdir: (.+)/.exec(gitinfo) + , gitdir = gitdirmatch.length == 2 ? gitdirmatch[1] : null; + + if (gitdir !== null) { + git = path.resolve(root, gitdir); + hooks = path.resolve(git, 'hooks'); + precommit = path.resolve(hooks, 'pre-commit'); + } +} + // // Bail out if we don't have an `.git` directory as the hooks will not get // triggered. If we do have directory create a hooks folder if it doesn't exist. diff --git a/uninstall.js b/uninstall.js index a0d2fd0..7c47903 100644 --- a/uninstall.js +++ b/uninstall.js @@ -3,7 +3,26 @@ var fs = require('fs') , path = require('path') , exists = fs.existsSync || path.existsSync - , precommit = path.resolve(__dirname, '../..', '.git', 'hooks', 'pre-commit'); + , root = path.resolve(__dirname, '..', '..') + , git = path.resolve(root, '.git'); + +// +// Resolve git directory for submodules +// +if (exists(git) && fs.lstatSync(git).isFile()) { + var gitinfo = fs.readFileSync(git).toString() + , gitdirmatch = /gitdir: (.+)/.exec(gitinfo) + , gitdir = gitdirmatch.length == 2 ? gitdirmatch[1] : null; + + if (gitdir !== null) { + git = path.resolve(root, gitdir); + } +} + +// +// Location of pre-commit hook, if it exists +// +var precommit = path.resolve(git, 'hooks', 'pre-commit'); // // Bail out if we don't have pre-commit file, it might be removed manually. From 77bf620de7f7e8cdfbc260524d86c49def4e4333 Mon Sep 17 00:00:00 2001 From: Alexander Sokolov Date: Fri, 30 Jun 2017 16:02:29 +0300 Subject: [PATCH 124/127] Add ability to find .git folder on upper levels (#100) --- install.js | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/install.js b/install.js index ba9d65b..77f090c 100644 --- a/install.js +++ b/install.js @@ -16,9 +16,31 @@ var fs = require('fs') // `pre-commit` file. The path needs to be absolute in order for the symlinking // to work correctly. // -var git = path.resolve(root, '.git') - , hooks = path.resolve(git, 'hooks') - , precommit = path.resolve(hooks, 'pre-commit'); + +var git = getGitFolderPath(root); + +// Function to recursively finding .git folder +function getGitFolderPath(currentPath) { + var git = path.resolve(currentPath, '.git') + + if (!exists(git) || !fs.lstatSync(git).isDirectory()) { + console.log('pre-commit:'); + console.log('pre-commit: Not found .git folder in', git); + + var newPath = path.resolve(currentPath, '..'); + + // Stop if we on top folder + if (currentPath === newPath) { + return null; + } + + return getGitFolderPath(newPath); + } + + console.log('pre-commit:'); + console.log('pre-commit: Found .git folder in', git); + return git; +} // // Resolve git directory for submodules @@ -39,7 +61,15 @@ if (exists(git) && fs.lstatSync(git).isFile()) { // Bail out if we don't have an `.git` directory as the hooks will not get // triggered. If we do have directory create a hooks folder if it doesn't exist. // -if (!exists(git) || !fs.lstatSync(git).isDirectory()) return; +if (!git) { + console.log('pre-commit:'); + console.log('pre-commit: Not found any .git folder for installing pre-commit hook'); + return; +} + +var hooks = path.resolve(git, 'hooks') + , precommit = path.resolve(hooks, 'pre-commit'); + if (!exists(hooks)) fs.mkdirSync(hooks); // From f25888ffc67d21beaa1572b53ab6704a67266b64 Mon Sep 17 00:00:00 2001 From: Martin Wijk Date: Fri, 30 Jun 2017 15:02:53 +0200 Subject: [PATCH 125/127] Change shebang to #!/usr/bin/env bash for better portability (#105) --- hook | 2 +- install.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hook b/hook index 62436f3..28a7f38 100755 --- a/hook +++ b/hook @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash HAS_NODE=`which node 2> /dev/null || which nodejs 2> /dev/null || which iojs 2> /dev/null` diff --git a/install.js b/install.js index 77f090c..e24fc0d 100644 --- a/install.js +++ b/install.js @@ -101,7 +101,7 @@ if(os.platform() === 'win32') { hookRelativeUnixPath = hookRelativeUnixPath.replace(/[\\\/]+/g, '/'); } -var precommitContent = '#!/bin/bash' + os.EOL +var precommitContent = '#!/usr/bin/env bash' + os.EOL + hookRelativeUnixPath + os.EOL + 'RESULT=$?' + os.EOL + '[ $RESULT -ne 0 ] && exit 1' + os.EOL From 84aa9eac11634d8fe6053fa7946dee5b77f09581 Mon Sep 17 00:00:00 2001 From: Filip Barakovski Date: Tue, 20 Nov 2018 01:16:39 +0100 Subject: [PATCH 126/127] Changes 'side affects' to 'side effects' (#141) --- hook | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook b/hook index 28a7f38..1bf23b8 100755 --- a/hook +++ b/hook @@ -38,7 +38,7 @@ elif [[ -x "$LOCAL" ]]; then fi # -# Add --dry-run cli flag support so we can execute this hook without side affects +# Add --dry-run cli flag support so we can execute this hook without side effects # and see if it works in the current environment # if [[ $* == *--dry-run* ]]; then From a84bdc87aabf79493343a366872ab204a62b1613 Mon Sep 17 00:00:00 2001 From: Ace Young <2482343+aceyoung9@users.noreply.github.com> Date: Tue, 4 Jun 2019 06:50:52 -0400 Subject: [PATCH 127/127] Update link to official npm docs (#143) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 137671e..16f6b2e 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ the existing `pre-commit` file in your `.git/hooks` folder. Existing `pre-commit` will try to run your `npm test` command in the root of the git repository by default unless it's the default value that is set by the `npm -init` script. +init` script. But `pre-commit` is not limited to just running your `npm test`'s during the commit hook. It's also capable of running every other script that you've @@ -116,7 +116,7 @@ or as `"pre-commit.{key}` key properties in the `package.json`: It's all the same. Different styles so use what matches your project. To learn more about the scripts, please read the official `npm` documentation: -https://npmjs.org/doc/scripts.html +https://docs.npmjs.com/misc/scripts And to learn more about git hooks read: