Implement catalog force replacement

This commit is contained in:
2026-06-19 16:39:01 +00:00
parent 4e673dda76
commit 9a2eaf8e5e
13 changed files with 307 additions and 35 deletions

View File

@@ -131,6 +131,65 @@ func TestExecuteSupersededAdditiveLeavesUnplannedFilesUnmanaged(t *testing.T) {
}
}
func TestExecuteForceReplaceClearsDestinationBundlePathOnly(t *testing.T) {
_, destinationBackend, req := catalogPlanRequest(t, config.WorkflowAdditive)
req.DestinationBundlePath = "bundle"
req.Force = true
testutil.WriteFakeFile(t, destinationBackend, "bundle/report.md", "old report")
testutil.WriteFakeFile(t, destinationBackend, "bundle/unplanned.txt", "remove")
testutil.WriteFakeFile(t, destinationBackend, "bundle-child/keep.txt", "keep")
testutil.WriteFakeFile(t, destinationBackend, "outside.txt", "keep")
plan, err := Build(context.Background(), req)
if err != nil {
t.Fatalf("Build() error = %v", err)
}
if plan.Action != ActionForceReplace {
t.Fatalf("plan action = %s, want %s", plan.Action, ActionForceReplace)
}
if err := Execute(context.Background(), req, plan); err != nil {
t.Fatalf("Execute() error = %v", err)
}
testutil.AssertFakeFile(t, destinationBackend, "bundle/report.md", "# Report\nSunny.\n")
testutil.AssertFakeFile(t, destinationBackend, "bundle/summary.txt", "Summary\n")
testutil.AssertFakeMissing(t, destinationBackend, "bundle/unplanned.txt")
testutil.AssertFakeFile(t, destinationBackend, "bundle-child/keep.txt", "keep")
testutil.AssertFakeFile(t, destinationBackend, "outside.txt", "keep")
catalog := readCatalogState(t, destinationBackend, "bundle")
if catalog.SchemaVersion != state.CatalogSchemaVersion || catalog.State.Mode != state.StateModeCatalog {
t.Fatalf("catalog identity = schema %d mode %s", catalog.SchemaVersion, catalog.State.Mode)
}
if len(catalog.Outputs) != 2 {
t.Fatalf("catalog outputs = %#v, want planned outputs only", catalog.Outputs)
}
}
func TestExecuteForceReplaceClearsFixedDestinationRoot(t *testing.T) {
_, destinationBackend, req := catalogPlanRequest(t, config.WorkflowAdditive)
req.DestinationBundlePath = ""
req.PathMapping = config.PathMappingFixed
req.Force = true
testutil.WriteFakeFile(t, destinationBackend, "report.md", "old report")
testutil.WriteFakeFile(t, destinationBackend, "unplanned.txt", "remove")
plan, err := Build(context.Background(), req)
if err != nil {
t.Fatalf("Build() error = %v", err)
}
if plan.Action != ActionForceReplace || storage.DisplayPath(plan.DestinationBundlePath) != "." {
t.Fatalf("plan action=%s destination=%s, want force_replace at root", plan.Action, storage.DisplayPath(plan.DestinationBundlePath))
}
if err := Execute(context.Background(), req, plan); err != nil {
t.Fatalf("Execute() error = %v", err)
}
testutil.AssertFakeFile(t, destinationBackend, "report.md", "# Report\nSunny.\n")
testutil.AssertFakeFile(t, destinationBackend, "summary.txt", "Summary\n")
testutil.AssertFakeMissing(t, destinationBackend, "unplanned.txt")
readCatalogState(t, destinationBackend, "")
}
func TestExecuteFailedWriteDoesNotWriteCatalogState(t *testing.T) {
_, destinationBackend, req := catalogPlanRequest(t, config.WorkflowAdditive)
plan, err := Build(context.Background(), req)