Merge pull request #496 from kykungz/resolve-top-level-git-dir

Fix git commands when executed from subdirectories
This commit is contained in:
GPT8
2025-07-23 17:10:37 +03:00
committed by GitHub
+49 -29
View File
@@ -1,7 +1,7 @@
import { execa } from 'execa'; import { execa } from 'execa';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import ignore, { Ignore } from 'ignore'; import ignore, { Ignore } from 'ignore';
import { join } from 'path';
import { outro, spinner } from '@clack/prompts'; import { outro, spinner } from '@clack/prompts';
export const assertGitRepo = async () => { export const assertGitRepo = async () => {
@@ -16,41 +16,44 @@ export const assertGitRepo = async () => {
// (file) => `:(exclude)${file}` // (file) => `:(exclude)${file}`
// ); // );
export const getOpenCommitIgnore = (): Ignore => { export const getOpenCommitIgnore = async (): Promise<Ignore> => {
const gitDir = await getGitDir();
const ig = ignore(); const ig = ignore();
try { try {
ig.add(readFileSync('.opencommitignore').toString().split('\n')); ig.add(
readFileSync(join(gitDir, '.opencommitignore')).toString().split('\n')
);
} catch (e) {} } catch (e) {}
return ig; return ig;
}; };
export const getCoreHooksPath = async (): Promise<string> => { export const getCoreHooksPath = async (): Promise<string> => {
const { stdout } = await execa('git', ['config', 'core.hooksPath']); const gitDir = await getGitDir();
const { stdout } = await execa('git', ['config', 'core.hooksPath'], {
cwd: gitDir
});
return stdout; return stdout;
}; };
export const getStagedFiles = async (): Promise<string[]> => { export const getStagedFiles = async (): Promise<string[]> => {
const { stdout: gitDir } = await execa('git', [ const gitDir = await getGitDir();
'rev-parse',
'--show-toplevel'
]);
const { stdout: files } = await execa('git', [ const { stdout: files } = await execa(
'diff', 'git',
'--name-only', ['diff', '--name-only', '--cached', '--relative'],
'--cached', { cwd: gitDir }
'--relative', );
gitDir
]);
if (!files) return []; if (!files) return [];
const filesList = files.split('\n'); const filesList = files.split('\n');
const ig = getOpenCommitIgnore(); const ig = await getOpenCommitIgnore();
const allowedFiles = filesList.filter((file) => !ig.ignores(file)); const allowedFiles = filesList.filter((file) => !ig.ignores(file));
if (!allowedFiles) return []; if (!allowedFiles) return [];
@@ -59,12 +62,17 @@ export const getStagedFiles = async (): Promise<string[]> => {
}; };
export const getChangedFiles = async (): Promise<string[]> => { export const getChangedFiles = async (): Promise<string[]> => {
const { stdout: modified } = await execa('git', ['ls-files', '--modified']); const gitDir = await getGitDir();
const { stdout: others } = await execa('git', [
'ls-files', const { stdout: modified } = await execa('git', ['ls-files', '--modified'], {
'--others', cwd: gitDir
'--exclude-standard' });
]);
const { stdout: others } = await execa(
'git',
['ls-files', '--others', '--exclude-standard'],
{ cwd: gitDir }
);
const files = [...modified.split('\n'), ...others.split('\n')].filter( const files = [...modified.split('\n'), ...others.split('\n')].filter(
(file) => !!file (file) => !!file
@@ -74,16 +82,20 @@ export const getChangedFiles = async (): Promise<string[]> => {
}; };
export const gitAdd = async ({ files }: { files: string[] }) => { export const gitAdd = async ({ files }: { files: string[] }) => {
const gitDir = await getGitDir();
const gitAddSpinner = spinner(); const gitAddSpinner = spinner();
gitAddSpinner.start('Adding files to commit'); gitAddSpinner.start('Adding files to commit');
await execa('git', ['add', ...files]); await execa('git', ['add', ...files], { cwd: gitDir });
gitAddSpinner.stop(`Staged ${files.length} files`); gitAddSpinner.stop(`Staged ${files.length} files`);
}; };
export const getDiff = async ({ files }: { files: string[] }) => { export const getDiff = async ({ files }: { files: string[] }) => {
const gitDir = await getGitDir();
const lockFiles = files.filter( const lockFiles = files.filter(
(file) => (file) =>
file.includes('.lock') || file.includes('.lock') ||
@@ -108,12 +120,20 @@ export const getDiff = async ({ files }: { files: string[] }) => {
(file) => !file.includes('.lock') && !file.includes('-lock.') (file) => !file.includes('.lock') && !file.includes('-lock.')
); );
const { stdout: diff } = await execa('git', [ const { stdout: diff } = await execa(
'diff', 'git',
'--staged', ['diff', '--staged', '--', ...filesWithoutLocks],
'--', { cwd: gitDir }
...filesWithoutLocks );
]);
return diff; return diff;
}; };
export const getGitDir = async (): Promise<string> => {
const { stdout: gitDir } = await execa('git', [
'rev-parse',
'--show-toplevel'
]);
return gitDir;
};