Add opt-in configuration overrides

This commit is contained in:
2026-11-07 04:39:34 +00:00
parent 85ae55bf42
commit aeb70e5873
22 changed files with 238 additions and 35 deletions

View File

@@ -19,8 +19,9 @@ type configCommandInput[I, S any] struct {
}
type selectedScopeInput[I, S any] struct {
scope *preparedScope[I, S]
input I
scope *preparedScope[I, S]
input I
selection Selection
}
type preparedComparison[I, S any] struct {
@@ -31,7 +32,6 @@ type preparedComparison[I, S any] struct {
type configOperationPlan[I, S any] struct {
prepared *preparedSuite[I, S]
operation Operation
selection Selection
scopeName string
path configkit.Path
scopes []selectedScopeInput[I, S]
@@ -76,6 +76,18 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
}),
)
}
if supportsOverrides(prepared, operation) {
flags = append(flags, commandkit.RepeatFlag(commandkit.FlagMeta{Name: "set", Usage: "Override POINTER=JSON (pointer keys cannot contain =)."}, []configkit.Override(nil), overrideParser("--set"),
func(input **configCommandInput[I, S], value commandkit.Supplied[[]configkit.Override]) {
(*input).selection.Overrides = value.Value
}))
if operation == Diff {
flags = append(flags, commandkit.RepeatFlag(commandkit.FlagMeta{Name: "against-set", Usage: "Right-side override POINTER=JSON (pointer keys cannot contain =)."}, []configkit.Override(nil), overrideParser("--against-set"),
func(input **configCommandInput[I, S], value commandkit.Supplied[[]configkit.Override]) {
(*input).against.Overrides = value.Value
}))
}
}
if operation == Explain {
flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "path", Usage: "JSON Pointer path to explain.", Required: true}, (*string)(nil), parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).path = value }))
@@ -155,6 +167,9 @@ func prepareConfigOperation[I, S any](prepared *preparedSuite[I, S], operation O
if !containsOperation(scope.scope.Operations, operation) {
return fmt.Errorf("configuration scope %q does not support %s (available: %s)", scope.scope.Name, operation, joinOperations(scope.scope.Operations))
}
if (len(input.selection.Overrides) > 0 || len(input.against.Overrides) > 0) && !scope.scope.Features.Overrides {
return fmt.Errorf("configuration scope %q does not support overrides", scope.scope.Name)
}
}
var path configkit.Path
@@ -172,13 +187,14 @@ func prepareConfigOperation[I, S any](prepared *preparedSuite[I, S], operation O
plan := &configOperationPlan[I, S]{
prepared: prepared,
operation: operation,
selection: input.selection,
scopeName: scopeName,
path: path,
scopes: make([]selectedScopeInput[I, S], 0, len(selected)),
}
if operation == Diff {
scope := selected[0]
input.selection = cloneSelection(input.selection)
input.against = cloneSelection(input.against)
left, err := prepareScopeInput(prepared, input.values, scope, scope.bindings, input.selection, true)
if err != nil {
return fmt.Errorf("configuration scope %q left input: %w", scope.scope.Name, err)
@@ -198,11 +214,12 @@ func prepareConfigOperation[I, S any](prepared *preparedSuite[I, S], operation O
return nil
}
for _, scope := range selected {
value, err := prepareScopeInput(prepared, input.values, scope, scope.bindings, input.selection, false)
selection := cloneSelection(input.selection)
value, err := prepareScopeInput(prepared, input.values, scope, scope.bindings, selection, false)
if err != nil {
return fmt.Errorf("configuration scope %q: %w", scope.scope.Name, err)
}
plan.scopes = append(plan.scopes, selectedScopeInput[I, S]{scope: scope, input: value})
plan.scopes = append(plan.scopes, selectedScopeInput[I, S]{scope: scope, input: value, selection: selection})
}
input.plan = plan
return nil