-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathgit.ts
More file actions
118 lines (106 loc) · 3.22 KB
/
git.ts
File metadata and controls
118 lines (106 loc) · 3.22 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
import { mkdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import type {
FetchResult,
Response,
SimpleGit,
SimpleGitFactory,
} from 'simple-git';
import { vi } from 'vitest';
export type GitConfig = { name: string; email: string };
export async function initGitRepo(
simpleGit: SimpleGitFactory,
opt: {
baseDir: string;
config?: GitConfig;
baseBranch?: string;
},
): Promise<SimpleGit> {
const { baseDir, baseBranch } = opt;
await mkdir(baseDir, { recursive: true });
const git = simpleGit(baseDir);
await git.init();
await git.branch(['-M', baseBranch ?? 'main']);
await configureGitUser(git, opt.config);
return git;
}
/** Like {@link initGitRepo}, but with a simulated remote origin. Working directory is `<baseDir>/repo`. */
export async function initGitRepoWithRemote(
simpleGit: SimpleGitFactory,
opt: {
baseDir: string;
config?: GitConfig;
baseBranch?: string;
},
): Promise<SimpleGit> {
const { baseDir, baseBranch = 'main' } = opt;
const originDir = path.join(baseDir, 'origin.git');
const repoDir = path.join(baseDir, 'repo');
await mkdir(originDir, { recursive: true });
await simpleGit(originDir).init(true, ['--initial-branch', baseBranch]);
await simpleGit(baseDir).clone(originDir, repoDir);
const git = simpleGit(repoDir);
await configureGitUser(git, opt.config);
await commitFile(git, { baseDir: repoDir });
await git.push('origin', baseBranch);
await git.remote(['set-head', 'origin', baseBranch]);
return git;
}
async function configureGitUser(
git: SimpleGit,
config?: GitConfig,
): Promise<void> {
const { email = 'john.doe@example.com', name = 'John Doe' } = config ?? {};
await git.addConfig('user.name', name);
await git.addConfig('user.email', email);
await git.addConfig('commit.gpgSign', 'false');
await git.addConfig('tag.gpgSign', 'false');
}
export async function commitFile(
git: SimpleGit,
opt?: {
file?: { name?: string; content?: string };
baseDir?: string;
commitMsg?: string;
tagName?: string;
},
): Promise<SimpleGit> {
const {
file,
baseDir = '',
commitMsg = 'Create README',
tagName,
} = opt ?? {};
const { name = 'README.md', content = `# hello-world-${Math.random()}\n` } =
file ?? {};
await writeFile(path.join(baseDir, name), content);
await git.add(name);
if (tagName) {
await git.tag([tagName]);
}
if (commitMsg) {
await git.commit(commitMsg);
}
return git;
}
export async function simulateGitFetch(git: SimpleGit) {
let fetchHead: string = await git.branchLocal().then(resp => resp.current);
vi.spyOn(git, 'fetch').mockImplementation((...args) => {
fetchHead = (args as unknown as [string, string, string[]])[1];
return Promise.resolve({}) as Response<FetchResult>;
});
const originalDiffSummary = git.diffSummary.bind(git);
const originalDiff = git.diff.bind(git);
vi.spyOn(git, 'diffSummary').mockImplementation(args =>
originalDiffSummary(
(args as unknown as string[]).map(arg =>
arg === 'FETCH_HEAD' ? fetchHead : arg,
),
),
);
vi.spyOn(git, 'diff').mockImplementation(args =>
originalDiff(
(args as string[]).map(arg => (arg === 'FETCH_HEAD' ? fetchHead : arg)),
),
);
}