feat: add safe Gitea sync and signed updates
This commit is contained in:
@@ -121,6 +121,71 @@ Force repair after you have closed all Git tools for this repository?`)
|
||||
}
|
||||
setLoading(false);
|
||||
render();
|
||||
} else if (action === "preview-workspace-sync") {
|
||||
if (!repository?.localPath) return;
|
||||
setLoading(true, "Fetching Gitea and building a safe synchronization plan…");
|
||||
try {
|
||||
ui.workspaceSyncPlan = await window.forgeflow.previewWorkspaceSync(
|
||||
repository.localPath,
|
||||
);
|
||||
ui.modal = { type: "workspace-sync" };
|
||||
showToast(
|
||||
ui.workspaceSyncPlan.needsSync
|
||||
? "Workspace sync preview ready"
|
||||
: "Workspace already synchronized",
|
||||
ui.workspaceSyncPlan.needsSync
|
||||
? `${ui.workspaceSyncPlan.summary.resultingTrackedChanges} tracked change(s) and ${ui.workspaceSyncPlan.summary.localFilesToStash} local file(s) reviewed.`
|
||||
: `Local ${ui.workspaceSyncPlan.branch} already matches ${ui.workspaceSyncPlan.upstream}.`,
|
||||
ui.workspaceSyncPlan.blockers?.length ? "error" : "success",
|
||||
);
|
||||
} catch (error) {
|
||||
showToast("Could not preview Gitea sync", error.message, "error");
|
||||
}
|
||||
setLoading(false);
|
||||
render();
|
||||
} else if (action === "confirm-workspace-sync") {
|
||||
if (!repository?.localPath || !ui.workspaceSyncPlan) return;
|
||||
const expectedPlanId = target.dataset.planId;
|
||||
setLoading(true, "Protecting local work and synchronizing exact Gitea state…");
|
||||
try {
|
||||
const result = await window.forgeflow.applyWorkspaceSync(
|
||||
repository.localPath,
|
||||
expectedPlanId,
|
||||
);
|
||||
ui.modal = null;
|
||||
ui.workspaceSyncPlan = null;
|
||||
await refreshRepositories(false);
|
||||
[ui.branches, ui.stashes] = await Promise.all([
|
||||
window.forgeflow.branches(repository.localPath),
|
||||
window.forgeflow.stashList(repository.localPath),
|
||||
]);
|
||||
const recovery = [
|
||||
result.backupBranch ? `recovery branch ${result.backupBranch}` : null,
|
||||
result.stash ? `stash ${result.stash.ref}` : null,
|
||||
].filter(Boolean).join(" and ");
|
||||
showToast(
|
||||
"Workspace synchronized with Gitea",
|
||||
recovery
|
||||
? `Local work is preserved in ${recovery}. Ignored runtime files were retained.`
|
||||
: `Tracked files now match ${result.plan.upstream}; ignored runtime files were retained.`,
|
||||
"success",
|
||||
);
|
||||
} catch (error) {
|
||||
if (error.code === "WORKSPACE_SYNC_PLAN_STALE") {
|
||||
try {
|
||||
ui.workspaceSyncPlan = await window.forgeflow.previewWorkspaceSync(
|
||||
repository.localPath,
|
||||
);
|
||||
ui.modal = { type: "workspace-sync" };
|
||||
} catch {
|
||||
ui.modal = null;
|
||||
ui.workspaceSyncPlan = null;
|
||||
}
|
||||
}
|
||||
showToast("Workspace synchronization stopped", error.message, "error");
|
||||
}
|
||||
setLoading(false);
|
||||
render();
|
||||
} else if (action === "repair-repository-sync") {
|
||||
if (!repository?.localPath) return;
|
||||
const strategy = target.dataset.strategy;
|
||||
|
||||
Reference in New Issue
Block a user