Files
opencommit/src/utils/git.ts
Moret84 a3fade4d42 refactor(git.ts): use git rev-parse to get the root directory of the repository (#46)
The function getStagedFiles has been refactored to use git rev-parse to
get the root directory of the repository. This improves the reliability
of the function as it will work regardless of the current working
directory. The root directory is then passed to the git diff command to
get the list of staged files. With only the --relative flag, staged
diff(s) on files in a different same level directory as the current
working one would not be found by the command.
2023-03-24 10:11:50 +08:00

102 lines
2.3 KiB
TypeScript

import { execa } from 'execa';
import { outro, spinner } from '@clack/prompts';
import { readFileSync } from 'fs';
import ignore, { Ignore } from 'ignore';
export const assertGitRepo = async () => {
try {
await execa('git', ['rev-parse']);
} catch (error) {
throw new Error(error as string);
}
};
// const excludeBigFilesFromDiff = ['*-lock.*', '*.lock'].map(
// (file) => `:(exclude)${file}`
// );
export const getOpenCommitIgnore = (): Ignore => {
const ig = ignore();
try {
ig.add(readFileSync('.opencommitignore').toString().split('\n'));
} catch (e) {}
return ig;
};
export const getStagedFiles = async (): Promise<string[]> => {
const { stdout: gitDir } = await execa("git", [
"rev-parse",
"--show-toplevel"
]);
const { stdout: files } = await execa("git", [
"diff",
"--name-only",
"--cached",
"--relative",
gitDir
]);
if (!files) return [];
const filesList = files.split('\n');
const ig = getOpenCommitIgnore();
const allowedFiles = filesList.filter((file) => !ig.ignores(file));
if (!allowedFiles) return [];
return allowedFiles.sort();
};
export const getChangedFiles = async (): Promise<string[]> => {
const { stdout: modified } = await execa('git', ['ls-files', '--modified']);
const { stdout: others } = await execa('git', [
'ls-files',
'--others',
'--exclude-standard'
]);
const files = [...modified.split('\n'), ...others.split('\n')].filter(
(file) => !!file
);
return files.sort();
};
export const gitAdd = async ({ files }: { files: string[] }) => {
const gitAddSpinner = spinner();
gitAddSpinner.start('Adding files to commit');
await execa('git', ['add', ...files]);
gitAddSpinner.stop('Done');
};
export const getDiff = async ({ files }: { files: string[] }) => {
const lockFiles = files.filter(
(file) => file.includes('.lock') || file.includes('-lock.')
);
if (lockFiles.length) {
outro(
`Some files are '.lock' files which are excluded by default from 'git diff'. No commit messages are generated for this files:\n${lockFiles.join(
'\n'
)}`
);
}
const filesWithoutLocks = files.filter(
(file) => !file.includes('.lock') && !file.includes('-lock.')
);
const { stdout: diff } = await execa('git', [
'diff',
'--staged',
'--',
...filesWithoutLocks
]);
return diff;
};