Skip to content

Commit 7631c2f

Browse files
committed
fix(hook): install from subdirectory
fix #199
1 parent dda7f8d commit 7631c2f

File tree

4 files changed

+36
-14
lines changed

4 files changed

+36
-14
lines changed

src/commands/hook.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,33 @@ export default command({
2929
parameters: ['<install/uninstall>'],
3030
}, (argv) => {
3131
(async () => {
32-
await assertGitRepo();
33-
32+
const gitRepoPath = await assertGitRepo();
3433
const { installUninstall: mode } = argv._;
3534

36-
const hookExists = await fileExists(symlinkPath);
35+
const absoltueSymlinkPath = path.join(gitRepoPath, symlinkPath);
36+
const hookExists = await fileExists(absoltueSymlinkPath);
3737
if (mode === 'install') {
3838
if (hookExists) {
3939
// If the symlink is broken, it will throw an error
4040
// eslint-disable-next-line @typescript-eslint/no-empty-function
41-
const realpath = await fs.realpath(symlinkPath).catch(() => {});
41+
const realpath = await fs.realpath(absoltueSymlinkPath).catch(() => {});
4242
if (realpath === hookPath) {
4343
console.warn('The hook is already installed');
4444
return;
4545
}
4646
throw new KnownError(`A different ${hookName} hook seems to be installed. Please remove it before installing aicommits.`);
4747
}
4848

49-
await fs.mkdir(path.dirname(symlinkPath), { recursive: true });
49+
await fs.mkdir(path.dirname(absoltueSymlinkPath), { recursive: true });
5050

5151
if (isWindows) {
5252
await fs.writeFile(
53-
symlinkPath,
53+
absoltueSymlinkPath,
5454
windowsHook,
5555
);
5656
} else {
57-
await fs.symlink(hookPath, symlinkPath, 'file');
58-
await fs.chmod(symlinkPath, 0o755);
57+
await fs.symlink(hookPath, absoltueSymlinkPath, 'file');
58+
await fs.chmod(absoltueSymlinkPath, 0o755);
5959
}
6060
console.log(`${green('✔')} Hook installed`);
6161
return;
@@ -68,20 +68,20 @@ export default command({
6868
}
6969

7070
if (isWindows) {
71-
const scriptContent = await fs.readFile(symlinkPath, 'utf8');
71+
const scriptContent = await fs.readFile(absoltueSymlinkPath, 'utf8');
7272
if (scriptContent !== windowsHook) {
7373
console.warn('Hook is not installed');
7474
return;
7575
}
7676
} else {
77-
const realpath = await fs.realpath(symlinkPath);
77+
const realpath = await fs.realpath(absoltueSymlinkPath);
7878
if (realpath !== hookPath) {
7979
console.warn('Hook is not installed');
8080
return;
8181
}
8282
}
8383

84-
await fs.rm(symlinkPath);
84+
await fs.rm(absoltueSymlinkPath);
8585
console.log(`${green('✔')} Hook uninstalled`);
8686
return;
8787
}

src/utils/git.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { execa } from 'execa';
22
import { KnownError } from './error.js';
33

44
export const assertGitRepo = async () => {
5-
const { stdout } = await execa('git', ['rev-parse', '--is-inside-work-tree'], { reject: false });
5+
const { stdout, failed } = await execa('git', ['rev-parse', '--show-toplevel'], { reject: false });
66

7-
if (stdout !== 'true') {
7+
if (failed) {
88
throw new KnownError('The current directory must be a Git repository!');
99
}
10+
11+
return stdout;
1012
};
1113

1214
const excludeFromDiff = (path: string) => `:(exclude)${path}`;

tests/specs/git-hook.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'path';
12
import { testSuite, expect } from 'manten';
23
import {
34
assertOpenAiToken,
@@ -22,6 +23,25 @@ export default testSuite(({ describe }) => {
2223
await fixture.rm();
2324
});
2425

26+
test('installs from Git repo subdirectory', async () => {
27+
const { fixture, aicommits } = await createFixture({
28+
...files,
29+
'some-dir': {
30+
'file.txt': '',
31+
},
32+
});
33+
await createGit(fixture.path);
34+
35+
const { stdout } = await aicommits(['hook', 'install'], {
36+
cwd: path.join(fixture.path, 'some-dir'),
37+
});
38+
expect(stdout).toMatch('Hook installed');
39+
40+
expect(await fixture.exists('.git/hooks/prepare-commit-msg')).toBe(true);
41+
42+
await fixture.rm();
43+
});
44+
2545
test('Commits', async () => {
2646
const { fixture, aicommits } = await createFixture(files);
2747
const git = await createGit(fixture.path);

tests/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ const createAicommits = (fixture: FsFixture) => {
1919
args?: string[],
2020
options?: Options,
2121
) => execaNode(aicommitsPath, args, {
22-
...options,
2322
cwd: fixture.path,
23+
...options,
2424
extendEnv: false,
2525
env: {
2626
...homeEnv,

0 commit comments

Comments
 (0)