Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/easy-sites-stick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"simple-git-hooks": minor
---

feat: silent success if nothing has changed
8 changes: 7 additions & 1 deletion cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,11 @@ if(skipInstall()) {
}

setHooksFromConfig(process.cwd(), process.argv)
.then(() => console.log('[INFO] Successfully set all git hooks'))
.then(({ isHookChanged }) => {
if (!isHookChanged) {
// all configured hooks are set but with same contents, silent success
return
}
console.log('[INFO] Successfully set all git hooks')
})
.catch(e => console.log('[ERROR], Was not able to set git hooks. Error: ' + e))
34 changes: 31 additions & 3 deletions simple-git-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,22 @@ async function setHooksFromConfig(projectRootPath=process.cwd(), argv=process.ar

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

let isHookUpdated = false
let isHookDeleted = false

for (let hook of VALID_GIT_HOOKS) {
if (Object.prototype.hasOwnProperty.call(config, hook)) {
_setHook(hook, config[hook], projectRootPath)
isHookUpdated = _setHook(hook, config[hook], projectRootPath).hookChanged
} else if (!preserveUnused.includes(hook)) {
_removeHook(hook, projectRootPath)
isHookDeleted = _removeHook(hook, projectRootPath)
}
}

const isHookChanged = isHookUpdated || isHookDeleted

return {
isHookChanged,
}
}

/**
Expand Down Expand Up @@ -226,7 +235,10 @@ function _setHook(hook, command, projectRoot=process.cwd()) {

if (!gitRoot) {
console.info('[INFO] No `.git` root folder found, skipping')
return
return {
hookChanged: false,
success: false
}
}

const hookCommand = PREPEND_SCRIPT + command
Expand All @@ -238,10 +250,23 @@ function _setHook(hook, command, projectRoot=process.cwd()) {
fs.mkdirSync(normalizedHookDirectory, { recursive: true })
}

if (fs.existsSync(hookPath)) {
const existingHook = fs.readFileSync(hookPath, { encoding: 'utf-8' })
if (existingHook === hookCommand) {
return {
hookChanged: false,
success: true
}
}
}
fs.writeFileSync(hookPath, hookCommand)
fs.chmodSync(hookPath, 0o0755)

console.info(`[INFO] Successfully set the ${hook} with command: ${command}`)
return {
hookChanged: true,
success: true
}
}

/**
Expand All @@ -268,6 +293,7 @@ async function removeHooks(projectRoot = process.cwd()) {
* Removes the pre-commit hook
* @param {string} hook
* @param {string} projectRoot
* @returns {boolean} whether the hook was removed
* @private
*/
function _removeHook(hook, projectRoot=process.cwd()) {
Expand All @@ -276,7 +302,9 @@ function _removeHook(hook, projectRoot=process.cwd()) {

if (fs.existsSync(hookPath)) {
fs.unlinkSync(hookPath)
return true
}
return false
}

/** Reads package.json file, returns package.json content and path
Expand Down
13 changes: 13 additions & 0 deletions simple-git-hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,19 @@ describe("Simple Git Hooks tests", () => {
expect(installedHooks).toEqual({ "pre-commit": TEST_SCRIPT });
});
});

describe('should silently succeed if all hooks are already installed', () => {
it('silent success by default', async () => {
createGitHooksFolder(PROJECT_WITH_CONF_IN_SEPARATE_JSON);

const output1 = execSync(`node ${require.resolve("./cli")}`, { cwd: PROJECT_WITH_CONF_IN_SEPARATE_JSON, encoding: 'utf8' });
expect(output1).toMatch(/\[INFO\] Successfully set all git hooks/);
expect(output1).toMatch(/\[INFO\] Successfully set the pre-commit with command: exit 1/);

const output2 = execSync(`node ${require.resolve("./cli")}`, { cwd: PROJECT_WITH_CONF_IN_SEPARATE_JSON, encoding: 'utf8' }).trim();
expect(output2).toBe('');
})
});
});

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