Skip to content

Commit 6151bd6

Browse files
MrFlounderclaude
andcommitted
feat: add crab destroy command + fix submodule copy logic
- `crab destroy <N>` completely removes workspace (worktree + files) - `crab ws <N> destroy` also works - Asks for confirmation, use --force to skip - Cleans up: tmux window, processes, worktree, branch, snapshots Also fixes bash syntax bug in submodule copy condition that was causing it to fall back to slow git submodule update. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7c8c3b3 commit 6151bd6

1 file changed

Lines changed: 92 additions & 1 deletion

File tree

src/crabcode

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,8 @@ init_submodules() {
632632

633633
# FAST PATH: Copy submodule from main repo if it exists there
634634
# This is MUCH faster than git submodule update which re-checksout all files
635-
if [ -d "$MAIN_REPO/$sub_path" ] && [ -d "$MAIN_REPO/$sub_path/.git" -o -f "$MAIN_REPO/$sub_path/.git" ]; then
635+
local main_sub="$MAIN_REPO/$sub_path"
636+
if [ -d "$main_sub" ] && { [ -d "$main_sub/.git" ] || [ -f "$main_sub/.git" ]; }; then
636637
echo " Copying submodule: $sub_path (fast copy from main repo)"
637638

638639
# Remove empty directory if exists
@@ -1241,6 +1242,77 @@ cleanup_workspace() {
12411242
success "Workspace $num cleaned and reset to origin/main"
12421243
}
12431244

1245+
# Completely destroy a workspace (remove worktree and all files)
1246+
destroy_workspace() {
1247+
local num=$1
1248+
local dir="$WORKSPACE_BASE/$WORKSPACE_PREFIX-$num"
1249+
local window_name="ws$num"
1250+
local branch_name=$(get_branch_name "$num")
1251+
1252+
if [ ! -d "$dir" ]; then
1253+
error "Workspace $num does not exist at $dir"
1254+
exit 1
1255+
fi
1256+
1257+
echo -e "${RED}Destroying workspace $num...${NC}"
1258+
echo -e "${YELLOW}This will permanently delete all files in the workspace!${NC}"
1259+
echo ""
1260+
1261+
# Confirm unless --force is passed
1262+
if [ "${2:-}" != "--force" ] && [ "${2:-}" != "-f" ]; then
1263+
echo -n "Are you sure? (y/N) "
1264+
read -r confirm
1265+
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
1266+
echo "Aborted."
1267+
return 1
1268+
fi
1269+
fi
1270+
1271+
# Kill the tmux window if it exists
1272+
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
1273+
echo " Killing tmux window..."
1274+
tmux kill-window -t "$SESSION_NAME:$window_name" 2>/dev/null || true
1275+
fi
1276+
1277+
# Kill any running processes for this workspace
1278+
local kill_pattern=$(config_get "cleanup.kill_pattern" "")
1279+
if [ -n "$kill_pattern" ]; then
1280+
kill_pattern="${kill_pattern//\{N\}/$num}"
1281+
kill_pattern="${kill_pattern//\{PREFIX\}/$WORKSPACE_PREFIX}"
1282+
echo " Killing processes..."
1283+
pkill -f "$kill_pattern" 2>/dev/null || true
1284+
fi
1285+
1286+
# Remove the git worktree properly
1287+
echo " Removing git worktree..."
1288+
cd "$MAIN_REPO"
1289+
git worktree remove "$dir" --force 2>/dev/null || true
1290+
1291+
# If worktree remove failed, force delete
1292+
if [ -d "$dir" ]; then
1293+
echo " Force removing directory..."
1294+
rm -rf "$dir"
1295+
fi
1296+
1297+
# Clean up the branch if it exists and is not checked out elsewhere
1298+
if git show-ref --verify --quiet "refs/heads/$branch_name"; then
1299+
# Check if branch is used by another worktree
1300+
local branch_in_use=$(git worktree list | grep "\[$branch_name\]" | wc -l | tr -d ' ')
1301+
if [ "$branch_in_use" = "0" ]; then
1302+
echo " Deleting branch $branch_name..."
1303+
git branch -D "$branch_name" 2>/dev/null || true
1304+
fi
1305+
fi
1306+
1307+
# Clean up snapshots for this workspace
1308+
if [ -d "$SNAPSHOT_DIR/ws-$num" ]; then
1309+
echo " Removing snapshots..."
1310+
rm -rf "$SNAPSHOT_DIR/ws-$num"
1311+
fi
1312+
1313+
success "Workspace $num destroyed"
1314+
}
1315+
12441316
restart_workspace() {
12451317
local num=$1
12461318
local dir="$WORKSPACE_BASE/$WORKSPACE_PREFIX-$num"
@@ -5447,6 +5519,8 @@ show_cheat() {
54475519
║ crab ws <N> --separate Open in new terminal window ║
54485520
║ crab ws <N> restart Reset git + restart panes ║
54495521
║ crab ws <N> cleanup Kill window + reset to origin/main ║
5522+
║ crab ws <N> destroy Completely remove workspace (worktree + files) ║
5523+
║ crab destroy <N> Shorthand for above ║
54505524
║ crab ws <N> continue Resume with --continue flag ║
54515525
║ ║
54525526
║ SHORTCUTS (auto-detect workspace from cwd or tmux window) ║
@@ -5638,6 +5712,9 @@ handle_ws_command() {
56385712
"cleanup"|"clean")
56395713
cleanup_workspace "$num"
56405714
;;
5715+
"destroy"|"rm"|"remove")
5716+
destroy_workspace "$num" "${2:-}"
5717+
;;
56415718
"restart"|"reset"|"refresh")
56425719
restart_workspace "$num"
56435720
;;
@@ -5786,6 +5863,20 @@ main() {
57865863
fi
57875864
cleanup_workspace "$num"
57885865
;;
5866+
"destroy"|"rm"|"remove")
5867+
load_config
5868+
validate_config
5869+
if [ -n "${2:-}" ] && [[ "${2:-}" =~ ^[0-9]+$ ]]; then
5870+
destroy_workspace "$2" "${3:-}"
5871+
else
5872+
num=$(detect_workspace)
5873+
if [ -z "$num" ]; then
5874+
error "Specify workspace: crab destroy <N>"
5875+
exit 1
5876+
fi
5877+
destroy_workspace "$num" "${2:-}"
5878+
fi
5879+
;;
57895880
"wip")
57905881
load_config
57915882
validate_config

0 commit comments

Comments
 (0)