From 5185f3365c3a227dc0f50309dcc7b75a852d5133 Mon Sep 17 00:00:00 2001 From: Matt <44251435+matt-degraffenreid@users.noreply.github.com> Date: Fri, 31 Mar 2023 23:29:22 -0600 Subject: [PATCH] Feature work with husky (#47) (#79) * refactor(cli.ts): call isHookCalled function asynchronously feat(githook.ts): add support for git core hooks path and fallback to default symlink url if not found feat(utils/git.ts): add getCoreHooksPath function to retrieve the path of the core hooks directory. * refactor(githook.ts): remove console.log statement from hookCommand function * feat(prepare-commit-msg-hook.ts): add isStageAllFlag parameter to prepareCommitMessageHook function to stage all changes if flag is true * refactor(githook.ts): use path.join to join path segments instead of string concatenation style(githook.ts): format code with prettier --- src/cli.ts | 3 ++- src/commands/githook.ts | 36 ++++++++++++++++++------- src/commands/prepare-commit-msg-hook.ts | 18 +++++++------ src/utils/git.ts | 8 ++++++ 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 734baaa..8dda745 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -22,7 +22,8 @@ cli( }, async () => { // await checkIsLatestVersion(); - if (isHookCalled) { + + if (await isHookCalled()) { prepareCommitMessageHook(); } else { commit(extraArgs); diff --git a/src/commands/githook.ts b/src/commands/githook.ts index 604255a..9b82bfe 100755 --- a/src/commands/githook.ts +++ b/src/commands/githook.ts @@ -1,12 +1,13 @@ import fs from 'fs/promises'; import path from 'path'; import { command } from 'cleye'; -import { assertGitRepo } from '../utils/git.js'; +import { assertGitRepo, getCoreHooksPath } from '../utils/git.js'; import { existsSync } from 'fs'; import chalk from 'chalk'; import { intro, outro } from '@clack/prompts'; import { COMMANDS } from '../CommandsEnum.js'; + const platform = process.platform; let separator = ''; @@ -29,11 +30,26 @@ switch (platform) { } const HOOK_NAME = 'prepare-commit-msg'; -const SYMLINK_URL = path.join(separator, '.git', 'hooks', HOOK_NAME); +const DEFAULT_SYMLINK_URL = path.join(separator, '.git', 'hooks', HOOK_NAME); -export const isHookCalled = process.argv[1].endsWith(`${SYMLINK_URL}`); +const getHooksPath = async (): Promise => { + try { + const hooksPath = await getCoreHooksPath(); + return path.join(hooksPath, HOOK_NAME); + } catch (error) { + return DEFAULT_SYMLINK_URL; + } +}; -const isHookExists = existsSync(SYMLINK_URL); +export const isHookCalled = async (): Promise => { + const hooksPath = await getHooksPath(); + return process.argv[1].endsWith(hooksPath); +}; + +const isHookExists = async (): Promise => { + const hooksPath = await getHooksPath(); + return existsSync(hooksPath); +}; export const hookCommand = command( { @@ -42,16 +58,16 @@ export const hookCommand = command( }, async (argv) => { const HOOK_URL = __filename; - + const SYMLINK_URL = await getHooksPath(); try { await assertGitRepo(); const { setUnset: mode } = argv._; if (mode === 'set') { - intro(`setting OpenCommit as '${HOOK_NAME}' hook`); + intro(`setting opencommit as '${HOOK_NAME}' hook at ${SYMLINK_URL}`); - if (isHookExists) { + if (await isHookExists()) { let realPath; try { realPath = await fs.realpath(SYMLINK_URL); @@ -76,9 +92,11 @@ export const hookCommand = command( } if (mode === 'unset') { - intro(`unsetting OpenCommit as '${HOOK_NAME}' hook`); + intro( + `unsetting opencommit as '${HOOK_NAME}' hook from ${SYMLINK_URL}` + ); - if (!isHookExists) { + if (!(await isHookExists())) { return outro( `OpenCommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove` ); diff --git a/src/commands/prepare-commit-msg-hook.ts b/src/commands/prepare-commit-msg-hook.ts index 00aa835..1231128 100644 --- a/src/commands/prepare-commit-msg-hook.ts +++ b/src/commands/prepare-commit-msg-hook.ts @@ -7,7 +7,9 @@ import { generateCommitMessageWithChatCompletion } from '../generateCommitMessag const [messageFilePath, commitSource] = process.argv.slice(2); -export const prepareCommitMessageHook = async () => { +export const prepareCommitMessageHook = async ( + isStageAllFlag: Boolean = false +) => { try { if (!messageFilePath) { throw new Error( @@ -17,16 +19,16 @@ export const prepareCommitMessageHook = async () => { if (commitSource) return; - const stagedFiles = await getStagedFiles(); - const changedFiles = await getChangedFiles(); + if (isStageAllFlag) { + const changedFiles = await getChangedFiles(); - if (!stagedFiles && !changedFiles) { - outro('No changes detected, write some code and run `oc` again'); - process.exit(1); + if (changedFiles) await gitAdd({ files: changedFiles }); + else { + outro('No changes detected, write some code and run `oc` again'); + process.exit(1); + } } - if (!stagedFiles && changedFiles) await gitAdd({ files: changedFiles }); - const staged = await getStagedFiles(); if (!staged) return; diff --git a/src/utils/git.ts b/src/utils/git.ts index d397b8f..f8510df 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -25,6 +25,14 @@ export const getOpenCommitIgnore = (): Ignore => { return ig; }; +export const getCoreHooksPath = async(): Promise => { + const { stdout } = await execa('git', [ + 'config', + 'core.hooksPath']); + + return stdout; +} + export const getStagedFiles = async (): Promise => { const { stdout: gitDir } = await execa('git', [ 'rev-parse',