Files
gh-cskiro-claudex-devops-tools/skills/git-worktree-setup/templates/batch-setup-template.sh
2025-11-29 18:16:54 +08:00

499 lines
12 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Git Worktree Batch Setup Script
# Generated by git-worktree-setup skill
#
# This script automates the creation of multiple git worktrees with parallel dependency installation.
#
# Usage:
# ./batch-setup.sh branch1 branch2 branch3 [--no-install] [--pattern=/path/{branch}]
set -euo pipefail
# ============================================================================
# Configuration
# ============================================================================
BRANCHES=()
SKIP_INSTALL=false
PATH_PATTERN=""
# Parse arguments
for arg in "$@"; do
case $arg in
--no-install)
SKIP_INSTALL=true
;;
--pattern=*)
PATH_PATTERN="${arg#*=}"
;;
*)
BRANCHES+=("$arg")
;;
esac
done
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================================================
# Helper Functions
# ============================================================================
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1" >&2
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_info() {
echo -e "${BLUE}${NC} $1"
}
print_header() {
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$1"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
}
# ============================================================================
# Prerequisite Checks
# ============================================================================
check_prerequisites() {
print_header "Checking Prerequisites"
# Check if in git repository
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
print_error "Not in a git repository"
exit 1
fi
print_success "Git repository detected"
# Get repository info
REPO_NAME=$(basename "$(git rev-parse --show-toplevel)")
REPO_ROOT=$(git rev-parse --show-toplevel)
CURRENT_BRANCH=$(git branch --show-current)
print_info "Repository: $REPO_NAME"
print_info "Current branch: $CURRENT_BRANCH"
# Check for branch names
if [ ${#BRANCHES[@]} -eq 0 ]; then
print_error "No branch names provided"
echo "Usage: $0 branch1 branch2 branch3 [--no-install] [--pattern=/path/{branch}]"
exit 1
fi
print_info "Branches to create: ${#BRANCHES[@]}"
for branch in "${BRANCHES[@]}"; do
echo " - $branch"
done
}
validate_branches() {
print_header "Validating Branches"
declare -gA BRANCH_TYPES
declare -gA WORKTREE_PATHS
for branch in "${BRANCHES[@]}"; do
# Check if branch exists
if git show-ref --verify "refs/heads/$branch" &>/dev/null; then
BRANCH_TYPES[$branch]="existing"
print_info "$branch: existing branch"
elif git show-ref --verify "refs/remotes/origin/$branch" &>/dev/null; then
BRANCH_TYPES[$branch]="remote"
print_info "$branch: exists on remote"
else
BRANCH_TYPES[$branch]="new"
print_info "$branch: will create new branch"
fi
# Determine worktree path
if [ -n "$PATH_PATTERN" ]; then
# Use custom pattern
WORKTREE_PATHS[$branch]="${PATH_PATTERN//\{branch\}/$branch}"
else
# Use default pattern
WORKTREE_PATHS[$branch]="$(dirname "$REPO_ROOT")/$REPO_NAME-$branch"
fi
echo "${WORKTREE_PATHS[$branch]}"
done
}
check_directory_conflicts() {
print_header "Checking for Directory Conflicts"
CONFLICTS=()
for branch in "${BRANCHES[@]}"; do
path="${WORKTREE_PATHS[$branch]}"
if [ -d "$path" ]; then
CONFLICTS+=("$branch$path")
fi
done
if [ ${#CONFLICTS[@]} -gt 0 ]; then
print_warning "Found ${#CONFLICTS[@]} directory conflicts:"
for conflict in "${CONFLICTS[@]}"; do
echo " $conflict"
done
echo ""
echo "Options:"
echo " 1. Skip conflicting worktrees"
echo " 2. Remove and recreate"
echo " 3. Abort"
read -p "Choose (1/2/3): " -r choice
case $choice in
1)
print_info "Will skip conflicting directories"
for conflict in "${CONFLICTS[@]}"; do
branch="${conflict%% →*}"
# Remove from BRANCHES array
BRANCHES=("${BRANCHES[@]/$branch}")
done
# Remove empty elements
BRANCHES=("${BRANCHES[@]}")
;;
2)
print_warning "Removing conflicting directories..."
for conflict in "${CONFLICTS[@]}"; do
path="${conflict##*→ }"
rm -rf "$path"
print_success "Removed: $path"
done
;;
3)
print_info "Aborted by user"
exit 0
;;
esac
else
print_success "No directory conflicts"
fi
}
# ============================================================================
# Worktree Creation
# ============================================================================
create_worktrees() {
print_header "Creating Worktrees"
declare -gA CREATED_WORKTREES
declare -ga FAILED_WORKTREES
local total=${#BRANCHES[@]}
local current=0
for branch in "${BRANCHES[@]}"; do
((current++))
echo ""
print_info "[$current/$total] Creating worktree for $branch..."
path="${WORKTREE_PATHS[$branch]}"
branch_type="${BRANCH_TYPES[$branch]}"
case $branch_type in
new)
if git worktree add "$path" -b "$branch" 2>&1; then
CREATED_WORKTREES[$branch]="$path"
print_success "$branch: Created with new branch"
else
FAILED_WORKTREES+=("$branch")
print_error "$branch: Failed to create"
fi
;;
existing)
if git worktree add "$path" "$branch" 2>&1; then
CREATED_WORKTREES[$branch]="$path"
print_success "$branch: Created from existing branch"
else
FAILED_WORKTREES+=("$branch")
print_error "$branch: Failed to create"
fi
;;
remote)
if git worktree add "$path" -b "$branch" --track "origin/$branch" 2>&1; then
CREATED_WORKTREES[$branch]="$path"
print_success "$branch: Created tracking remote"
else
FAILED_WORKTREES+=("$branch")
print_error "$branch: Failed to create"
fi
;;
esac
done
echo ""
print_header "Worktree Creation Summary"
print_success "Created: ${#CREATED_WORKTREES[@]}/$total worktrees"
if [ ${#FAILED_WORKTREES[@]} -gt 0 ]; then
print_error "Failed: ${#FAILED_WORKTREES[@]} worktrees"
for failed in "${FAILED_WORKTREES[@]}"; do
echo " - $failed"
done
fi
}
# ============================================================================
# Development Environment Setup
# ============================================================================
detect_package_manager() {
cd "$REPO_ROOT"
if [ -f "pnpm-lock.yaml" ]; then
PKG_MANAGER="pnpm"
INSTALL_CMD="pnpm install"
elif [ -f "yarn.lock" ]; then
PKG_MANAGER="yarn"
INSTALL_CMD="yarn install"
elif [ -f "bun.lockb" ]; then
PKG_MANAGER="bun"
INSTALL_CMD="bun install"
elif [ -f "package-lock.json" ]; then
PKG_MANAGER="npm"
INSTALL_CMD="npm install"
elif [ -f "package.json" ]; then
PKG_MANAGER="npm"
INSTALL_CMD="npm install"
else
PKG_MANAGER="none"
INSTALL_CMD=""
fi
if [ "$PKG_MANAGER" != "none" ]; then
print_info "Using $PKG_MANAGER for all worktrees"
fi
}
install_dependencies() {
if [ "$SKIP_INSTALL" = true ]; then
print_info "Skipping dependency installation (--no-install flag)"
return 0
fi
if [ "$PKG_MANAGER" = "none" ]; then
print_info "No package.json found, skipping dependency installation"
return 0
fi
if [ ${#CREATED_WORKTREES[@]} -eq 0 ]; then
print_warning "No worktrees created, skipping dependency installation"
return 0
fi
print_header "Installing Dependencies (Parallel)"
declare -gA INSTALL_SUCCESS
declare -gA INSTALL_FAILED
declare -A INSTALL_PIDS
# Start installations in parallel
for branch in "${!CREATED_WORKTREES[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
print_info "Starting installation in $branch..."
# Run in background
(
cd "$path"
$INSTALL_CMD > "/tmp/install-$branch.log" 2>&1
) &
INSTALL_PIDS[$branch]=$!
done
# Wait for all installations
for branch in "${!INSTALL_PIDS[@]}"; do
pid=${INSTALL_PIDS[$branch]}
print_info "Waiting for $branch (PID: $pid)..."
if wait "$pid"; then
INSTALL_SUCCESS[$branch]=true
print_success "$branch: Dependencies installed"
else
INSTALL_FAILED[$branch]=true
print_error "$branch: Installation failed (see /tmp/install-$branch.log)"
fi
done
echo ""
print_header "Installation Summary"
print_success "Successful: ${#INSTALL_SUCCESS[@]}/${#CREATED_WORKTREES[@]}"
if [ ${#INSTALL_FAILED[@]} -gt 0 ]; then
print_warning "Failed: ${#INSTALL_FAILED[@]}"
for branch in "${!INSTALL_FAILED[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
echo " - $branch (manually run: cd $path && $INSTALL_CMD)"
done
fi
}
# ============================================================================
# Summary and Next Steps
# ============================================================================
print_final_summary() {
print_header "Batch Worktree Creation Complete"
echo "Created: ${#CREATED_WORKTREES[@]}/${#BRANCHES[@]} worktrees"
if [ ${#FAILED_WORKTREES[@]} -gt 0 ]; then
echo "Failed: ${#FAILED_WORKTREES[@]}/${#BRANCHES[@]} worktrees"
fi
echo ""
if [ ${#CREATED_WORKTREES[@]} -gt 0 ]; then
echo "Successful worktrees:"
for branch in "${!CREATED_WORKTREES[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
branch_type="${BRANCH_TYPES[$branch]}"
print_success "$branch$path ($branch_type)"
done
fi
echo ""
if [ ${#FAILED_WORKTREES[@]} -gt 0 ]; then
echo "Failed worktrees:"
for branch in "${FAILED_WORKTREES[@]}"; do
print_error "$branch"
done
echo ""
fi
print_header "Next Steps"
echo "Start working on each worktree:"
echo ""
for branch in "${!CREATED_WORKTREES[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
echo "${BLUE}# $branch${NC}"
echo "cd $path"
echo "claude"
echo ""
done
print_header "All Worktrees"
git worktree list
echo ""
print_header "Batch Management"
echo "List all: git worktree list"
echo "Remove all:"
for branch in "${!CREATED_WORKTREES[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
echo " git worktree remove $path"
done
echo ""
# Offer to generate cleanup script
read -p "Generate cleanup script? (yes/no): " -r
if [[ $REPLY =~ ^[Yy]es$ ]]; then
generate_cleanup_script
fi
}
generate_cleanup_script() {
CLEANUP_SCRIPT="cleanup-worktrees.sh"
cat > "$CLEANUP_SCRIPT" << 'EOF'
#!/bin/bash
# Cleanup script for batch-created worktrees
# Generated by git-worktree-setup skill
set -euo pipefail
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
echo "Cleaning up worktrees..."
EOF
for branch in "${!CREATED_WORKTREES[@]}"; do
path="${CREATED_WORKTREES[$branch]}"
cat >> "$CLEANUP_SCRIPT" << EOF
echo "Removing $branch..."
if git worktree remove "$path" 2>/dev/null; then
echo -e "\${GREEN}✓\${NC} Removed: $branch"
read -p "Delete branch '$branch'? (yes/no): " -r
if [[ \$REPLY =~ ^[Yy]es$ ]]; then
git branch -d "$branch" 2>/dev/null && echo -e "\${GREEN}✓\${NC} Deleted branch: $branch" || echo -e "\${RED}✗\${NC} Failed to delete branch: $branch"
fi
else
echo -e "\${RED}✗\${NC} Failed to remove: $branch"
fi
EOF
done
cat >> "$CLEANUP_SCRIPT" << 'EOF'
echo ""
echo "Cleanup complete!"
echo ""
echo "Remaining worktrees:"
git worktree list
EOF
chmod +x "$CLEANUP_SCRIPT"
print_success "Generated cleanup script: $CLEANUP_SCRIPT"
print_info "Run with: ./$CLEANUP_SCRIPT"
}
# ============================================================================
# Main Execution
# ============================================================================
main() {
print_header "Git Worktree Batch Setup"
# Phase 0: Prerequisites
check_prerequisites
validate_branches
check_directory_conflicts
# Confirm before proceeding
echo ""
read -p "Create ${#BRANCHES[@]} worktrees? (yes/no): " -r
if [[ ! $REPLY =~ ^[Yy]es$ ]]; then
print_info "Aborted by user"
exit 0
fi
# Phase 1: Create worktrees
create_worktrees
# Phase 2: Setup development environments
detect_package_manager
install_dependencies
# Phase 3: Summary
print_final_summary
print_success "Batch setup complete!"
}
# Run main function
main "$@"