@@ -107,7 +107,14 @@ var rootCmd = &cobra.Command{
}
preset = p
- cmdOverrides, err := promptForCommand(command)
+ // Resolve config before prompting so we can see what the
+ // preset already provides and skip unnecessary prompts.
+ peek, err := config.Resolve(preset, command, overrides)
+ if err != nil {
+ return err
+ }
+
+ cmdOverrides, err := promptForCommand(command, peek)
if err != nil {
return err
}
@@ -350,34 +357,51 @@ func promptPreset() (string, error) {
}
// 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.
// Returns CLI overrides to merge, or nil if the command needs no extra input.
-func promptForCommand(command string) (map[string][]string, error) {
+func promptForCommand(command string, cfg *config.ResolvedConfig) (map[string][]string, error) {
switch command {
case "restore":
- return promptRestore()
+ return promptRestore(cfg)
case "backup":
- return promptBackup()
+ return promptBackup(cfg)
default:
return nil, nil
}
}
-// promptRestore collects the snapshot ID and target directory for restore.
-func promptRestore() (map[string][]string, error) {
- snapshotID, target, err := form.RestoreInputs()
+// promptRestore collects the snapshot ID and target directory for restore,
+// skipping prompts for values already present in the resolved config.
+func promptRestore(cfg *config.ResolvedConfig) (map[string][]string, error) {
+ hasSnapshotID := len(cfg.Arguments) > 0
+ hasTarget := cfg.HasFlag("target")
+
+ if hasSnapshotID && hasTarget {
+ return nil, nil
+ }
+
+ snapshotID, target, err := form.RestoreInputs(hasSnapshotID, hasTarget)
if err != nil {
return nil, fmt.Errorf("restore inputs: %w", err)
}
- return map[string][]string{
- overrideArgumentsKey: {snapshotID},
- "target": {target},
- }, nil
+
+ overrides := make(map[string][]string)
+ if !hasSnapshotID {
+ overrides[overrideArgumentsKey] = []string{snapshotID}
+ }
+ if !hasTarget {
+ overrides["target"] = []string{target}
+ }
+ return overrides, nil
}
-// promptBackup collects backup paths if none are likely to come from config.
-// The user is always offered the chance to provide paths; config-defined
-// _arguments will still take precedence during resolution.
-func promptBackup() (map[string][]string, error) {
+// promptBackup collects backup paths when none are configured in the preset.
+func promptBackup(cfg *config.ResolvedConfig) (map[string][]string, error) {
+ if len(cfg.Arguments) > 0 {
+ return nil, nil
+ }
+
paths, err := form.BackupPaths()
if err != nil {
return nil, fmt.Errorf("backup paths: %w", err)
@@ -51,6 +51,18 @@ type Flag struct {
Value string // empty for boolean switches
}
+// HasFlag reports whether the resolved config contains a flag with the given
+// name (without leading dashes, e.g. "target" not "--target").
+func (rc *ResolvedConfig) HasFlag(name string) bool {
+ dashed := flagName(name)
+ for _, f := range rc.Flags {
+ if f.Name == dashed {
+ return true
+ }
+ }
+ return false
+}
+
// rawConfig is the entire parsed TOML file as nested string-keyed maps.
type rawConfig map[string]any
@@ -50,23 +50,29 @@ func SelectPreset(presets []string) (string, error) {
}
// RestoreInputs collects the required inputs for `restic restore`:
-// a snapshot ID and a target directory.
-func RestoreInputs() (snapshotID, target string, err error) {
- form := huh.NewForm(
- huh.NewGroup(
- huh.NewInput().
- Title("Snapshot ID").
- Placeholder("e.g. latest or a1b2c3d4").
- Value(&snapshotID).
- Validate(notEmpty("snapshot ID")),
- huh.NewInput().
- Title("Target directory").
- Placeholder("e.g. /tmp/restore").
- Value(&target).
- Validate(notEmpty("target directory")),
- ),
- )
+// a snapshot ID and a target directory. Fields whose corresponding
+// "has" parameter is true are skipped (already provided by config).
+func RestoreInputs(hasSnapshotID, hasTarget bool) (snapshotID, target string, err error) {
+ var fields []huh.Field
+ if !hasSnapshotID {
+ fields = append(fields, huh.NewInput().
+ Title("Snapshot ID").
+ Placeholder("e.g. latest or a1b2c3d4").
+ Value(&snapshotID).
+ Validate(notEmpty("snapshot ID")))
+ }
+ if !hasTarget {
+ fields = append(fields, huh.NewInput().
+ Title("Target directory").
+ Placeholder("e.g. /tmp/restore").
+ Value(&target).
+ Validate(notEmpty("target directory")))
+ }
+ if len(fields) == 0 {
+ return "", "", nil
+ }
+ form := huh.NewForm(huh.NewGroup(fields...))
if err := wrapAbort(form.Run()); err != nil {
return "", "", err
}