Skip to content

Commit 2f3ec3f

Browse files
authored
feat: silent success if nothing has changed (#138)
1 parent 33af460 commit 2f3ec3f

File tree

4 files changed

+56
-4
lines changed

4 files changed

+56
-4
lines changed

.changeset/easy-sites-stick.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"simple-git-hooks": minor
3+
---
4+
5+
feat: silent success if nothing has changed

cli.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,11 @@ if(skipInstall()) {
1111
}
1212

1313
setHooksFromConfig(process.cwd(), process.argv)
14-
.then(() => console.log('[INFO] Successfully set all git hooks'))
14+
.then(({ isHookChanged }) => {
15+
if (!isHookChanged) {
16+
// all configured hooks are set but with same contents, silent success
17+
return
18+
}
19+
console.log('[INFO] Successfully set all git hooks')
20+
})
1521
.catch(e => console.log('[ERROR], Was not able to set git hooks. Error: ' + e))

simple-git-hooks.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,22 @@ async function setHooksFromConfig(projectRootPath=process.cwd(), argv=process.ar
180180

181181
const preserveUnused = Array.isArray(config.preserveUnused) ? config.preserveUnused : config.preserveUnused ? VALID_GIT_HOOKS: []
182182

183+
let isHookChanged = false
184+
183185
for (let hook of VALID_GIT_HOOKS) {
184186
if (Object.prototype.hasOwnProperty.call(config, hook)) {
185-
_setHook(hook, config[hook], projectRootPath)
187+
const isHookUpdated = _setHook(hook, config[hook], projectRootPath).hookChanged
188+
isHookChanged = isHookChanged || isHookUpdated
186189
} else if (!preserveUnused.includes(hook)) {
187-
_removeHook(hook, projectRootPath)
190+
const isHookDeleted = _removeHook(hook, projectRootPath)
191+
isHookChanged = isHookChanged || isHookDeleted
188192
}
189193
}
194+
195+
196+
return {
197+
isHookChanged,
198+
}
190199
}
191200

192201
/**
@@ -230,7 +239,10 @@ function _setHook(hook, command, projectRoot=process.cwd()) {
230239

231240
if (!gitRoot) {
232241
console.info('[INFO] No `.git` root folder found, skipping')
233-
return
242+
return {
243+
hookChanged: false,
244+
success: false
245+
}
234246
}
235247

236248
const hookCommand = PREPEND_SCRIPT + command
@@ -242,10 +254,23 @@ function _setHook(hook, command, projectRoot=process.cwd()) {
242254
fs.mkdirSync(normalizedHookDirectory, { recursive: true })
243255
}
244256

257+
if (fs.existsSync(hookPath)) {
258+
const existingHook = fs.readFileSync(hookPath, { encoding: 'utf-8' })
259+
if (existingHook === hookCommand) {
260+
return {
261+
hookChanged: false,
262+
success: true
263+
}
264+
}
265+
}
245266
fs.writeFileSync(hookPath, hookCommand)
246267
fs.chmodSync(hookPath, 0o0755)
247268

248269
console.info(`[INFO] Successfully set the ${hook} with command: ${command}`)
270+
return {
271+
hookChanged: true,
272+
success: true
273+
}
249274
}
250275

251276
/**
@@ -272,6 +297,7 @@ async function removeHooks(projectRoot = process.cwd()) {
272297
* Removes the pre-commit hook
273298
* @param {string} hook
274299
* @param {string} projectRoot
300+
* @returns {boolean} whether the hook was removed
275301
* @private
276302
*/
277303
function _removeHook(hook, projectRoot=process.cwd()) {
@@ -280,7 +306,9 @@ function _removeHook(hook, projectRoot=process.cwd()) {
280306

281307
if (fs.existsSync(hookPath)) {
282308
fs.unlinkSync(hookPath)
309+
return true
283310
}
311+
return false
284312
}
285313

286314
/** Reads package.json file, returns package.json content and path

simple-git-hooks.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,19 @@ describe("Simple Git Hooks tests", () => {
653653
expect(installedHooks).toEqual({ "pre-commit": TEST_SCRIPT });
654654
});
655655
});
656+
657+
describe('should silently succeed if all hooks are already installed', () => {
658+
it('silent success by default', async () => {
659+
createGitHooksFolder(PROJECT_WITH_CONF_IN_SEPARATE_JSON);
660+
661+
const output1 = execSync(`node ${require.resolve("./cli")}`, { cwd: PROJECT_WITH_CONF_IN_SEPARATE_JSON, encoding: 'utf8' });
662+
expect(output1).toMatch(/\[INFO\] Successfully set all git hooks/);
663+
expect(output1).toMatch(/\[INFO\] Successfully set the pre-commit with command: exit 1/);
664+
665+
const output2 = execSync(`node ${require.resolve("./cli")}`, { cwd: PROJECT_WITH_CONF_IN_SEPARATE_JSON, encoding: 'utf8' }).trim();
666+
expect(output2).toBe('');
667+
})
668+
});
656669
});
657670

658671
describe("ENV vars features tests", () => {

0 commit comments

Comments
 (0)