Files
humanlayer/hack/create_worktree.sh
2025-06-19 12:31:19 -07:00

110 lines
3.4 KiB
Bash
Executable File

#!/bin/bash
# create_worktree.sh - Create a new worktree for development work
# Usage: ./create_worktree.sh [worktree_name]
# If no name provided, generates a unique human-readable one
set -e # Exit on any error
# Function to generate a unique worktree name
generate_unique_name() {
local adjectives=("swift" "bright" "clever" "smooth" "quick" "clean" "sharp" "neat" "cool" "fast")
local nouns=("fix" "task" "work" "dev" "patch" "branch" "code" "build" "test" "run")
local adj=${adjectives[$RANDOM % ${#adjectives[@]}]}
local noun=${nouns[$RANDOM % ${#nouns[@]}]}
local timestamp=$(date +%H%M)
echo "${adj}_${noun}_${timestamp}"
}
# Get worktree name from parameter or generate one
WORKTREE_NAME=${1:-$(generate_unique_name)}
# Get base directory name (should be 'humanlayer')
REPO_BASE_NAME=$(basename "$(pwd)")
# Construct paths
WORKTREE_DIR_NAME="${REPO_BASE_NAME}_${WORKTREE_NAME}"
WORKTREES_BASE="$HOME/.humanlayer/worktrees"
WORKTREE_PATH="${WORKTREES_BASE}/${WORKTREE_DIR_NAME}"
echo "🌳 Creating worktree: ${WORKTREE_NAME}"
echo "📁 Location: ${WORKTREE_PATH}"
# Check if worktrees base directory exists
if [ ! -d "$WORKTREES_BASE" ]; then
echo "❌ Error: Directory $WORKTREES_BASE does not exist."
echo " Please create it first: mkdir -p $WORKTREES_BASE"
exit 1
fi
# Check if worktree already exists
if [ -d "$WORKTREE_PATH" ]; then
echo "❌ Error: Worktree directory already exists: $WORKTREE_PATH"
exit 1
fi
# Get current branch
CURRENT_BRANCH=$(git branch --show-current)
echo "🔀 Creating from branch: ${CURRENT_BRANCH}"
# Create worktree (creates branch if it doesn't exist)
if git show-ref --verify --quiet "refs/heads/${WORKTREE_NAME}"; then
echo "📋 Using existing branch: ${WORKTREE_NAME}"
git worktree add "$WORKTREE_PATH" "$WORKTREE_NAME"
else
echo "🆕 Creating new branch: ${WORKTREE_NAME}"
git worktree add -b "$WORKTREE_NAME" "$WORKTREE_PATH" "$CURRENT_BRANCH"
fi
# Copy .claude directory if it exists
if [ -d ".claude" ]; then
echo "📋 Copying .claude directory..."
cp -r .claude "$WORKTREE_PATH/"
fi
# Change to worktree directory
cd "$WORKTREE_PATH"
echo "🔧 Setting up worktree dependencies..."
if ! make setup; then
echo "❌ Setup failed. Cleaning up worktree..."
cd - > /dev/null
git worktree remove --force "$WORKTREE_PATH"
git branch -D "$WORKTREE_NAME" 2>/dev/null || true
echo "❌ Not allowed to create worktree from a branch that isn't passing setup."
exit 1
fi
echo "🧪 Verifying worktree with checks and tests..."
temp_output=$(mktemp)
if make check test > "$temp_output" 2>&1; then
rm "$temp_output"
echo "✅ All checks and tests pass!"
else
cat "$temp_output"
rm "$temp_output"
echo "❌ Checks and tests failed. Cleaning up worktree..."
cd - > /dev/null
git worktree remove --force "$WORKTREE_PATH"
git branch -D "$WORKTREE_NAME" 2>/dev/null || true
echo "❌ Not allowed to create worktree from a branch that isn't passing checks and tests."
exit 1
fi
# Return to original directory
cd - > /dev/null
echo "✅ Worktree created successfully!"
echo "📁 Path: ${WORKTREE_PATH}"
echo "🔀 Branch: ${WORKTREE_NAME}"
echo ""
echo "To work in this worktree:"
echo " cd ${WORKTREE_PATH}"
echo ""
echo "To remove this worktree later:"
echo " git worktree remove ${WORKTREE_PATH}"
echo " git branch -D ${WORKTREE_NAME}"