fix(FN-4475): complete Step 1 — centralize empty cherry-pick guard

Fusion-Task-Id: FN-4475
Fusion-Task-Lineage: cb285fff-18e6-4bad-8f22-9158c99337f5
This commit is contained in:
Fusion
2026-05-14 08:04:08 -07:00
committed by gsxdsm
parent f8dcc7bb63
commit 9da675d0ab

View File

@@ -4284,7 +4284,35 @@ async function ensureTaskTrailersOnHead(rootDir: string, task: Pick<Task, "id">
}
}
type CherryPickCommitResult = { landed: boolean };
type CherryPickCommitResult = { landed: true } | { landed: false; reason: "empty" };
type CherryPickAttemptResult =
| { kind: "landed" }
| { kind: "empty"; recovery: "skip" | "abort-reset" };
async function runCherryPickWithEmptySkip(rootDir: string, args: string): Promise<CherryPickAttemptResult> {
try {
await execAsync(`git cherry-pick ${args}`, { cwd: rootDir });
return { kind: "landed" };
} catch (error) {
if (!isEmptyCherryPickError(error)) {
throw error;
}
try {
await execAsync("git cherry-pick --skip", { cwd: rootDir });
return { kind: "empty", recovery: "skip" };
} catch {
try {
await execAsync("git cherry-pick --abort", { cwd: rootDir });
} catch {
// best effort
}
await execAsync("git reset --hard HEAD", { cwd: rootDir });
return { kind: "empty", recovery: "abort-reset" };
}
}
}
export function isEmptyCherryPickError(error: unknown): boolean {
if (!error || typeof error !== "object") return false;
@@ -4331,23 +4359,13 @@ async function cherryPickCommitPreservingTaskTrailers(
result: MergeResult,
): Promise<CherryPickCommitResult> {
try {
await execAsync(`git cherry-pick ${quoteArg(commitSha)}`, { cwd: rootDir });
const initialPick = await runCherryPickWithEmptySkip(rootDir, quoteArg(commitSha));
if (initialPick.kind === "empty") {
return { landed: false, reason: "empty" };
}
} catch (error) {
const conflictedFiles = await getConflictedFiles(rootDir);
if (conflictedFiles.length === 0) {
if (isEmptyCherryPickError(error)) {
try {
await execAsync("git cherry-pick --skip", { cwd: rootDir });
} catch {
try {
await execAsync("git cherry-pick --abort", { cwd: rootDir });
} catch {
// best effort
}
await execAsync("git reset --hard HEAD", { cwd: rootDir });
}
return { landed: false };
}
throw error;
}
@@ -4383,9 +4401,15 @@ async function cherryPickCommitPreservingTaskTrailers(
}
if (mergeConflictStrategy === "smart-prefer-main") {
await execAsync(`git cherry-pick -X ours ${quoteArg(commitSha)}`, { cwd: rootDir });
const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X ours ${quoteArg(commitSha)}`);
if (fallbackPick.kind === "empty") {
return { landed: false, reason: "empty" };
}
} else if (mergeConflictStrategy === "smart-prefer-branch") {
await execAsync(`git cherry-pick -X theirs ${quoteArg(commitSha)}`, { cwd: rootDir });
const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X theirs ${quoteArg(commitSha)}`);
if (fallbackPick.kind === "empty") {
return { landed: false, reason: "empty" };
}
} else {
throw error;
}