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
This commit is contained in:
Matt
2023-03-31 23:29:22 -06:00
committed by GitHub
parent 17ed061f73
commit 5185f3365c
4 changed files with 47 additions and 18 deletions
+2 -1
View File
@@ -22,7 +22,8 @@ cli(
}, },
async () => { async () => {
// await checkIsLatestVersion(); // await checkIsLatestVersion();
if (isHookCalled) {
if (await isHookCalled()) {
prepareCommitMessageHook(); prepareCommitMessageHook();
} else { } else {
commit(extraArgs); commit(extraArgs);
+27 -9
View File
@@ -1,12 +1,13 @@
import fs from 'fs/promises'; import fs from 'fs/promises';
import path from 'path'; import path from 'path';
import { command } from 'cleye'; import { command } from 'cleye';
import { assertGitRepo } from '../utils/git.js'; import { assertGitRepo, getCoreHooksPath } from '../utils/git.js';
import { existsSync } from 'fs'; import { existsSync } from 'fs';
import chalk from 'chalk'; import chalk from 'chalk';
import { intro, outro } from '@clack/prompts'; import { intro, outro } from '@clack/prompts';
import { COMMANDS } from '../CommandsEnum.js'; import { COMMANDS } from '../CommandsEnum.js';
const platform = process.platform; const platform = process.platform;
let separator = ''; let separator = '';
@@ -29,11 +30,26 @@ switch (platform) {
} }
const HOOK_NAME = 'prepare-commit-msg'; 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<string> => {
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<boolean> => {
const hooksPath = await getHooksPath();
return process.argv[1].endsWith(hooksPath);
};
const isHookExists = async (): Promise<boolean> => {
const hooksPath = await getHooksPath();
return existsSync(hooksPath);
};
export const hookCommand = command( export const hookCommand = command(
{ {
@@ -42,16 +58,16 @@ export const hookCommand = command(
}, },
async (argv) => { async (argv) => {
const HOOK_URL = __filename; const HOOK_URL = __filename;
const SYMLINK_URL = await getHooksPath();
try { try {
await assertGitRepo(); await assertGitRepo();
const { setUnset: mode } = argv._; const { setUnset: mode } = argv._;
if (mode === 'set') { 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; let realPath;
try { try {
realPath = await fs.realpath(SYMLINK_URL); realPath = await fs.realpath(SYMLINK_URL);
@@ -76,9 +92,11 @@ export const hookCommand = command(
} }
if (mode === 'unset') { 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( return outro(
`OpenCommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove` `OpenCommit wasn't previously set as '${HOOK_NAME}' hook, nothing to remove`
); );
+10 -8
View File
@@ -7,7 +7,9 @@ import { generateCommitMessageWithChatCompletion } from '../generateCommitMessag
const [messageFilePath, commitSource] = process.argv.slice(2); const [messageFilePath, commitSource] = process.argv.slice(2);
export const prepareCommitMessageHook = async () => { export const prepareCommitMessageHook = async (
isStageAllFlag: Boolean = false
) => {
try { try {
if (!messageFilePath) { if (!messageFilePath) {
throw new Error( throw new Error(
@@ -17,16 +19,16 @@ export const prepareCommitMessageHook = async () => {
if (commitSource) return; if (commitSource) return;
const stagedFiles = await getStagedFiles(); if (isStageAllFlag) {
const changedFiles = await getChangedFiles(); const changedFiles = await getChangedFiles();
if (!stagedFiles && !changedFiles) { if (changedFiles) await gitAdd({ files: changedFiles });
outro('No changes detected, write some code and run `oc` again'); else {
process.exit(1); 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(); const staged = await getStagedFiles();
if (!staged) return; if (!staged) return;
+8
View File
@@ -25,6 +25,14 @@ export const getOpenCommitIgnore = (): Ignore => {
return ig; return ig;
}; };
export const getCoreHooksPath = async(): Promise<string> => {
const { stdout } = await execa('git', [
'config',
'core.hooksPath']);
return stdout;
}
export const getStagedFiles = async (): Promise<string[]> => { export const getStagedFiles = async (): Promise<string[]> => {
const { stdout: gitDir } = await execa('git', [ const { stdout: gitDir } = await execa('git', [
'rev-parse', 'rev-parse',