ai/ai
ai/ai
1
0
ai/claude/scripts/update-submodules.sh
2025-06-07 03:05:38 +09:00

282 lines
7.9 KiB
Bash
Executable File

#!/bin/zsh
# Platform-specific commands
case $OSTYPE in
darwin*)
date_cmd() { gdate "$@"; }
;;
linux*)
date_cmd() { date "$@"; }
;;
esac
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SCRIPT_DIR="${0:a:h}"
REPO_ROOT="${SCRIPT_DIR:h:h}"
LOGFILE="$REPO_ROOT/.submodule-update.log"
# Usage function
usage() {
echo "Usage: $0 [--all] [--module=<name>] [--auto] [--dry-run] [--help]"
echo ""
echo "Options:"
echo " --all Update all submodules"
echo " --module=<name> Update specific submodule (os, gpt, card, etc.)"
echo " --auto Auto-commit if changes detected"
echo " --dry-run Show what would be done without making changes"
echo " --help Show this help message"
echo ""
echo "Available submodules:"
git submodule status | awk '{print " " $2}'
exit 1
}
# Logging function
log() {
local level="$1"
shift
local message="$*"
local timestamp=$(date_cmd '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOGFILE"
}
# Parse arguments
UPDATE_ALL=false
SPECIFIC_MODULE=""
AUTO_COMMIT=false
DRY_RUN=false
for arg in "$@"; do
case $arg in
--all)
UPDATE_ALL=true
;;
--module=*)
SPECIFIC_MODULE="${arg#*=}"
;;
--auto)
AUTO_COMMIT=true
;;
--dry-run)
DRY_RUN=true
;;
--help|-h)
usage
;;
*)
echo "Unknown argument: $arg"
usage
;;
esac
done
# Validate arguments
if [[ "$UPDATE_ALL" == false && -z "$SPECIFIC_MODULE" ]]; then
echo "Error: Either --all or --module=<name> is required"
usage
fi
if [[ "$UPDATE_ALL" == true && -n "$SPECIFIC_MODULE" ]]; then
echo "Error: Cannot use both --all and --module"
usage
fi
# Change to repository root
cd "$REPO_ROOT" || exit 1
echo -e "${BLUE}🚀 Starting submodule update...${NC}"
log "INFO" "Starting submodule update (all=$UPDATE_ALL, module=$SPECIFIC_MODULE, auto=$AUTO_COMMIT, dry-run=$DRY_RUN)"
if [[ "$DRY_RUN" == true ]]; then
echo -e "${YELLOW}🔍 DRY RUN MODE - No changes will be made${NC}"
fi
# Update function
update_submodule() {
local module_name="$1"
local module_path="$2"
echo -e "\n${BLUE}📦 Processing: $module_name${NC}"
# Check if submodule exists
if [[ ! -d "$module_path" ]]; then
echo -e "${RED}❌ Submodule directory not found: $module_path${NC}"
return 1
fi
# Get current commit
local current_commit=$(git submodule status "$module_path" | awk '{print $1}' | sed 's/^[+-]//')
# Get current branch of the submodule
cd "$module_path" || return 1
local current_branch=$(git branch --show-current)
if [[ -z "$current_branch" ]]; then
# If not on a branch (detached HEAD), try to determine the default branch
current_branch="main"
if ! git rev-parse origin/main >/dev/null 2>&1; then
current_branch="master"
fi
fi
cd "$REPO_ROOT"
if [[ "$DRY_RUN" == true ]]; then
echo -e "${YELLOW}🔍 [DRY RUN] Would update $module_name (branch: $current_branch)${NC}"
echo " Current: $current_commit"
cd "$module_path" || return 1
git fetch origin >/dev/null 2>&1
local latest_commit=$(git rev-parse "origin/$current_branch" 2>/dev/null)
echo " Latest: $latest_commit"
cd "$REPO_ROOT"
if [[ "$current_commit" != "$latest_commit" ]]; then
echo -e "${YELLOW} 📝 Changes available${NC}"
return 0
else
echo -e "${GREEN} ✅ Already up to date${NC}"
return 1
fi
fi
# Update submodule
echo "🔄 Fetching latest changes..."
cd "$module_path" || return 1
if ! git fetch origin; then
echo -e "${RED}❌ Failed to fetch from origin${NC}"
cd "$REPO_ROOT"
return 1
fi
# Use the current branch we detected earlier
local latest_commit=$(git rev-parse "origin/$current_branch" 2>/dev/null)
if [[ "$current_commit" == "$latest_commit" ]]; then
echo -e "${GREEN}✅ Already up to date${NC}"
cd "$REPO_ROOT"
return 1
fi
echo "📝 Updating to latest commit on branch $current_branch..."
# First ensure we're on the correct branch
if ! git checkout "$current_branch"; then
echo -e "${RED}❌ Failed to checkout branch $current_branch${NC}"
cd "$REPO_ROOT"
return 1
fi
# Then pull the latest changes
if ! git pull origin "$current_branch"; then
echo -e "${RED}❌ Failed to pull latest changes from $current_branch${NC}"
cd "$REPO_ROOT"
return 1
fi
cd "$REPO_ROOT"
# Get the new commit after update
local new_commit=$(cd "$module_path" && git rev-parse HEAD)
# Stage the submodule update
git add "$module_path"
echo -e "${GREEN}✅ Updated $module_name (branch: $current_branch)${NC}"
echo " From: $current_commit"
echo " To: $new_commit"
log "INFO" "Updated $module_name on branch $current_branch: $current_commit -> $new_commit"
return 0
}
# Get list of submodules
declare -A submodules
while IFS= read -r line; do
if [[ $line =~ ^\[submodule\ \"([^\"]+)\"\] ]]; then
current_name="${match[1]}"
elif [[ $line =~ ^[[:space:]]*path[[:space:]]*=[[:space:]]*(.+)$ ]]; then
submodules[$current_name]="${match[1]}"
fi
done < .gitmodules
# Main execution
success_count=0
total_count=0
if [[ "$UPDATE_ALL" == true ]]; then
echo -e "${BLUE}📚 Updating all submodules...${NC}"
for module_name in "${(@k)submodules}"; do
module_path="${submodules[$module_name]}"
((total_count++))
if update_submodule "$module_name" "$module_path"; then
((success_count++))
fi
done
else
echo -e "${BLUE}📖 Updating submodule: $SPECIFIC_MODULE${NC}"
if [[ -z "${submodules[$SPECIFIC_MODULE]}" ]]; then
echo -e "${RED}❌ Submodule '$SPECIFIC_MODULE' not found${NC}"
echo "Available submodules: ${(@k)submodules}"
exit 1
fi
module_path="${submodules[$SPECIFIC_MODULE]}"
((total_count++))
if update_submodule "$SPECIFIC_MODULE" "$module_path"; then
((success_count++))
fi
fi
# Summary
echo ""
echo -e "${BLUE}📊 Summary:${NC}"
echo " 📦 Modules processed: $total_count"
echo " ✅ Updates applied: $success_count"
echo " 📝 No changes: $((total_count - success_count))"
if [[ "$DRY_RUN" == true ]]; then
echo ""
echo -e "${YELLOW}🔍 This was a dry run. To apply changes, run without --dry-run${NC}"
exit 0
fi
# Auto-commit if requested and changes exist
if [[ "$success_count" -gt 0 ]]; then
if [[ "$AUTO_COMMIT" == true ]]; then
echo ""
echo -e "${BLUE}💾 Auto-committing submodule updates...${NC}"
commit_message="Update submodules
📦 Updated modules: $success_count/$total_count
$(git diff --cached --name-only | sed 's/^/- /')
🤖 Generated with submodule auto-update
$(date_cmd '+%Y-%m-%d %H:%M:%S')"
if git commit -m "$commit_message"; then
echo -e "${GREEN}✅ Changes committed successfully${NC}"
log "INFO" "Auto-committed $success_count submodule updates"
else
echo -e "${RED}❌ Failed to commit changes${NC}"
log "ERROR" "Failed to auto-commit submodule updates"
fi
else
echo ""
echo -e "${YELLOW}📝 Changes staged but not committed. Run 'git commit' to commit them.${NC}"
echo "Or use --auto flag to commit automatically."
fi
fi
echo ""
echo -e "${GREEN}🎉 Submodule update completed!${NC}"
log "INFO" "Submodule update completed: $success_count/$total_count updated"