package cli import ( "context" "fmt" "io" "gitea.maximumdirect.net/eric/distributor/internal/app" ) func pruneCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int { if hasHelp(args) { printPruneHelp(stdout) return exitOK } flags := newFlagSet("prune", stderr) configPath := flags.String("config", "", "path to config file") pipelineID := flags.String("pipeline", "", "pipeline id") destinationID := flags.String("destination", "", "destination id") dryRun := flags.Bool("dry-run", false, "report planned deletes without deleting outputs or rewriting state") apply := flags.Bool("apply", false, "delete planned managed outputs and rewrite state") formatFlag := addFormatFlag(flags) if err := flags.Parse(args); err != nil { return exitUsage } if rejectPositionalArgs(stderr, "prune", flags.Args()) { return exitUsage } format, ok := parseOutputFormat(stderr, "prune", *formatFlag) if !ok { return exitUsage } if !validatePruneFlags(stderr, *configPath, *pipelineID, *destinationID, *dryRun, *apply) { return exitUsage } if _, err := app.Prune(ctx, app.PruneOptions{ ConfigPath: *configPath, PipelineID: *pipelineID, DestinationID: *destinationID, DryRun: *dryRun, Stdout: stdout, OutputFormat: format, }); err != nil { return fail(stderr, err) } return exitOK } func validatePruneFlags(stderr io.Writer, configPath, pipelineID, destinationID string, dryRun, apply bool) bool { if configPath == "" { fmt.Fprintf(stderr, "%s: prune requires --config\n", app.Name) return false } if pipelineID == "" { fmt.Fprintf(stderr, "%s: prune requires --pipeline\n", app.Name) return false } if destinationID == "" { fmt.Fprintf(stderr, "%s: prune requires --destination\n", app.Name) return false } if dryRun == apply { fmt.Fprintf(stderr, "%s: prune requires exactly one of --dry-run or --apply\n", app.Name) return false } return true } func printPruneHelp(w io.Writer) { fmt.Fprint(w, `Usage: distributor prune --config --pipeline --destination (--dry-run|--apply) [--format text|json] Options: --config Path to config file --pipeline Pipeline id that selects the destination root --destination Destination id that selects the destination root --dry-run Report planned deletes without deleting outputs or rewriting state --apply Delete planned managed outputs and rewrite state --format text|json Output format Prune reads the selected destination's configured retention policy and managed state, then plans owner-scoped managed output deletion. --dry-run is read-only. --apply deletes only planned managed output paths, preserves unmanaged files, and rewrites state after confirmed deletes. `) }