Fix worktree cleanup looping on orphaned directories
When git worktree remove fails with "not a working tree", fall back to removing the directory directly and run git worktree prune to clean stale metadata. Fixes bug 364. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -253,8 +253,24 @@ fn remove_worktree_sync(project_root: &Path, wt_path: &Path, branch: &str) -> Re
|
|||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
if stderr.contains("not a working tree") {
|
||||||
|
// Orphaned directory: git doesn't recognise it as a worktree.
|
||||||
|
// Remove the directory directly and prune stale git metadata.
|
||||||
|
slog!(
|
||||||
|
"[worktree] orphaned worktree detected, removing directory: {}",
|
||||||
|
wt_path.display()
|
||||||
|
);
|
||||||
|
if let Err(e) = std::fs::remove_dir_all(wt_path) {
|
||||||
|
slog!("[worktree] failed to remove orphaned directory: {e}");
|
||||||
|
}
|
||||||
|
let _ = Command::new("git")
|
||||||
|
.args(["worktree", "prune"])
|
||||||
|
.current_dir(project_root)
|
||||||
|
.output();
|
||||||
|
} else {
|
||||||
slog!("[worktree] remove warning: {stderr}");
|
slog!("[worktree] remove warning: {stderr}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete branch (best effort)
|
// Delete branch (best effort)
|
||||||
let _ = Command::new("git")
|
let _ = Command::new("git")
|
||||||
@@ -630,6 +646,28 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn remove_worktree_sync_removes_orphaned_directory() {
|
||||||
|
let tmp = TempDir::new().unwrap();
|
||||||
|
let project_root = tmp.path().join("my-project");
|
||||||
|
fs::create_dir_all(&project_root).unwrap();
|
||||||
|
init_git_repo(&project_root);
|
||||||
|
|
||||||
|
// Create a directory that looks like a worktree but isn't registered with git
|
||||||
|
let wt_path = project_root
|
||||||
|
.join(".storkit")
|
||||||
|
.join("worktrees")
|
||||||
|
.join("orphan");
|
||||||
|
fs::create_dir_all(&wt_path).unwrap();
|
||||||
|
fs::write(wt_path.join("some_file.txt"), "stale").unwrap();
|
||||||
|
assert!(wt_path.exists());
|
||||||
|
|
||||||
|
// git worktree remove will fail with "not a working tree",
|
||||||
|
// but the fallback should rm -rf the directory
|
||||||
|
remove_worktree_sync(&project_root, &wt_path, "feature/orphan").unwrap();
|
||||||
|
assert!(!wt_path.exists());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_worktree_sync_cleans_up_directory() {
|
fn remove_worktree_sync_cleans_up_directory() {
|
||||||
let tmp = TempDir::new().unwrap();
|
let tmp = TempDir::new().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user