diff --git a/scripts/worktree.sh b/scripts/worktree.sh new file mode 100755 index 0000000..dc54da8 --- /dev/null +++ b/scripts/worktree.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash +# ============================================================================== +# Diablo 2 Web - Git Worktree Helper for Multi-Session Parallel Issue Fixing +# +# Usage: +# ./scripts/worktree.sh create [base_branch] +# ./scripts/worktree.sh list +# ./scripts/worktree.sh remove +# +# Examples: +# ./scripts/worktree.sh create 42 +# ./scripts/worktree.sh create 43 main +# ./scripts/worktree.sh list +# ./scripts/worktree.sh remove 42 +# ============================================================================== + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)" +PARENT_DIR="$(dirname "$REPO_ROOT")" + +PRIMARY_SOURCE="/usr/local/google/home/taodao/d2w-wg1-main" +if [[ ! -d "$PRIMARY_SOURCE" ]]; then + PRIMARY_SOURCE="$REPO_ROOT" +fi + +parse_target() { + local input="$1" + if [[ "$input" =~ ^[0-9]+$ ]]; then + BRANCH="fix/issue-${input}" + DIR_NAME="d2w-issue-${input}" + elif [[ "$input" =~ ^fix/issue-([0-9]+)$ ]]; then + BRANCH="$input" + DIR_NAME="d2w-issue-${BASH_REMATCH[1]}" + else + BRANCH="$input" + local sanitized + sanitized="$(echo "$input" | tr '/' '-')" + DIR_NAME="d2w-${sanitized}" + fi + TARGET_DIR="${PARENT_DIR}/${DIR_NAME}" +} + +cmd_create() { + local input="${1:-}" + local base_branch="${2:-main}" + + if [[ -z "$input" ]]; then + echo "Error: Issue ID or branch name is required." + echo "Example: $0 create 42" + exit 1 + fi + + parse_target "$input" + + echo "============================================================" + echo ">>> Creating Worktree for Issue/Task: $input" + echo " Target Directory: $TARGET_DIR" + echo " Branch Name: $BRANCH" + echo " Base Branch: $base_branch" + echo "============================================================" + + if [[ -d "$TARGET_DIR" ]]; then + echo "Error: Directory '$TARGET_DIR' already exists!" + exit 1 + fi + + # Check if branch exists + if git -C "$REPO_ROOT" show-ref --verify --quiet "refs/heads/$BRANCH"; then + echo "--> Branch '$BRANCH' already exists. Attaching to existing branch..." + git -C "$REPO_ROOT" worktree add "$TARGET_DIR" "$BRANCH" + else + echo "--> Creating new branch '$BRANCH' from '$base_branch'..." + git -C "$REPO_ROOT" worktree add "$TARGET_DIR" -b "$BRANCH" "$base_branch" + fi + + echo "--> Symlinking node_modules from $PRIMARY_SOURCE..." + if [[ -d "$PRIMARY_SOURCE/node_modules" ]]; then + ln -s "$PRIMARY_SOURCE/node_modules" "$TARGET_DIR/node_modules" + else + echo "Warning: $PRIMARY_SOURCE/node_modules not found. You may need to run 'npm install'." + fi + + echo "--> Symlinking samples/ assets..." + mkdir -p "$TARGET_DIR/samples" + if [[ -d "$PRIMARY_SOURCE/samples/d2-packs" ]]; then + ln -s "$PRIMARY_SOURCE/samples/d2-packs" "$TARGET_DIR/samples/d2-packs" + fi + if [[ -L "$PRIMARY_SOURCE/samples/d2" ]]; then + cp -P "$PRIMARY_SOURCE/samples/d2" "$TARGET_DIR/samples/d2" 2>/dev/null || true + fi + + echo "--> Running smoke verification test in new worktree..." + ( + cd "$TARGET_DIR" + npx vitest run tests/save-schema.test.ts --reporter=basic + ) + + echo "" + echo "============================================================" + echo " Worktree created successfully!" + echo "============================================================" + echo "To start working in this session:" + echo " cd $TARGET_DIR" + echo "" + echo "To run tests in this worktree:" + echo " npm test" + echo "" + echo "To run Vite dev server (use a separate port):" + echo " npm run dev -- --port 5174" + echo "" + echo "When finished with this issue, you can clean it up via:" + echo " $0 remove $input" + echo "============================================================" +} + +cmd_list() { + echo "Current active worktrees:" + git -C "$REPO_ROOT" worktree list +} + +cmd_remove() { + local input="${1:-}" + if [[ -z "$input" ]]; then + echo "Error: Issue ID or branch name is required." + echo "Example: $0 remove 42" + exit 1 + fi + + parse_target "$input" + + if [[ ! -d "$TARGET_DIR" ]]; then + echo "Warning: Directory '$TARGET_DIR' does not exist." + git -C "$REPO_ROOT" worktree list + return + fi + + echo "Removing worktree at '$TARGET_DIR'..." + # Remove symlinks first to be clean + rm -f "$TARGET_DIR/node_modules" "$TARGET_DIR/samples/d2-packs" "$TARGET_DIR/samples/d2" 2>/dev/null || true + git -C "$REPO_ROOT" worktree remove "$TARGET_DIR" + echo "Worktree removed. Note: Git branch '$BRANCH' is preserved." + echo "To delete the branch as well (if merged), run:" + echo " git branch -d $BRANCH" +} + +case "${1:-}" in + create) + shift + cmd_create "$@" + ;; + list) + cmd_list + ;; + remove) + shift + cmd_remove "$@" + ;; + *) + echo "Usage: $0 {create |list|remove }" + exit 1 + ;; +esac