-
Notifications
You must be signed in to change notification settings - Fork 463
Expand file tree
/
Copy pathgit.ts
More file actions
114 lines (92 loc) · 2.31 KB
/
git.ts
File metadata and controls
114 lines (92 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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;
};
export const getGitHooksPath = async () => {
const { stdout, failed } = await execa(
'git',
['rev-parse', '--git-path', 'hooks'],
{ reject: false }
);
if (failed) {
throw new KnownError('Failed to determine Git hooks directory');
}
return stdout;
};
export const getGitDir = async () => {
const { stdout, failed } = await execa(
'git',
['rev-parse', '--show-toplevel'],
{ reject: false }
);
if (!failed) {
return stdout;
}
const { stdout: gitDir, failed: gitDirFailed } = await execa(
'git',
['rev-parse', '--git-dir'],
{ reject: false }
);
if (gitDirFailed) {
throw new KnownError('The current directory must be a Git repository!');
}
return gitDir;
};
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 getStagedDiffForFiles = async (files: string[], excludeFiles?: string[]) => {
const diffCached = ['diff', '--cached', '--diff-algorithm=minimal'];
const excludes = [
...filesToExclude,
...(excludeFiles ? excludeFiles.map(excludeFromDiff) : []),
];
const { stdout: diff } = await execa('git', [
...diffCached,
...excludes,
'--',
...files,
]);
return {
files,
diff,
};
};
export const getDetectedMessage = (files: string[]) =>
`Detected ${files.length.toLocaleString()} staged file${
files.length > 1 ? 's' : ''
}`;