@@ -23,7 +23,6 @@ var (
flagPreset string
flagShowCmd bool
flagConfigFile string
- presetResolved bool
)
const overrideArgumentsKey = "_arguments"
@@ -54,14 +53,7 @@ var rootCmd = &cobra.Command{
return nil
}
- // Preset was resolved by the session; pass it directly
- // so runCommand skips its own preset prompt.
- flagPreset = preset
- // Mark that the session already handled preset selection
- // so runCommand does not re-prompt even when preset is "".
- presetResolved = true
-
- return runCommand(commandName, cmd, nil, overrides)
+ return runCommand(commandName, cmd, nil, overrides, &preset)
},
}
@@ -72,7 +64,14 @@ func registerRootFlags() {
flags.StringVarP(&flagConfigFile, "config", "C", "", "path to keld config file")
}
-func runCommand(commandName string, cmd *cobra.Command, rawArgs []string, sessionOverrides map[string][]string) error {
+// runCommand resolves config and executes restic.
+//
+// sessionPreset signals that a TUI session already handled preset
+// selection. When non-nil, its value is used as the preset and the
+// standalone preset prompt is skipped. When nil, the subcommand was
+// invoked non-interactively (with arguments) and no prompting
+// occurs.
+func runCommand(commandName string, cmd *cobra.Command, rawArgs []string, sessionOverrides map[string][]string, sessionPreset *string) error {
if flagConfigFile != "" {
if err := os.Setenv("KELD_CONFIG_FILE", flagConfigFile); err != nil {
return fmt.Errorf("setting KELD_CONFIG_FILE: %w", err)
@@ -86,10 +85,15 @@ func runCommand(commandName string, cmd *cobra.Command, rawArgs []string, sessio
preset := flagPreset
// Interactive mode when launched from root command or when a
- // TUI session ran (presetResolved). The session handles preset
- // selection, but runCommand may still need to collect values
- // for commands without dedicated TUI screens (e.g. backup paths).
- interactive := cmd == cmd.Root() || presetResolved
+ // TUI session ran (sessionPreset != nil). The session handles
+ // preset selection, but runCommand may still need to collect
+ // values for commands without dedicated TUI screens (e.g.
+ // backup paths).
+ interactive := cmd == cmd.Root() || sessionPreset != nil
+
+ if sessionPreset != nil {
+ preset = *sessionPreset
+ }
if preset != "" {
if err := validatePreset(preset); err != nil {
@@ -99,18 +103,10 @@ func runCommand(commandName string, cmd *cobra.Command, rawArgs []string, sessio
overrides := mergeOverrides(parsePassthrough(rawArgs), sessionOverrides)
- // In interactive mode, fill missing preset/command inputs via prompts.
- // When the unified session has already resolved the preset (presetResolved),
- // skip the standalone preset prompt.
+ // In interactive mode, fill missing command-specific inputs
+ // via prompts. The session already handles preset selection,
+ // so only command-level prompts are needed here.
if interactive {
- if !presetResolved && preset == "" {
- p, err := promptPreset()
- if err != nil {
- return err
- }
- preset = p
- }
-
// Resolve config before prompting so we can skip questions for values
// already provided by presets.
peek, err := config.Resolve(preset, commandName, overrides)
@@ -473,20 +469,6 @@ func validatePreset(preset string) error {
return fmt.Errorf("unknown preset %q; available presets: %s", preset, strings.Join(known, ", "))
}
-// promptPreset shows an interactive preset selector when presets are defined
-// in the config. Returns "" (global-only) if no presets exist.
-func promptPreset() (string, error) {
- presets := config.Presets()
- if len(presets) == 0 {
- return "", nil
- }
- selected, err := form.SelectPreset(presets)
- if err != nil {
- return "", fmt.Errorf("preset selection: %w", err)
- }
- return selected, nil
-}
-
// promptForCommand collects required inputs for commands that need them.
// The resolved config is checked first so prompts are skipped for values
// the preset already provides.
@@ -108,7 +108,7 @@ func TestRunCommandAppliesRootFlagsAndPassthrough(t *testing.T) {
backup := lookupSubcommand(t, "backup")
out, err := captureStdout(t, func() error {
- return runCommand("backup", backup, []string{"--tag", "daily", "/src"}, nil)
+ return runCommand("backup", backup, []string{"--tag", "daily", "/src"}, nil, nil)
})
if err != nil {
t.Fatalf("runCommand returned error: %v", err)
@@ -133,7 +133,7 @@ func TestRunCommandRejectsUnknownPreset(t *testing.T) {
setRootFlagValuesForTest(t, "missing", true, configFile)
backup := lookupSubcommand(t, "backup")
- err := runCommand("backup", backup, nil, nil)
+ err := runCommand("backup", backup, nil, nil, nil)
if err == nil {
t.Fatal("expected unknown preset error")
}
@@ -199,16 +199,13 @@ func setRootFlagValuesForTest(t *testing.T, preset string, showCommand bool, con
t.Helper()
prevPreset, prevShowCommand, prevConfigFile := flagPreset, flagShowCmd, flagConfigFile
- prevPresetResolved := presetResolved
flagPreset = preset
flagShowCmd = showCommand
flagConfigFile = configFile
- presetResolved = false
t.Cleanup(func() {
flagPreset = prevPreset
flagShowCmd = prevShowCommand
flagConfigFile = prevConfigFile
- presetResolved = prevPresetResolved
})
}
@@ -58,11 +58,10 @@ func registerSubcommands() {
return nil
}
flagPreset = preset
- presetResolved = true
- return runCommand(cmdName, cmd, nil, overrides)
+ return runCommand(cmdName, cmd, nil, overrides, &preset)
}
- return runCommand(commandName, cmd, args, nil)
+ return runCommand(commandName, cmd, args, nil, nil)
},
}