husky
Advanced tools
Comparing version 0.14.0 to 0.14.1-0
@@ -5,30 +5,44 @@ 'use strict' | ||
const path = require('path') | ||
const mock = require('mock-fs') | ||
const mkdirp = require('mkdirp') | ||
const rimraf = require('rimraf') | ||
const tempy = require('tempy') | ||
const installFrom = require('../src/install') | ||
const uninstallFrom = require('../src/uninstall') | ||
const gitDir = '/.git' | ||
function install(rootDir, dir) { | ||
installFrom(path.join(rootDir, dir)) | ||
} | ||
function readHook(hookPath) { | ||
return fs.readFileSync(path.join(gitDir, hookPath), 'utf-8') | ||
function uninstall(rootDir, dir) { | ||
uninstallFrom(path.join(rootDir, dir)) | ||
} | ||
function exists(hookPath) { | ||
return fs.existsSync(path.join(gitDir, hookPath)) | ||
function mkdir(rootDir, dir) { | ||
mkdirp.sync(path.join(rootDir, dir)) | ||
} | ||
describe('husky', function() { | ||
afterEach(function() { | ||
mock.restore() | ||
}) | ||
function writeFile(dir, filePath, data) { | ||
fs.writeFileSync(path.join(dir, filePath), data) | ||
} | ||
it('should support basic layout', function() { | ||
mock({ | ||
'/.git/hooks': {}, | ||
'/node_modules/husky': {} | ||
}) | ||
function readFile(dir, filePath) { | ||
return fs.readFileSync(path.join(dir, filePath), 'utf-8') | ||
} | ||
installFrom('/node_modules/husky') | ||
const hook = readHook('hooks/pre-commit') | ||
function exists(dir, filePath) { | ||
return fs.existsSync(path.join(dir, filePath)) | ||
} | ||
describe('husky', () => { | ||
let dir | ||
beforeEach(() => (dir = tempy.directory())) | ||
afterEach(() => rimraf.sync(dir)) | ||
it('should support basic layout', () => { | ||
mkdir(dir, '.git/hooks') | ||
mkdir(dir, 'node_modules/husky') | ||
install(dir, '/node_modules/husky') | ||
const hook = readFile(dir, '.git/hooks/pre-commit') | ||
expect(hook).toMatch('#husky') | ||
@@ -39,121 +53,107 @@ expect(hook).toMatch('cd .') | ||
const prepareCommitMsg = readHook('hooks/prepare-commit-msg') | ||
const prepareCommitMsg = readFile(dir, '.git/hooks/prepare-commit-msg') | ||
expect(prepareCommitMsg).toMatch('cannot be bypassed') | ||
uninstallFrom('/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeFalsy() | ||
uninstall(dir, 'node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeFalsy() | ||
}) | ||
it('should support project installed in sub directory', function() { | ||
mock({ | ||
'/.git/hooks': {}, | ||
'/A/B/node_modules/husky': {} | ||
}) | ||
it('should support project installed in sub directory', () => { | ||
mkdir(dir, '.git/hooks') | ||
mkdir(dir, 'A/B/node_modules/husky') | ||
installFrom('/A/B/node_modules/husky') | ||
const hook = readHook('hooks/pre-commit') | ||
install(dir, 'A/B/node_modules/husky') | ||
const hook = readFile(dir, '.git/hooks/pre-commit') | ||
expect(hook).toMatch('cd A/B') | ||
uninstallFrom('/A/B/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeFalsy() | ||
uninstall(dir, 'A/B/node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeFalsy() | ||
}) | ||
it('should support git submodule', function() { | ||
mock({ | ||
'/.git/modules/A/B': {}, | ||
'/A/B/.git': 'git: ../../.git/modules/A/B', | ||
'/A/B/node_modules/husky': {} | ||
}) | ||
it('should support git submodule', () => { | ||
mkdir(dir, '.git/modules/A/B') | ||
mkdir(dir, 'A/B/node_modules/husky') | ||
writeFile(dir, 'A/B/.git', 'git: ../../.git/modules/A/B') | ||
installFrom('/A/B/node_modules/husky') | ||
const hook = readHook('modules/A/B/hooks/pre-commit') | ||
install(dir, 'A/B/node_modules/husky') | ||
const hook = readFile(dir, '.git/modules/A/B/hooks/pre-commit') | ||
expect(hook).toMatch('cd .') | ||
uninstallFrom('/A/B/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeFalsy() | ||
uninstall(dir, 'A/B/node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeFalsy() | ||
}) | ||
it('should support git submodule and sub directory', function() { | ||
mock({ | ||
'/.git/modules/A/B': {}, | ||
'/A/B/.git': 'git: ../../.git/modules/A/B', | ||
'/A/B/C/node_modules/husky': {} | ||
}) | ||
it('should support git submodule and sub directory', () => { | ||
mkdir(dir, '.git/modules/A/B') | ||
mkdir(dir, 'A/B/C/node_modules/husky') | ||
writeFile(dir, 'A/B/.git', 'git: ../../.git/modules/A/B') | ||
installFrom('/A/B/C/node_modules/husky') | ||
const hook = readHook('modules/A/B/hooks/pre-commit') | ||
install(dir, 'A/B/C/node_modules/husky') | ||
const hook = readFile(dir, '.git/modules/A/B/hooks/pre-commit') | ||
expect(hook).toMatch('cd C') | ||
uninstallFrom('/A/B/app/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeFalsy() | ||
uninstall(dir, 'A/B/app/node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeFalsy() | ||
}) | ||
it('should support git worktrees', function() { | ||
mock({ | ||
'/.git/worktrees/B': {}, | ||
'/A/B/.git': 'git: /.git/worktrees/B', | ||
'/A/B/node_modules/husky': {} | ||
}) | ||
it('should support git worktrees', () => { | ||
mkdir(dir, '.git/worktrees/B') | ||
mkdir(dir, 'A/B/node_modules/husky') | ||
installFrom('/A/B/node_modules/husky') | ||
const hook = readHook('worktrees/B/hooks/pre-commit') | ||
// Git path for worktrees is absolute | ||
const absolutePath = path.join(dir, '.git/worktrees/B') | ||
writeFile(dir, 'A/B/.git', `git: ${absolutePath}`) | ||
install(dir, 'A/B/node_modules/husky') | ||
const hook = readFile(dir, '.git/worktrees/B/hooks/pre-commit') | ||
expect(hook).toMatch('cd .') | ||
uninstallFrom('/A/B/node_modules/husky') | ||
expect(exists('hooks/pre-commit')).toBeFalsy() | ||
uninstall(dir, 'A/B/node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-commit')).toBeFalsy() | ||
}) | ||
it('should not modify user hooks', function() { | ||
mock({ | ||
'/.git/hooks': {}, | ||
'/.git/hooks/pre-push': 'foo', | ||
'/node_modules/husky': {} | ||
}) | ||
it('should not modify user hooks', () => { | ||
mkdir(dir, '.git/hooks') | ||
mkdir(dir, 'node_modules/husky') | ||
writeFile(dir, '.git/hooks/pre-push', 'foo') | ||
// Verify that it's not overwritten | ||
installFrom('/node_modules/husky') | ||
const hook = readHook('hooks/pre-push') | ||
install(dir, 'node_modules/husky') | ||
const hook = readFile(dir, '.git/hooks/pre-push') | ||
expect(hook).toBe('foo') | ||
uninstallFrom('/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeTruthy() | ||
uninstall(dir, 'node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeTruthy() | ||
}) | ||
it('should not install from /node_modules/A/node_modules', function() { | ||
mock({ | ||
'/.git/hooks': {}, | ||
'/node_modules/A/node_modules/husky': {} | ||
}) | ||
it('should not install from /node_modules/A/node_modules', () => { | ||
mkdir(dir, '.git/hooks') | ||
mkdir(dir, 'node_modules/A/node_modules/husky') | ||
installFrom('/node_modules/A/node_modules/husky') | ||
expect(exists('hooks/pre-push')).toBeFalsy() | ||
install(dir, 'node_modules/A/node_modules/husky') | ||
expect(exists(dir, '.git/hooks/pre-push')).toBeFalsy() | ||
}) | ||
it("should not crash if there's no .git directory", function() { | ||
mock({ | ||
'/node_modules/husky': {} | ||
}) | ||
it("should not crash if there's no .git directory", () => { | ||
mkdir(dir, 'node_modules/husky') | ||
expect(function() { | ||
installFrom('/node_modules/husky') | ||
}).not.toThrow() | ||
expect(function() { | ||
uninstallFrom('/node_modules/husky') | ||
}).not.toThrow() | ||
expect(() => install(dir, 'node_modules/husky')).not.toThrow() | ||
expect(() => uninstall(dir, 'node_modules/husky')).not.toThrow() | ||
}) | ||
it('should migrate ghooks scripts', function() { | ||
mock({ | ||
'/.git/hooks/pre-commit': | ||
'// Generated by ghooks. Do not edit this file.', | ||
'/node_modules/husky': {} | ||
}) | ||
it('should migrate ghooks scripts', () => { | ||
mkdir(dir, '.git/hooks') | ||
mkdir(dir, '/node_modules/husky') | ||
writeFile( | ||
dir, | ||
'.git/hooks/pre-commit', | ||
'// Generated by ghooks. Do not edit this file.' | ||
) | ||
installFrom('/node_modules/husky') | ||
const hook = readHook('hooks/pre-commit') | ||
install(dir, 'node_modules/husky') | ||
const hook = readFile(dir, '.git/hooks/pre-commit') | ||
expect(hook).toMatch('husky') | ||
@@ -160,0 +160,0 @@ expect(hook).not.toMatch('ghooks') |
{ | ||
"name": "husky", | ||
"version": "0.14.0", | ||
"version": "0.14.1-0", | ||
"description": "Prevents bad commit or push (git hooks, pre-commit/precommit, pre-push/prepush, post-merge/postmerge and all that stuff...)", | ||
@@ -40,5 +40,6 @@ "engines": { | ||
"jest": "^20.0.4", | ||
"mock-fs": "^4.4.1", | ||
"mkdirp": "^0.5.1", | ||
"prettier": "^1.4.4", | ||
"rimraf": "^2.2.8" | ||
"rimraf": "^2.6.1", | ||
"tempy": "^0.1.0" | ||
}, | ||
@@ -45,0 +46,0 @@ "dependencies": { |
@@ -13,2 +13,6 @@ # husky [![](http://img.shields.io/npm/dm/husky.svg?style=flat)](https://www.npmjs.org/package/husky) [![npm version](https://badge.fury.io/js/husky.svg)](https://www.npmjs.com/package/husky) [![Build Status](https://travis-ci.org/typicode/husky.svg?branch=master)](https://travis-ci.org/typicode/husky) | ||
```sh | ||
yarn add husky --dev | ||
``` | ||
```javascript | ||
@@ -46,6 +50,10 @@ // Edit package.json | ||
```bash | ||
npm uninstall husky --save-dev | ||
```sh | ||
npm uninstall husky | ||
``` | ||
```sh | ||
yarn remove husky | ||
``` | ||
## Tricks | ||
@@ -104,2 +112,3 @@ | ||
* [pkg-ok](https://github.com/typicode/pkg-ok) - prevents publishing modules with bad paths | ||
* [react-fake-props](https://github.com/typicode/react-fake-props) - Fake props for your React tests | ||
@@ -106,0 +115,0 @@ ## License |
@@ -17,8 +17,8 @@ 'use strict' | ||
// git: pathToGit | ||
gitDir = fs.readFileSync(gitDir, 'utf-8').split(':')[1].trim() | ||
return path.resolve(dir, gitDir, 'hooks') | ||
// On Windows pathToGit can contain ':' (example "gitdir: C:/Some/Path") | ||
const gitFileData = fs.readFileSync(gitDir, 'utf-8') | ||
gitDir = gitFileData.split(':').slice(1).join(':').trim() | ||
} | ||
return path.join(gitDir, 'hooks') | ||
return path.resolve(dir, gitDir, 'hooks') | ||
} | ||
@@ -25,0 +25,0 @@ } |
@@ -7,11 +7,11 @@ 'use strict' | ||
module.exports = function findParent(currentDir, name) { | ||
const dirs = currentDir.split('/') | ||
const dirs = currentDir.split(path.sep) | ||
while (dirs.pop()) { | ||
const dir = dirs.join('/') | ||
const dir = dirs.join(path.sep) | ||
if (fs.existsSync(`${dir}/${name}`)) { | ||
return path.resolve(`${dir}/`) | ||
if (fs.existsSync(path.join(dir, name))) { | ||
return path.resolve(dir) | ||
} | ||
} | ||
} |
@@ -14,20 +14,29 @@ 'use strict' | ||
// https://github.com/typicode/husky/issues/49 | ||
return 'export PATH="$PATH:/c/Program Files/nodejs"' | ||
return stripIndent( | ||
` | ||
# Node standard installation | ||
export PATH="$PATH:/c/Program Files/nodejs"'` | ||
) | ||
} else { | ||
// ~ is unavaible, so $HOME is used | ||
const home = process.env.HOME | ||
// Using normalize to support ' in path | ||
// https://github.com/typicode/husky/issues/117 | ||
const home = normalize(process.env.HOME) | ||
// Add | ||
// Brew standard installation path /usr/local/bin | ||
// Node standard installation path /usr/local | ||
// for GUI apps | ||
// https://github.com/typicode/husky/issues/49 | ||
const arr = [ | ||
stripIndent(` | ||
stripIndent( | ||
` | ||
load_nvm () { | ||
export $1=$2 | ||
command_exists nvm || [ -s "$2/nvm.sh" ] && . $2/nvm.sh | ||
# If nvm is not loaded, load it | ||
command_exists nvm || { | ||
export NVM_DIR=${home}/.nvm | ||
[ -s "$1/nvm.sh" ] && . $1/nvm.sh | ||
} | ||
# If nvm has been loaded correctly, use project .nvmrc | ||
command_exists nvm && [ -f .nvmrc ] && nvm use | ||
} | ||
# Add common path where Node can be found | ||
# Brew standard installation path /usr/local/bin | ||
# Node standard installation path /usr/local | ||
export PATH=$PATH:/usr/local/bin:/usr/local` | ||
@@ -37,9 +46,20 @@ ) | ||
arr.push( | ||
stripIndent( | ||
` | ||
# nvm path with standard installation | ||
load_nvm ${home}/.nvm` | ||
) | ||
) | ||
if (process.platform === 'darwin') { | ||
// Load nvm with BREW_NVM_DIR set to /usr/local/opt/nvm | ||
arr.push('load_nvm BREW_NVM_DIR /usr/local/opt/nvm') | ||
arr.push( | ||
stripIndent( | ||
` | ||
# nvm path installed with Brew | ||
load_nvm /usr/local/opt/nvm` | ||
) | ||
) | ||
} | ||
// Load nvm with NVM_DIR set to $HOME/.nvm | ||
arr.push(`load_nvm NVM_DIR ${home}/.nvm`) | ||
return arr.join('\n') | ||
@@ -68,3 +88,2 @@ } | ||
# https://github.com/typicode/husky/issues/76 | ||
has_hook_script () { | ||
@@ -76,2 +95,3 @@ [ -f package.json ] && cat package.json | grep -q "\\"$1\\"[[:space:]]*:" | ||
# Check if ${npmScriptName} script is defined, skip if not | ||
has_hook_script ${npmScriptName} || exit 0` | ||
@@ -82,20 +102,21 @@ ).trim(), | ||
` | ||
# Check that npm exists | ||
command_exists npm || { | ||
echo >&2 "husky > Can't find npm in PATH. Skipping ${npmScriptName} script in package.json" | ||
echo >&2 "husky > can't find npm in PATH, skipping ${npmScriptName} script in package.json" | ||
exit 0 | ||
} | ||
# Expose GIT params | ||
# Export Git hook params | ||
export GIT_PARAMS="$*" | ||
# Run script | ||
echo "husky > npm run -s ${npmScriptName} (node \`node -v\`)" | ||
# Run npm script | ||
echo "husky > npm run -s ${npmScriptName} (node \`node -v\`)\\n" | ||
echo | ||
npm run -s ${npmScriptName} || { | ||
echo | ||
echo "husky > ${hookName} hook failed ${noVerifyMessage}" | ||
echo "\\nhusky > ${hookName} hook failed ${noVerifyMessage}" | ||
exit 1 | ||
}` | ||
).trim() | ||
} | ||
` | ||
) | ||
].join('\n') | ||
} |
Sorry, the diff of this file is not supported yet
90568
414
115
5