Keep worktrees git could not read, never delete them
Any git error on a directory under the worktree root was classified orphan, and orphan deletes the directory outright, so a transient failure reading the source root became data loss on a plain `agentws prune --yes`. - prove a backing repo gone by stat before calling a directory an orphan - classify an unexplained git failure as keep, naming the error - refuse to remove a worktree whose git state is unknown, even with --include-keep - spell out that --include-keep discards uncommitted and in-progress work
This commit is contained in:
+15
-6
@@ -88,7 +88,7 @@ func newPruneCmd() *cobra.Command {
|
||||
f.BoolVar(&opts.keepBranches, "keep-branches", false, "Never delete a local branch, whatever the classification")
|
||||
f.BoolVar(&opts.noFetch, "no-fetch", false, "Do not fetch; judge against the refs already on disk")
|
||||
f.BoolVar(&opts.jsonOut, "json", false, "Emit JSON instead of a table")
|
||||
f.BoolVar(&opts.includeKeep, "include-keep", false, "Dangerous: also remove worktrees classified keep (needs --yes; never deletes their branch)")
|
||||
f.BoolVar(&opts.includeKeep, "include-keep", false, "Dangerous: also remove worktrees classified keep (needs --yes). Destroys uncommitted changes and paused rebase/merge state, which no branch is carrying; only the branch itself survives")
|
||||
f.BoolVar(&opts.includeUnmanaged, "include-unmanaged", false, "Also remove worktrees that live outside the worktree root")
|
||||
return cmd
|
||||
}
|
||||
@@ -142,11 +142,15 @@ func classifyAll(notes io.Writer, prs prLister, worktrees []managedWt, opts prun
|
||||
byRepo := map[string][]managedWt{}
|
||||
var results []pruneResult
|
||||
for _, w := range worktrees {
|
||||
if w.orphan {
|
||||
switch {
|
||||
case w.inspectErr != nil:
|
||||
// Unknown is not gone: a checkout git refused to answer for keeps.
|
||||
results = append(results, pruneResult{wt: w, verdict: verdictKeep, reason: "inspection failed: " + oneLine(w.inspectErr.Error())})
|
||||
case w.orphan:
|
||||
results = append(results, pruneResult{wt: w, verdict: verdictRemove, reason: "backing repo gone, no git state to read"})
|
||||
continue
|
||||
default:
|
||||
byRepo[w.srcDir] = append(byRepo[w.srcDir], w)
|
||||
}
|
||||
byRepo[w.srcDir] = append(byRepo[w.srcDir], w)
|
||||
}
|
||||
|
||||
srcDirs := make([]string, 0, len(byRepo))
|
||||
@@ -159,14 +163,14 @@ func classifyAll(notes io.Writer, prs prLister, worktrees []managedWt, opts prun
|
||||
ctx, err := newRepoCtx(notes, prs, srcDir, opts.noFetch)
|
||||
if err != nil {
|
||||
for _, w := range byRepo[srcDir] {
|
||||
results = append(results, pruneResult{wt: w, verdict: verdictKeep, reason: "repo state unknown: " + err.Error()})
|
||||
results = append(results, pruneResult{wt: w, verdict: verdictKeep, reason: "repo state unknown: " + oneLine(err.Error())})
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, w := range byRepo[srcDir] {
|
||||
res, err := classify(w, ctx)
|
||||
if err != nil {
|
||||
res = pruneResult{wt: w, verdict: verdictKeep, reason: "inspection failed: " + err.Error()}
|
||||
res = pruneResult{wt: w, verdict: verdictKeep, reason: "inspection failed: " + oneLine(err.Error())}
|
||||
}
|
||||
results = append(results, res)
|
||||
}
|
||||
@@ -210,6 +214,11 @@ func report(out io.Writer, results []pruneResult, opts pruneOpts) error {
|
||||
return tw.Flush()
|
||||
}
|
||||
|
||||
// oneLine flattens a git error onto a single line so one row stays one row.
|
||||
func oneLine(s string) string {
|
||||
return strings.Join(strings.Fields(s), " ")
|
||||
}
|
||||
|
||||
func dash(s string) string {
|
||||
if s == "" {
|
||||
return "-"
|
||||
|
||||
Reference in New Issue
Block a user