Skip to content

Commit 8207721

Browse files
committed
CIHelper: add a way to create the initial Git notes
GitGitGadget stores its information in Git notes that are pushed to the `pr-repo`. These notes need to be initialized before any 3rd-party project can be handled by GitGitGadget. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 081b17f commit 8207721

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

lib/ci-helper.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export class CIHelper {
103103
needsUpstreamBranches?: boolean;
104104
needsMailToCommitNotes?: boolean;
105105
createOrUpdateCheckRun?: boolean | "post";
106+
createGitNotes?: boolean;
106107
}): Promise<void> {
107108
// configure the Git committer information
108109
process.env.GIT_CONFIG_PARAMETERS = [
@@ -136,6 +137,9 @@ export class CIHelper {
136137
}
137138

138139
if (setupOptions?.createOrUpdateCheckRun) {
140+
if (setupOptions?.createGitNotes) {
141+
throw new Error(`Cannot use createOrUpdateCheckRun and createGitNotes at the same time`);
142+
}
139143
return await this.createOrUpdateCheckRun(setupOptions.createOrUpdateCheckRun === "post");
140144
}
141145

@@ -169,6 +173,47 @@ export class CIHelper {
169173
]) {
170174
await git(["config", key, value], { workDir: this.workDir });
171175
}
176+
if (setupOptions?.createGitNotes) {
177+
if (
178+
setupOptions.needsMailToCommitNotes ||
179+
setupOptions.needsUpstreamBranches ||
180+
setupOptions.needsMailingListMirror
181+
) {
182+
throw new Error("`createGitNotes` cannot be combined with any other options");
183+
}
184+
const initialUser = core.getInput("initial-user");
185+
console.time("verify that Git notes do not yet exist");
186+
const existingNotes = await git(
187+
[
188+
"ls-remote",
189+
"origin",
190+
GitNotes.defaultNotesRef,
191+
"refs/notes/mail-to-commit",
192+
"refs/notes/commit-to-mail",
193+
],
194+
{
195+
workDir: this.workDir,
196+
},
197+
);
198+
if (existingNotes !== "") {
199+
throw new Error(`Git notes already exist in ${this.workDir}:\n${existingNotes}`);
200+
}
201+
console.timeEnd("verify that Git notes do not yet exist");
202+
console.time("create the initial Git notes and push them");
203+
for (const key of ["mail-to-commit", "commit-to-mail"]) {
204+
const notes = new GitNotes(this.workDir, `refs/notes/${key}`);
205+
await notes.initializeWithEmptyCommit();
206+
await notes.push(this.urlRepo, this.notesPushToken);
207+
}
208+
const options: IGitGitGadgetOptions = {
209+
allowedUsers: [initialUser],
210+
};
211+
await this.notes.set("", options, true);
212+
await this.notes.push(this.urlRepo, this.notesPushToken);
213+
console.timeEnd("create the initial Git notes and push them");
214+
return;
215+
}
216+
172217
console.time("fetch Git notes");
173218
const notesRefs = [GitNotes.defaultNotesRef];
174219
if (setupOptions?.needsMailToCommitNotes) {

lib/git-notes.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ export class GitNotes {
120120
return notes.replace(/^[^]*\n\n/, "");
121121
}
122122

123+
public async initializeWithEmptyCommit(): Promise<void> {
124+
const emptyTree = await git(["hash-object", "-t", "tree", "--stdin"], { stdin: "", workDir: this.workDir });
125+
const emptyCommit = await git(["commit-tree", "-m", "Initial empty commit", emptyTree], {
126+
workDir: this.workDir,
127+
});
128+
await git(["update-ref", this.notesRef, emptyCommit, ""], { workDir: this.workDir });
129+
}
130+
123131
public async update(url: string): Promise<void> {
124132
if (this.notesRef.match(/^refs\/notes\/(gitgitgadget|commit-to-mail|mail-to-commit)$/)) {
125133
await git(["fetch", "--no-tags", url, `+${this.notesRef}:${this.notesRef}`], { workDir: this.workDir });

0 commit comments

Comments
 (0)