Files
aicommits/src/utils/git.ts
2023-05-03 23:24:34 +09:00

64 lines
1.3 KiB
TypeScript

import { execa } from 'execa';
import { KnownError } from './error.js';
export const assertGitRepo = async () => {
const { stdout, failed } = await execa('git', ['rev-parse', '--show-toplevel'], { reject: false });
if (failed) {
throw new KnownError('The current directory must be a Git repository!');
}
return stdout;
};
const excludeFromDiff = (path: string) => `:(exclude)${path}`;
const filesToExclude = [
'package-lock.json',
'pnpm-lock.yaml',
// yarn.lock, Cargo.lock, Gemfile.lock, Pipfile.lock, etc.
'*.lock',
].map(excludeFromDiff);
export const getStagedDiff = async (excludeFiles?: string[]) => {
const diffCached = ['diff', '--cached', '--diff-algorithm=minimal'];
const { stdout: files } = await execa(
'git',
[
...diffCached,
'--name-only',
...filesToExclude,
...(
excludeFiles
? excludeFiles.map(excludeFromDiff)
: []
),
],
);
if (!files) {
return;
}
const { stdout: diff } = await execa(
'git',
[
...diffCached,
...filesToExclude,
...(
excludeFiles
? excludeFiles.map(excludeFromDiff)
: []
),
],
);
return {
files: files.split('\n'),
diff,
};
};
export const getDetectedMessage = (files: string[]) => `Detected ${files.length.toLocaleString()} staged file${files.length > 1 ? 's' : ''}`;