├── .npmignore ├── .gitignore ├── .travis.yml ├── .editorconfig ├── History.md ├── package.json ├── install.js ├── uninstall.js ├── README.md └── hooks ├── pre-commit ├── pre-push ├── pre-release └── post-release /.npmignore: -------------------------------------------------------------------------------- 1 | benchmark/ 2 | test/ 3 | cov/ 4 | Makefile 5 | covrage.html 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.seed 2 | *.log 3 | *.csv 4 | *.dat 5 | *.out 6 | *.pid 7 | *.gz 8 | 9 | coverage.html 10 | coverage/ 11 | cov/ 12 | 13 | node_modules 14 | 15 | dump.rdb 16 | .DS_Store 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | - "0.11" 5 | script: "make test-travis" 6 | after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [Makefile] 16 | indent_style = tab 17 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 1.2.1 / 2018-12-20 3 | ================== 4 | 5 | **others** 6 | * [[`61d547b`](http://github.com/node-modules/git-pre-hooks/commit/61d547b71d3c0d8ec263652ed3f488e9ff11a2ae)] - Run tasks using shell (Alba Mendez <>) 7 | 8 | 1.2.0 / 2015-09-27 9 | ================== 10 | 11 | * support post release 12 | 13 | 1.1.1 / 2014-12-16 14 | ================== 15 | 16 | * exit 1 when error 17 | 18 | 1.1.0 / 2014-12-03 19 | ================== 20 | 21 | * change config field to git-pre-hooks 22 | 23 | 1.0.2 / 2014-12-02 24 | ================== 25 | 26 | * pipe stdout 27 | * fix uninstall 28 | 29 | 1.0.0 / 2014-12-02 30 | ================== 31 | 32 | * init 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-pre-hooks", 3 | "version": "1.2.1", 4 | "description": "Automatically install git pre hooks in your git repository that run your task", 5 | "main": "index.js", 6 | "scripts": { 7 | "install": "node install.js", 8 | "uninstall": "node uninstall.js" 9 | }, 10 | "keywords": [ 11 | "git", 12 | "hooks", 13 | "commit", 14 | "release", 15 | "package" 16 | ], 17 | "author": { 18 | "name": "dead-horse", 19 | "email": "dead_horse@qq.com", 20 | "url": "http://deadhorse.me" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git@github.com:node-modules/git-pre-hooks" 25 | }, 26 | "license": "MIT", 27 | "engine": { 28 | "node": ">=0.10" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /install.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * git-pre-hooks - install.js 3 | * Copyright(c) 2014 dead_horse 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var path = require('path'); 14 | var fs = require('fs'); 15 | 16 | var hooks = {}; 17 | 18 | var pkgHooksDir = path.join(__dirname, 'hooks'); 19 | var hookList = fs.readdirSync(pkgHooksDir); 20 | hookList.forEach(function (name) { 21 | hooks[name] = fs.readFileSync(path.join(pkgHooksDir, name)); 22 | }); 23 | 24 | var gitdir = path.join(__dirname, '../../.git'); 25 | var hooksdir = path.join(gitdir, 'hooks'); 26 | 27 | if (!fs.existsSync(gitdir)) return; 28 | if (!fs.existsSync(hooksdir)) fs.mkdirSync(hooksdir); 29 | 30 | hookList.forEach(function (name) { 31 | var hookPath = path.join(hooksdir, name); 32 | 33 | // back old hook 34 | if (fs.existsSync(hookPath) 35 | && fs.readFileSync(hookPath, 'utf-8').indexOf('generate by git-pre-hooks') < 0) { 36 | fs.writeFileSync(hookPath + '.back', fs.readFileSync(hookPath)); 37 | } 38 | 39 | fs.writeFileSync(hookPath, hooks[name]); 40 | fs.chmodSync(hookPath, '755'); 41 | }); 42 | -------------------------------------------------------------------------------- /uninstall.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * git-pre-hooks - uninstall.js 3 | * Copyright(c) 2014 dead_horse 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /** 10 | * Module dependencies. 11 | */ 12 | 13 | var path = require('path'); 14 | var fs = require('fs'); 15 | 16 | var hooks = {}; 17 | 18 | var hookList = fs.readdirSync('./hooks'); 19 | 20 | var gitdir = path.join(__dirname, '../../.git'); 21 | var hooksdir = path.join(gitdir, 'hooks'); 22 | console.log(gitdir, hooksdir) 23 | if (!fs.existsSync(gitdir)) return; 24 | if (!fs.existsSync(hooksdir)) return; 25 | 26 | hookList.forEach(function (name) { 27 | var hookPath = path.join(hooksdir, name); 28 | var hookBackPath = hookPath + '.back'; 29 | 30 | var existHook = fs.existsSync(hookPath); 31 | var hookNeedClean = isGenerated(hookPath); 32 | var existBack = fs.existsSync(hookBackPath); 33 | 34 | if (hookNeedClean) { 35 | if (existBack) { 36 | fs.writeFileSync(hookPath, fs.readFileSync(hookBackPath, 'utf-8')); 37 | fs.chmodSync(hookPath, '755'); 38 | fs.unlinkSync(hookBackPath); 39 | } else { 40 | fs.unlinkSync(hookPath); 41 | } 42 | } 43 | }); 44 | 45 | function isGenerated(hookPath) { 46 | return fs.readFileSync(hookPath, 'utf-8').indexOf('generate by git-pre-hooks') >= 0; 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | git-pre-hooks 2 | --------------- 3 | 4 | [![NPM version][npm-image]][npm-url] 5 | [![node version][node-image]][node-url] 6 | [![Gittip][gittip-image]][gittip-url] 7 | 8 | [npm-image]: https://img.shields.io/npm/v/git-pre-hooks.svg?style=flat-square 9 | [npm-url]: https://npmjs.org/package/git-pre-hooks 10 | [node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square 11 | [node-url]: http://nodejs.org/download/ 12 | [gittip-image]: https://img.shields.io/gittip/dead-horse.svg?style=flat-square 13 | [gittip-url]: https://www.gittip.com/dead-horse/ 14 | 15 | Automatically install git pre hooks in your git repository that run your task. 16 | 17 | ## Installation 18 | 19 | ```bash 20 | $ npm install git-pre-hooks --save-dev 21 | ``` 22 | 23 | ## Usage 24 | 25 | First install `git-pre-hooks` from npm. 26 | 27 | ``` 28 | npm install git-pre-hooks --save-dev 29 | ``` 30 | 31 | Then add `git-pre-hooks` config in your `package.json`: 32 | 33 | ``` 34 | "git-pre-hooks": { 35 | "pre-commit": "make jshint", 36 | "pre-push": "make test", 37 | "pre-release": ["make test", "make build", "make test-build"], 38 | "post-release": "npm publish" 39 | } 40 | ``` 41 | 42 | ### `pre-release` & `post-release` hook 43 | 44 | If you are using [git-extras](https://github.com/tj/git-extras), `git-pre-hooks` also support `pre-release` and `post-release` hook. 45 | Please make sure you install `git-extras` after 2014/12/03. 46 | 47 | One-liner: 48 | 49 | ```sh 50 | $ (cd /tmp && git clone --depth 1 https://github.com/tj/git-extras.git && cd git-extras && sudo make install) 51 | ``` 52 | 53 | ### License 54 | 55 | MIT 56 | -------------------------------------------------------------------------------- /hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* generate by git-pre-hooks */ 4 | 'use strict'; 5 | 6 | var child = require('child_process'); 7 | var fmt = require('util').format; 8 | var path = require('path'); 9 | 10 | var command = path.basename(__filename); 11 | 12 | child.exec('git rev-parse --show-toplevel', function (err, stdout) { 13 | if (err) return error(err); 14 | 15 | var root = stdout.trim(); 16 | var pkg; 17 | try { 18 | pkg = require(path.join(root, 'package.json')); 19 | } catch (err) { 20 | return error(err); 21 | } 22 | 23 | // no task to run 24 | if (!pkg 25 | || !pkg['git-pre-hooks'] 26 | || !pkg['git-pre-hooks'][command] 27 | || !pkg['git-pre-hooks'][command].length) return; 28 | 29 | run(root, pkg['git-pre-hooks'][command]); 30 | }); 31 | 32 | function run(root, tasks) { 33 | if (typeof tasks === 'string') tasks = [tasks]; 34 | if (!Array.isArray(tasks)) { 35 | return error(new Error('hooks.' + command + ' in package.json must be string or array')); 36 | } 37 | 38 | next(); 39 | 40 | function next() { 41 | if (tasks.length === 0) return; 42 | 43 | var task = tasks.shift(); 44 | var c = child.spawn(task, {cwd: root, stdio: 'inherit', shell: true}); 45 | c.on('exit', function (code) { 46 | if (code !== 0) { 47 | return error(new Error(fmt('task `%s` exit with code %s', task, code))); 48 | } 49 | next(); 50 | }); 51 | } 52 | } 53 | 54 | function error(err) { 55 | if (err.task) console.error('[%s] run `%s` error', command, err.task); 56 | console.error('[%s] Error Stack:\n%s', command, err.stack.replace(/^/gm, ' ')); 57 | process.exit(1); 58 | } 59 | -------------------------------------------------------------------------------- /hooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* generate by git-pre-hooks */ 4 | 'use strict'; 5 | 6 | var child = require('child_process'); 7 | var fmt = require('util').format; 8 | var path = require('path'); 9 | 10 | var command = path.basename(__filename); 11 | 12 | child.exec('git rev-parse --show-toplevel', function (err, stdout) { 13 | if (err) return error(err); 14 | 15 | var root = stdout.trim(); 16 | var pkg; 17 | try { 18 | pkg = require(path.join(root, 'package.json')); 19 | } catch (err) { 20 | return error(err); 21 | } 22 | 23 | // no task to run 24 | if (!pkg 25 | || !pkg['git-pre-hooks'] 26 | || !pkg['git-pre-hooks'][command] 27 | || !pkg['git-pre-hooks'][command].length) return; 28 | 29 | run(root, pkg['git-pre-hooks'][command]); 30 | }); 31 | 32 | function run(root, tasks) { 33 | if (typeof tasks === 'string') tasks = [tasks]; 34 | if (!Array.isArray(tasks)) { 35 | return error(new Error('hooks.' + command + ' in package.json must be string or array')); 36 | } 37 | 38 | next(); 39 | 40 | function next() { 41 | if (tasks.length === 0) return; 42 | 43 | var task = tasks.shift(); 44 | var c = child.spawn(task, {cwd: root, stdio: 'inherit', shell: true}); 45 | c.on('exit', function (code) { 46 | if (code !== 0) { 47 | return error(new Error(fmt('task `%s` exit with code %s', task, code))); 48 | } 49 | next(); 50 | }); 51 | } 52 | } 53 | 54 | function error(err) { 55 | if (err.task) console.error('[%s] run `%s` error', command, err.task); 56 | console.error('[%s] Error Stack:\n%s', command, err.stack.replace(/^/gm, ' ')); 57 | process.exit(1); 58 | } 59 | -------------------------------------------------------------------------------- /hooks/pre-release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* generate by git-pre-hooks */ 4 | 'use strict'; 5 | 6 | var child = require('child_process'); 7 | var fmt = require('util').format; 8 | var path = require('path'); 9 | 10 | var command = path.basename(__filename); 11 | 12 | child.exec('git rev-parse --show-toplevel', function (err, stdout) { 13 | if (err) return error(err); 14 | 15 | var root = stdout.trim(); 16 | var pkg; 17 | try { 18 | pkg = require(path.join(root, 'package.json')); 19 | } catch (err) { 20 | return error(err); 21 | } 22 | 23 | // no task to run 24 | if (!pkg 25 | || !pkg['git-pre-hooks'] 26 | || !pkg['git-pre-hooks'][command] 27 | || !pkg['git-pre-hooks'][command].length) return; 28 | 29 | run(root, pkg['git-pre-hooks'][command]); 30 | }); 31 | 32 | function run(root, tasks) { 33 | if (typeof tasks === 'string') tasks = [tasks]; 34 | if (!Array.isArray(tasks)) { 35 | return error(new Error('hooks.' + command + ' in package.json must be string or array')); 36 | } 37 | 38 | next(); 39 | 40 | function next() { 41 | if (tasks.length === 0) return; 42 | 43 | var task = tasks.shift(); 44 | var c = child.spawn(task, {cwd: root, stdio: 'inherit', shell: true}); 45 | c.on('exit', function (code) { 46 | if (code !== 0) { 47 | return error(new Error(fmt('task `%s` exit with code %s', task, code))); 48 | } 49 | next(); 50 | }); 51 | } 52 | } 53 | 54 | function error(err) { 55 | if (err.task) console.error('[%s] run `%s` error', command, err.task); 56 | console.error('[%s] Error Stack:\n%s', command, err.stack.replace(/^/gm, ' ')); 57 | process.exit(1); 58 | } 59 | -------------------------------------------------------------------------------- /hooks/post-release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* generate by git-pre-hooks */ 4 | 'use strict'; 5 | 6 | var child = require('child_process'); 7 | var fmt = require('util').format; 8 | var path = require('path'); 9 | 10 | var command = path.basename(__filename); 11 | 12 | child.exec('git rev-parse --show-toplevel', function (err, stdout) { 13 | if (err) return error(err); 14 | 15 | var root = stdout.trim(); 16 | var pkg; 17 | try { 18 | pkg = require(path.join(root, 'package.json')); 19 | } catch (err) { 20 | return error(err); 21 | } 22 | 23 | // no task to run 24 | if (!pkg 25 | || !pkg['git-pre-hooks'] 26 | || !pkg['git-pre-hooks'][command] 27 | || !pkg['git-pre-hooks'][command].length) return; 28 | 29 | run(root, pkg['git-pre-hooks'][command]); 30 | }); 31 | 32 | function run(root, tasks) { 33 | if (typeof tasks === 'string') tasks = [tasks]; 34 | if (!Array.isArray(tasks)) { 35 | return error(new Error('hooks.' + command + ' in package.json must be string or array')); 36 | } 37 | 38 | next(); 39 | 40 | function next() { 41 | if (tasks.length === 0) return; 42 | 43 | var task = tasks.shift(); 44 | var c = child.spawn(task, {cwd: root, stdio: 'inherit', shell: true}); 45 | c.on('exit', function (code) { 46 | if (code !== 0) { 47 | return error(new Error(fmt('task `%s` exit with code %s', task, code))); 48 | } 49 | next(); 50 | }); 51 | } 52 | } 53 | 54 | function error(err) { 55 | if (err.task) console.error('[%s] run `%s` error', command, err.task); 56 | console.error('[%s] Error Stack:\n%s', command, err.stack.replace(/^/gm, ' ')); 57 | process.exit(1); 58 | } 59 | --------------------------------------------------------------------------------