-
Notifications
You must be signed in to change notification settings - Fork 425
Expand file tree
/
Copy pathgit.ts
More file actions
153 lines (119 loc) · 3.61 KB
/
git.ts
File metadata and controls
153 lines (119 loc) · 3.61 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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { execa } from 'execa';
import { readFileSync, existsSync } from 'fs';
import ignore, { Ignore } from 'ignore';
import { join } from 'path';
import { homedir } from 'os';
import { outro, spinner } from '@clack/prompts';
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 = async (): Promise<Ignore> => {
const gitDir = await getGitDir();
const ig = ignore();
const globalIgnorePath = join(homedir(), '.opencommitignore');
if (existsSync(globalIgnorePath)) {
try {
const globalIgnoreContent = readFileSync(globalIgnorePath, 'utf8');
ig.add(globalIgnoreContent.split('\n'));
} catch (e) {
// do nothing
}
}
const localIgnorePath = join(gitDir, '.opencommitignore');
if (existsSync(localIgnorePath)) {
try {
const localIgnoreContent = readFileSync(localIgnorePath, 'utf8');
ig.add(localIgnoreContent.split('\n'));
} catch (e) {
// do nothing
}
}
return ig;
};
export const getCoreHooksPath = async (): Promise<string> => {
const gitDir = await getGitDir();
const { stdout } = await execa('git', ['config', 'core.hooksPath'], {
cwd: gitDir
});
return stdout;
};
export const getStagedFiles = async (): Promise<string[]> => {
const gitDir = await getGitDir();
const { stdout: files } = await execa(
'git',
['diff', '--name-only', '--cached', '--relative'],
{ cwd: gitDir }
);
if (!files) return [];
const filesList = files.split('\n');
const ig = await getOpenCommitIgnore();
const allowedFiles = filesList.filter((file) => !ig.ignores(file));
if (!allowedFiles) return [];
return allowedFiles.sort();
};
export const getChangedFiles = async (): Promise<string[]> => {
const gitDir = await getGitDir();
const { stdout: modified } = await execa('git', ['ls-files', '--modified'], {
cwd: gitDir
});
const { stdout: others } = await execa(
'git',
['ls-files', '--others', '--exclude-standard'],
{ cwd: gitDir }
);
const files = [...modified.split('\n'), ...others.split('\n')].filter(
(file) => !!file
);
return files.sort();
};
export const gitAdd = async ({ files }: { files: string[] }) => {
const gitDir = await getGitDir();
const gitAddSpinner = spinner();
gitAddSpinner.start('Adding files to commit');
await execa('git', ['add', ...files], { cwd: gitDir });
gitAddSpinner.stop(`Staged ${files.length} files`);
};
export const getDiff = async ({ files }: { files: string[] }) => {
const gitDir = await getGitDir();
const lockFiles = files.filter(
(file) =>
file.includes('.lock') ||
file.includes('-lock.') ||
file.includes('.svg') ||
file.includes('.png') ||
file.includes('.jpg') ||
file.includes('.jpeg') ||
file.includes('.webp') ||
file.includes('.gif')
);
if (lockFiles.length) {
outro(
`Some files 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],
{ cwd: gitDir }
);
return diff;
};
export const getGitDir = async (): Promise<string> => {
const { stdout: gitDir } = await execa('git', [
'rev-parse',
'--show-toplevel'
]);
return gitDir;
};