UNPKG

@shaberman-forks/husky

Version:

Prevents bad commit or push (git hooks, pre-commit/precommit, pre-push/prepush, post-merge/postmerge and all that stuff...)

105 lines (102 loc) 3.98 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const chalk_1 = __importDefault(require("chalk")); const minimatch_1 = __importDefault(require("minimatch")); const child_process_1 = require("child_process"); const getConf_1 = require("../getConf"); const read_pkg_1 = require("../read-pkg"); // Husky <1.0.0 (commands were defined in pkg.scripts) function getOldCommand(cwd, hookName) { // In some cases, package.json may not exist // For example, when switching to gh-page branch let pkg = {}; try { pkg = read_pkg_1.readPkg(cwd); } catch (err) { if (err.code !== 'ENOENT') { throw err; } } return pkg && pkg.scripts && pkg.scripts[hookName.replace('-', '')]; } // Husky >= 1.0.0 function getCommands(cwd, hookName) { const config = getConf_1.getConf(cwd); const command = config && config.hooks && config.hooks[hookName]; if (!command) { return undefined; } // See if the command is declared as a runOnChange, i.e. `{ glob: command }` instead of just `command` if (typeof command === 'object') { let { output } = child_process_1.spawnSync('sh', ['-c', 'git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD'], { cwd }); // `output` looks like a string[], but it's really a list of null | Buffer where Buffer is line separated output = output.flatMap((s) => s && s.toString().split('\n')); return Object.entries(command) .filter(([glob]) => output.find((line) => line && minimatch_1.default(line, glob)) !== undefined) .map(([, command]) => command); } return [command]; } function runCommand(cwd, hookName, cmd, env) { console.log(`husky > ${hookName} (node ${process.version})`); const { status } = child_process_1.spawnSync('sh', ['-c', cmd], { cwd, env: Object.assign(Object.assign({}, process.env), env), stdio: 'inherit', }); if (status !== 0) { const noVerifyMessage = [ 'commit-msg', 'pre-commit', 'pre-rebase', 'pre-push', ].includes(hookName) ? '(add --no-verify to bypass)' : '(cannot be bypassed with --no-verify due to Git specs)'; console.log(`husky > ${hookName} hook failed ${noVerifyMessage}`); } // If shell exits with 127 it means that some command was not found. // However, if husky has been deleted from node_modules, it'll be a 127 too. // To be able to distinguish between both cases, 127 is changed to 1. if (status === 127) { return 1; } return status || 0; } /** * @param {array} argv process.argv * @param {string} options.cwd cwd * @param {promise} options.getStdinFn - used for mocking only */ async function run([, , hookName = '', HUSKY_GIT_PARAMS], { cwd = process.cwd() } = {}) { // Probe for commands that would want `runOnChange` data const oldCommand = getOldCommand(cwd, hookName); const commands = getCommands(cwd, hookName); // Add HUSKY_GIT_PARAMS to env const env = {}; if (HUSKY_GIT_PARAMS) { env.HUSKY_GIT_PARAMS = HUSKY_GIT_PARAMS; } if (commands) { return commands .map((command) => runCommand(cwd, hookName, command, env)) .reduce((acc, i) => (i === 0 ? acc : i), 0); } if (oldCommand) { console.log(chalk_1.default.red(` Warning: Setting ${hookName} script in package.json > scripts will be deprecated. Please move it to husky.hooks in package.json or .huskyrc file. For an automatic update you can also run: npx --no-install husky-upgrade yarn husky-upgrade See https://github.com/typicode/husky for more information. `)); return runCommand(cwd, hookName, oldCommand, env); } return 0; } exports.default = run;