package app import ( "context" "errors" "flag" "fmt" "io" "gitea.maximumdirect.net/eric/narratio/internal/adapters/storage" "gitea.maximumdirect.net/eric/narratio/internal/config" ) // Restore validates restore CLI/config inputs and storage preflight for future restore phases. func Restore(ctx context.Context, args []string, out io.Writer) error { fs := flag.NewFlagSet("restore", flag.ContinueOnError) fs.SetOutput(out) var pipelinePath string var sessionPath string var sessionID string var dryRun bool var force bool var includeAudio bool fs.StringVar(&pipelinePath, "config", "", "path to pipeline.yml (optional; defaults searched)") fs.StringVar(&sessionPath, "session", "", "path to session.yml") fs.StringVar(&sessionID, "session-id", "", "session identifier for session.yml templates") fs.BoolVar(&dryRun, "dry-run", false, "plan restore actions without writing local files") fs.BoolVar(&force, "force", false, "overwrite local conflicts with remote state") fs.BoolVar(&includeAudio, "include-audio", false, "include archived session-level audio objects") fs.Usage = func() { _, _ = fmt.Fprintln(out, "Usage: narratio restore [--config ] [--session ] [--session-id ] [--dry-run] [--force] [--include-audio]") _, _ = fmt.Fprintln(out) _, _ = fmt.Fprintln(out, "Flags:") fs.PrintDefaults() } if err := fs.Parse(args); err != nil { if errors.Is(err, flag.ErrHelp) { return nil } return fmt.Errorf("restore: invalid flags: %w", err) } if fs.NArg() != 0 { return fmt.Errorf("restore: unexpected positional arguments") } resolvedPipelinePath, err := resolvePipelineConfigPath(pipelinePath) if err != nil { return fmt.Errorf("restore: %w", err) } resolvedSessionPath, err := resolveSessionConfigPath(sessionPath) if err != nil { return fmt.Errorf("restore: %w", err) } cfg, err := config.LoadWithSessionOptions(resolvedPipelinePath, resolvedSessionPath, config.SessionLoadOptions{ SessionID: sessionID, }) if err != nil { return fmt.Errorf("restore: %w", err) } if err := config.Validate(cfg); err != nil { return fmt.Errorf("restore: %w", err) } _, err = storage.NewObjectStoreFromConfig(ctx, cfg) if err != nil { return fmt.Errorf("restore: %w", err) } // Phase 2 boundary: command wiring and preflight only. _ = dryRun _ = force _ = includeAudio return fmt.Errorf("restore: not yet implemented (phase 3: remote current-state discovery)") }