@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
JavaScript
;
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;