UNPKG

6.92 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const find_up_1 = __importDefault(require("find-up"));
7const fs_1 = __importDefault(require("fs"));
8const path_1 = __importDefault(require("path"));
9const pkg_dir_1 = __importDefault(require("pkg-dir"));
10const getConf_1 = __importDefault(require("../getConf"));
11const getScript_1 = __importDefault(require("./getScript"));
12const is_1 = require("./is");
13const resolveGitDir_1 = __importDefault(require("./resolveGitDir"));
14const hookList = [
15 'applypatch-msg',
16 'pre-applypatch',
17 'post-applypatch',
18 'pre-commit',
19 'prepare-commit-msg',
20 'commit-msg',
21 'post-commit',
22 'pre-rebase',
23 'post-checkout',
24 'post-merge',
25 'pre-push',
26 'pre-receive',
27 'update',
28 'post-receive',
29 'post-update',
30 'push-to-checkout',
31 'pre-auto-gc',
32 'post-rewrite',
33 'sendemail-validate'
34];
35function writeHook(filename, script) {
36 fs_1.default.writeFileSync(filename, script, 'utf-8');
37 fs_1.default.chmodSync(filename, 0o0755);
38}
39function createHook(filename, script) {
40 // Get name, used for logging
41 const name = path_1.default.basename(filename);
42 // Check if hook exist
43 if (fs_1.default.existsSync(filename)) {
44 const hook = fs_1.default.readFileSync(filename, 'utf-8');
45 // Migrate
46 if (is_1.isGhooks(hook)) {
47 console.log(`migrating existing ghooks script: ${name}`);
48 return writeHook(filename, script);
49 }
50 // Migrate
51 if (is_1.isPreCommit(hook)) {
52 console.log(`migrating existing pre-commit script: ${name}`);
53 return writeHook(filename, script);
54 }
55 // Update
56 if (is_1.isHusky(hook) || is_1.isYorkie(hook)) {
57 return writeHook(filename, script);
58 }
59 // Skip
60 console.log(`skipping existing user hook: ${name}`);
61 return;
62 }
63 // Create hook if it doesn't exist
64 writeHook(filename, script);
65}
66function createHooks(filenames, script) {
67 filenames.forEach((filename) => createHook(filename, script));
68}
69function canRemove(filename) {
70 if (fs_1.default.existsSync(filename)) {
71 const data = fs_1.default.readFileSync(filename, 'utf-8');
72 return is_1.isHusky(data);
73 }
74 return false;
75}
76function removeHook(filename) {
77 fs_1.default.unlinkSync(filename);
78}
79function removeHooks(filenames) {
80 filenames.filter(canRemove).forEach(removeHook);
81}
82// This prevents the case where someone would want to debug a node_module that has
83// husky as devDependency and run npm install from node_modules directory
84function isInNodeModules(dir) {
85 // INIT_CWD holds the full path you were in when you ran npm install (supported also by yarn and pnpm)
86 // See https://docs.npmjs.com/cli/run-script
87 if (process.env.INIT_CWD) {
88 return process.env.INIT_CWD.indexOf('node_modules') !== -1;
89 }
90 // Old technique
91 return (dir.match(/node_modules/g) || []).length > 1;
92}
93function getHooks(gitDir) {
94 const gitHooksDir = path_1.default.join(gitDir, 'hooks');
95 return hookList.map((hookName) => path_1.default.join(gitHooksDir, hookName));
96}
97/**
98 * @param {string} huskyDir - e.g. /home/typicode/project/node_modules/husky/
99 * @param {string} requireRunNodePath - path to run-node resolved by require e.g. /home/typicode/project/node_modules/run-node/run-node
100 * @param {string} isCI - true if running in CI
101 */
102function install(huskyDir, requireRunNodePath = require.resolve('run-node/run-node'), isCI) {
103 console.log('husky > Setting up git hooks');
104 // First directory containing user's package.json
105 const userPkgDir = pkg_dir_1.default.sync(path_1.default.join(huskyDir, '..'));
106 if (userPkgDir === undefined) {
107 console.log("Can't find package.json, skipping Git hooks installation.");
108 console.log('Please check that your project has a package.json or create it and reinstall husky.');
109 return;
110 }
111 // Get conf from package.json or .huskyrc
112 const conf = getConf_1.default(userPkgDir);
113 // Get directory containing .git directory or in the case of Git submodules, the .git file
114 const gitDirOrFile = find_up_1.default.sync('.git', { cwd: userPkgDir });
115 // Resolve git directory (e.g. .git/ or .git/modules/path/to/submodule)
116 const resolvedGitDir = resolveGitDir_1.default(userPkgDir);
117 // Checks
118 if (process.env.HUSKY_SKIP_INSTALL === 'true') {
119 console.log("HUSKY_SKIP_INSTALL environment variable is set to 'true',", 'skipping Git hooks installation.');
120 return;
121 }
122 if (gitDirOrFile === null || gitDirOrFile === undefined) {
123 console.log("Can't find .git, skipping Git hooks installation.");
124 console.log("Please check that you're in a cloned repository", "or run 'git init' to create an empty Git repository and reinstall husky.");
125 return;
126 }
127 if (resolvedGitDir === null) {
128 console.log("Can't find resolved .git directory, skipping Git hooks installation.");
129 return;
130 }
131 if (isCI && conf.skipCI) {
132 console.log('CI detected, skipping Git hooks installation.');
133 return;
134 }
135 if (isInNodeModules(huskyDir)) {
136 console.log('Trying to install from node_modules directory, skipping Git hooks installation.');
137 return;
138 }
139 // Create hooks directory if doesn't exist
140 if (!fs_1.default.existsSync(path_1.default.join(resolvedGitDir, 'hooks'))) {
141 fs_1.default.mkdirSync(path_1.default.join(resolvedGitDir, 'hooks'));
142 }
143 // Create hooks
144 // Get root dir based on the first .git directory of file found
145 const rootDir = path_1.default.dirname(gitDirOrFile);
146 const hooks = getHooks(resolvedGitDir);
147 const script = getScript_1.default(rootDir, huskyDir, requireRunNodePath);
148 createHooks(hooks, script);
149 console.log(`husky > Done`);
150 console.log('husky > Like husky? You can support the project on Patreon:');
151 console.log('husky > \x1b[4;36m%s\x1b[0m ❤', 'https://www.patreon.com/typicode');
152}
153exports.install = install;
154function uninstall(huskyDir) {
155 console.log('husky > Uninstalling git hooks');
156 const userPkgDir = pkg_dir_1.default.sync(path_1.default.join(huskyDir, '..'));
157 const resolvedGitDir = resolveGitDir_1.default(userPkgDir);
158 if (resolvedGitDir === null) {
159 console.log("Can't find resolved .git directory, skipping Git hooks uninstallation.");
160 return;
161 }
162 if (isInNodeModules(huskyDir)) {
163 console.log('Trying to uninstall from node_modules directory, skipping Git hooks uninstallation.');
164 return;
165 }
166 // Remove hooks
167 const hooks = getHooks(resolvedGitDir);
168 removeHooks(hooks);
169 console.log('husky > Done');
170}
171exports.uninstall = uninstall;