282 lines
7.9 KiB
Bash
Executable File
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" |