From f2ea4d276605e50b50488a8ffddf78be750bbc8d Mon Sep 17 00:00:00 2001 From: Aly Raffauf Date: Mon, 10 Aug 2026 07:37:43 -0400 Subject: [PATCH] refactor: keep decision seams within shape limits --- internal/application/apply/decisions.go | 30 +++++++++++++++++++------ internal/cli/prompt.go | 25 ++++++++++++++------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/internal/application/apply/decisions.go b/internal/application/apply/decisions.go index f335f9e..f0baef1 100644 --- a/internal/application/apply/decisions.go +++ b/internal/application/apply/decisions.go @@ -144,7 +144,7 @@ func (service *Service) resolveRepeatedly(ctx context.Context, request DecisionR if err := ctx.Err(); err != nil { return DecisionResponse{}, err } - response, err := service.resolveOnce(ctx, request, difference) + response, err := service.resolveOnce(decisionResolution{context: ctx, request: request, difference: difference}) if err != nil { return DecisionResponse{}, err } @@ -156,11 +156,20 @@ func (service *Service) resolveRepeatedly(ctx context.Context, request DecisionR // resolveOnce asks the resolver once and validates its response against the // allowed choices of the request. -func (service *Service) resolveOnce(ctx context.Context, request DecisionRequest, difference DifferenceProvider) (DecisionResponse, error) { +type decisionResolution struct { + context context.Context + request DecisionRequest + difference DifferenceProvider +} + +func (service *Service) resolveOnce(input decisionResolution) (DecisionResponse, error) { + ctx, request, difference := input.context, input.request, input.difference if service.resolver == nil { return DecisionResponse{}, failure.New(failure.Operational, "apply: decision resolver is unavailable", nil) } - response, err := resolveDecision(service.resolver, ctx, request, difference) + response, err := resolveDecision(decisionResolutionInput{ + resolver: service.resolver, context: ctx, request: request, difference: difference, + }) if err != nil { return DecisionResponse{}, err } @@ -172,9 +181,16 @@ func (service *Service) resolveOnce(ctx context.Context, request DecisionRequest return DecisionResponse{}, failure.New(failure.InvalidInput, "apply: invalid decision response for "+request.TargetPath(), nil) } -func resolveDecision(resolver DecisionResolver, ctx context.Context, request DecisionRequest, difference DifferenceProvider) (DecisionResponse, error) { - if differenceResolver, ok := resolver.(DifferenceResolver); ok { - return differenceResolver.ResolveWithDifference(ctx, request, difference) +type decisionResolutionInput struct { + resolver DecisionResolver + context context.Context + request DecisionRequest + difference DifferenceProvider +} + +func resolveDecision(input decisionResolutionInput) (DecisionResponse, error) { + if differenceResolver, ok := input.resolver.(DifferenceResolver); ok { + return differenceResolver.ResolveWithDifference(input.context, input.request, input.difference) } - return resolver.Resolve(ctx, request) + return input.resolver.Resolve(input.context, input.request) } diff --git a/internal/cli/prompt.go b/internal/cli/prompt.go index 0516885..8cd6a7b 100644 --- a/internal/cli/prompt.go +++ b/internal/cli/prompt.go @@ -72,7 +72,9 @@ func (p *DecisionPrompt) resolve(ctx context.Context, request apply.DecisionRequ if err != nil { return apply.DecisionResponse{}, failure.New(failure.InvalidInput, "cli: EOF before a valid answer", err) } - response, done, err := p.answer(ctx, request, answer, difference) + response, done, err := p.answer(promptAnswer{ + context: ctx, request: request, answer: answer, difference: difference, + }) if err != nil { return apply.DecisionResponse{}, err } @@ -110,24 +112,31 @@ func readAnswer(scanner *bufio.Scanner) (string, error) { // answer maps one raw answer to a response, displaying the safe difference // and re-prompting on diff or invalid input. -func (p *DecisionPrompt) answer(ctx context.Context, request apply.DecisionRequest, answer string, difference apply.DifferenceProvider) (apply.DecisionResponse, bool, error) { - if answer == "" { - return apply.DecisionResponse{Choice: request.Choices()[0]}, true, nil +type promptAnswer struct { + context context.Context + request apply.DecisionRequest + answer string + difference apply.DifferenceProvider +} + +func (p *DecisionPrompt) answer(input promptAnswer) (apply.DecisionResponse, bool, error) { + if input.answer == "" { + return apply.DecisionResponse{Choice: input.request.Choices()[0]}, true, nil } - choice := apply.DecisionChoice(answer) - for _, allowed := range request.Choices() { + choice := apply.DecisionChoice(input.answer) + for _, allowed := range input.request.Choices() { if choice != allowed { continue } if choice != apply.ChoiceDiff { return apply.DecisionResponse{Choice: choice}, true, nil } - if err := p.renderDifference(ctx, request.TargetPath(), difference); err != nil { + if err := p.renderDifference(input.context, input.request.TargetPath(), input.difference); err != nil { return apply.DecisionResponse{}, false, err } return apply.DecisionResponse{}, false, nil } - _, err := fmt.Fprintf(p.stderr, "invalid answer %q\n", answer) + _, err := fmt.Fprintf(p.stderr, "invalid answer %q\n", input.answer) return apply.DecisionResponse{}, false, err } -- 2.51.2