From c03a72f1d7b598c1fe8fd01bb1f5bbfbd0256313 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 14 Sep 2026 22:29:06 +0200 Subject: plan 10: an interrupt stops between steps; nohup keeps ignoring hangups --- internal/apply/apply.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'internal/apply/apply.go') diff --git a/internal/apply/apply.go b/internal/apply/apply.go index 684641e..a93aad4 100644 --- a/internal/apply/apply.go +++ b/internal/apply/apply.go @@ -7,6 +7,7 @@ package apply import ( + "context" "errors" "fmt" "os" @@ -44,7 +45,7 @@ type StepResult struct { // marking the rest skipped. It never touches a file whose size or mtime no // longer matches what the plan recorded. It is ChainLogged with no done. func Chain(c plan.Chain) []StepResult { - results, _ := ChainLogged(c, nil) + results, _ := ChainLogged(context.Background(), c, nil) return results } @@ -58,11 +59,18 @@ func Chain(c plan.Chain) []StepResult { // planned destination was taken since planning, stops the chain too: every // later step was planned against the name the file did not get, and must // not act on whatever is at that path (review M3). -func ChainLogged(c plan.Chain, done func(i int, sr StepResult) error) ([]StepResult, error) { +// +// Once ctx is cancelled (an interrupt), the step already under way finishes +// and every later step is skipped as "interrupted": an interrupt stops after +// the current step, not after the file's whole chain (spec ยง11). +func ChainLogged(ctx context.Context, c plan.Chain, done func(i int, sr StepResult) error) ([]StepResult, error) { results := make([]StepResult, len(c.Steps)) stopWhy := "" for i, step := range c.Steps { + if stopWhy == "" && ctx.Err() != nil { + stopWhy = "interrupted" + } switch { case stopWhy != "": results[i] = StepResult{Step: step, Status: "skipped", Detail: stopWhy} -- cgit v1.3