diff --git a/package-lock.json b/package-lock.json index 7c4c30e90..07c295eb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,15 +24,6 @@ "js-tokens": "3.0.2" } }, - "@types/execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@types/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-mgfd93RhzjYBUHHV532turHC2j4l/qxsF/PbfDmprHDEUHmNZGlDn1CEsulGK3AfsPdhkWzZQT/S/k0UGhLGsA==", - "dev": true, - "requires": { - "@types/node": "10.0.6" - } - }, "@types/find-up": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/find-up/-/find-up-2.1.1.tgz", @@ -1280,6 +1271,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, "requires": { "lru-cache": "4.1.1", "shebang-command": "1.2.0", @@ -1611,20 +1603,6 @@ "merge": "1.2.0" } }, - "execa": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.9.0.tgz", - "integrity": "sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==", - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -2759,7 +2737,8 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "get-value": { "version": "2.0.6", @@ -3386,7 +3365,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-symbol": { "version": "1.0.1", @@ -3421,7 +3401,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "2.1.0", @@ -4225,6 +4206,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -4577,6 +4559,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, "requires": { "path-key": "2.0.1" } @@ -4808,7 +4791,8 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true }, "p-limit": { "version": "1.2.0", @@ -4902,7 +4886,8 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, "path-parse": { "version": "1.0.5", @@ -5123,7 +5108,8 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "punycode": { "version": "1.4.1", @@ -5856,6 +5842,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, "requires": { "shebang-regex": "1.0.0" } @@ -5863,7 +5850,8 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true }, "shellwords": { "version": "0.1.1", @@ -5874,7 +5862,8 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true }, "slash": { "version": "2.0.0", @@ -6272,7 +6261,8 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true }, "strip-indent": { "version": "1.0.1", @@ -7185,6 +7175,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, "requires": { "isexe": "2.0.0" } @@ -7319,7 +7310,8 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true }, "yargs": { "version": "10.1.2", diff --git a/package.json b/package.json index f58772d3f..7604f7035 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "homepage": "https://github.com/typicode/husky#readme", "dependencies": { "cosmiconfig": "^4.0.0", - "execa": "^0.9.0", "find-up": "^2.1.0", "is-ci": "^1.1.0", "pkg-dir": "^2.0.0", @@ -56,7 +55,6 @@ "slash": "^2.0.0" }, "devDependencies": { - "@types/execa": "^0.9.0", "@types/find-up": "^2.1.1", "@types/jest": "^22.2.3", "@types/node": "^10.0.6", diff --git a/src/installer/bin.ts b/src/installer/bin.ts index 6f6fb0ca0..5668aaa40 100644 --- a/src/installer/bin.ts +++ b/src/installer/bin.ts @@ -1,4 +1,3 @@ -import * as execa from 'execa' import * as fs from 'fs' import * as isCI from 'is-ci' import * as path from 'path' diff --git a/src/runner/__tests__/index.ts b/src/runner/__tests__/index.ts index 8d49719cd..0b7f24260 100644 --- a/src/runner/__tests__/index.ts +++ b/src/runner/__tests__/index.ts @@ -82,6 +82,28 @@ describe('run', () => { expect(status).toBe(1) }) + it('should support POSIX shell command on Windows', () => { + const dir = tempy.directory() + + fs.writeFileSync( + path.join(dir, 'package.json'), + JSON.stringify({ + husky: { + hooks: { + 'pre-commit': 'MSG=success npm run test --script-shell=$SHELL' + } + }, + scripts: { + test: 'echo "$MSG"' + } + }) + ) + + const status = index([, getScriptPath(dir), 'pre-commit']) + + expect(status).toBe(0) + }) + it('should support old scripts but show a deprecated message', () => { const dir = tempy.directory() diff --git a/src/runner/index.ts b/src/runner/index.ts index f1065763f..6ee5c1280 100644 --- a/src/runner/index.ts +++ b/src/runner/index.ts @@ -1,4 +1,5 @@ -import * as execa from 'execa' +import { spawnSync } from 'child_process' +import { join } from 'path' import * as readPkg from 'read-pkg' import getConf from '../getConf' @@ -17,40 +18,48 @@ export default function([, scriptPath, hookName = '']: string[]): number { const oldCommand: string | undefined = pkg && pkg.scripts && pkg.scripts[hookName.replace('-', '')] + if (command) { + console.log(`husky > ${hookName} (node ${process.version})`) + return shell(cwd, hookName, command) + } + + if (oldCommand) { + console.log() + console.log( + `Warning: Setting ${hookName} script in package.json > scripts will be deprecated in v1.0` + ) + console.log( + `Please move it to husky.hooks in package.json, a .huskyrc file, or a husky.config.js file` + ) + console.log(`Or run ./node_modules/.bin/husky-upgrade for automatic update`) + console.log() + console.log(`See https://github.com/typicode/husky for usage`) + console.log() + console.log(`husky > ${hookName} (node ${process.version})`) + return shell(cwd, hookName, oldCommand) + } + + return 0 +} + +function shell(cwd: string, hookName: string, cmds: string) { + const shellPath = process.env.SHELL || 'sh' + let status try { - if (command) { - console.log(`husky > ${hookName} (node ${process.version})`) - execa.shellSync(command, { cwd, stdio: 'inherit' }) - return 0 - } - - if (oldCommand) { - console.log() - console.log( - `Warning: Setting ${hookName} script in package.json > scripts will be deprecated in v1.0` - ) - console.log( - `Please move it to husky.hooks in package.json, a .huskyrc file, or a husky.config.js file` - ) - console.log( - `Or run ./node_modules/.bin/husky-upgrade for automatic update` - ) - console.log() - console.log(`See https://github.com/typicode/husky for usage`) - console.log() - console.log(`husky > ${hookName} (node ${process.version})`) - execa.shellSync(oldCommand, { cwd, stdio: 'inherit' }) - return 0 - } - - return 0 - } catch (e) { + status = spawnSync(shellPath as string, ['-c', cmds], { + cwd, + stdio: 'inherit' + }).status + } catch (ex) { + status = 1 + } + if (status) { const noVerifyMessage = hookName === 'prepare-commit-msg' ? '(cannot be bypassed with --no-verify due to Git specs)' : '(add --no-verify to bypass)' console.log(`husky > ${hookName} hook failed ${noVerifyMessage}`) - return 1 } + return status || 0 }