Class override system: .upstream file handling and restore logic Php_Fixer: Redirect use statements to correct manifest FQCN Fix: Only match PHP files in __find_class_fqcn_in_manifest Complete Php_Fixer use statement redirection implementation (checkpoint 2) WIP: Php_Fixer use statement redirection for class overrides (checkpoint) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
682 lines
26 KiB
Bash
Executable File
682 lines
26 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# RSpade Framework Update Script
|
|
# Pulls updates from rspade_upstream remote while preserving ./rsx in project mode
|
|
# This script runs BEFORE Laravel loads to update framework code independently
|
|
|
|
set -e
|
|
|
|
# Parse arguments
|
|
NO_REBUILD=false
|
|
SHOW_DIFF=false
|
|
STASH_CHANGES=false
|
|
for arg in "$@"; do
|
|
if [ "$arg" = "--no-rebuild" ]; then
|
|
NO_REBUILD=true
|
|
elif [ "$arg" = "--diff" ]; then
|
|
SHOW_DIFF=true
|
|
elif [ "$arg" = "--stash" ]; then
|
|
STASH_CHANGES=true
|
|
fi
|
|
done
|
|
|
|
# Configure git to ignore file mode changes
|
|
git config core.fileMode false
|
|
|
|
# Determine project mode: Check for .rspade-dev-environment or rsx/.git
|
|
IS_PROJECT_MODE=false
|
|
if [ -f ".rspade-dev-environment" ] || [ -d "rsx/.git" ]; then
|
|
IS_PROJECT_MODE=true
|
|
fi
|
|
|
|
# In project mode, rsx/.git MUST exist
|
|
if [ "$IS_PROJECT_MODE" = true ] && [ ! -d "rsx/.git" ]; then
|
|
echo "ERROR: ./rsx is not a git repository."
|
|
echo ""
|
|
echo "The development environment appears corrupted."
|
|
echo "Expected ./rsx to be an independent git repository."
|
|
exit 1
|
|
fi
|
|
|
|
# Check if framework is forked
|
|
if [ -f ".rspade-forked-framework" ]; then
|
|
echo "ERROR: Framework is in forked mode."
|
|
echo ""
|
|
echo "You have taken full ownership of the RSpade framework codebase."
|
|
echo "Automatic updates are disabled to prevent overwriting your changes."
|
|
echo ""
|
|
echo "To manually update from upstream:"
|
|
echo " 1. git fetch rspade_upstream"
|
|
echo " 2. git diff rspade_upstream/rspade_selfupdate"
|
|
echo " 3. Manually merge desired changes"
|
|
echo " 4. Test thoroughly"
|
|
echo ""
|
|
echo "For detailed procedures: php artisan rsx:man framework_fork"
|
|
exit 1
|
|
fi
|
|
|
|
# Check .env for IS_FRAMEWORK_DEVELOPER=true
|
|
if [ -f ".env" ]; then
|
|
if grep -q "^IS_FRAMEWORK_DEVELOPER=true" .env; then
|
|
echo "ERROR: This command is disabled for framework developers."
|
|
echo ""
|
|
echo "This command is for application developers to pull framework updates."
|
|
echo "Framework developers should use standard git commands to manage the monorepo."
|
|
echo ""
|
|
echo "To use this command, set IS_FRAMEWORK_DEVELOPER=false in .env"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Check APP_ENV for production
|
|
if [ -f ".env" ]; then
|
|
if grep -q "^APP_ENV=production" .env; then
|
|
echo "ERROR: Framework updates are disabled in production mode."
|
|
echo ""
|
|
echo "Framework updates should be incorporated into and tested in a"
|
|
echo "development environment before deploying to production."
|
|
echo ""
|
|
echo "Update in development, test thoroughly, then deploy to production."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Verify rspade_upstream remote exists, auto-configure for project mode
|
|
if ! git remote get-url rspade_upstream >/dev/null 2>&1; then
|
|
# Auto-configure remote for project mode (when system/ is a submodule)
|
|
if [ "$IS_PROJECT_MODE" = false ] && [ -f "../.gitmodules" ] && grep -q "path = system" ../.gitmodules 2>/dev/null; then
|
|
echo "→ Configuring rspade_upstream remote (first-time setup)..."
|
|
UPSTREAM_URL="ssh://git@privategit.hanson.xyz:3322/brianhansonxyz/rspade_system.git"
|
|
if git remote add rspade_upstream "$UPSTREAM_URL" 2>&1; then
|
|
echo " ✓ Remote configured: $UPSTREAM_URL"
|
|
echo ""
|
|
else
|
|
echo "ERROR: Failed to configure rspade_upstream remote."
|
|
exit 1
|
|
fi
|
|
else
|
|
# Framework dev mode or can't auto-detect - require manual configuration
|
|
echo "ERROR: Remote \"rspade_upstream\" not configured."
|
|
echo ""
|
|
echo "Configure the upstream remote:"
|
|
echo " git remote add rspade_upstream <upstream-url>"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Pull RSpade Framework Updates ==="
|
|
echo ""
|
|
|
|
# Detect current branch and set upstream branch
|
|
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>&1)
|
|
|
|
# Handle detached HEAD state (common in git submodules)
|
|
if [ "$CURRENT_BRANCH" = "HEAD" ]; then
|
|
echo "⚠ Detected detached HEAD state (git submodule)"
|
|
echo " Checking out master branch..."
|
|
if ! git checkout master 2>&1; then
|
|
echo "ERROR: Failed to checkout master branch"
|
|
exit 1
|
|
fi
|
|
CURRENT_BRANCH="master"
|
|
echo " ✓ Now on master branch"
|
|
echo ""
|
|
fi
|
|
|
|
UPSTREAM_BRANCH="rspade_upstream/${CURRENT_BRANCH}"
|
|
|
|
if [ "$IS_PROJECT_MODE" = true ]; then
|
|
echo "Mode: Project (./rsx will be preserved)"
|
|
else
|
|
echo "Mode: Framework development (./rsx will be updated)"
|
|
fi
|
|
echo "Branch: $CURRENT_BRANCH → $UPSTREAM_BRANCH"
|
|
echo ""
|
|
|
|
# Remove read-only attribute from CLAUDE.dist.md before update
|
|
if [ -f "docs/CLAUDE.dist.md" ]; then
|
|
echo "→ Removing read-only attribute from docs/CLAUDE.dist.md..."
|
|
chmod u+w docs/CLAUDE.dist.md 2>/dev/null || true
|
|
fi
|
|
|
|
# Fetch updates first (before verifying branch exists)
|
|
echo "Fetching updates from rspade_upstream..."
|
|
if ! git fetch rspade_upstream 2>&1; then
|
|
echo "ERROR: Failed to fetch updates"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Updates fetched"
|
|
|
|
# Verify upstream branch exists (after fetch)
|
|
if ! git rev-parse "$UPSTREAM_BRANCH" >/dev/null 2>&1; then
|
|
echo "ERROR: Upstream branch $UPSTREAM_BRANCH not found"
|
|
echo ""
|
|
echo "Current branch: $CURRENT_BRANCH"
|
|
echo "Expected upstream: $UPSTREAM_BRANCH"
|
|
echo ""
|
|
echo "Available upstream branches:"
|
|
git branch -r | grep rspade_upstream/ | sed 's/^/ /'
|
|
exit 1
|
|
fi
|
|
|
|
# Check if already up-to-date
|
|
CURRENT_HEAD=$(git rev-parse HEAD 2>&1)
|
|
UPSTREAM_HEAD=$(git rev-parse "$UPSTREAM_BRANCH" 2>&1)
|
|
|
|
ALREADY_UP_TO_DATE=false
|
|
if [ "$CURRENT_HEAD" = "$UPSTREAM_HEAD" ]; then
|
|
echo ""
|
|
echo "✓ Already up to date"
|
|
echo ""
|
|
ALREADY_UP_TO_DATE=true
|
|
fi
|
|
|
|
# Handle --diff option: show diff and exit
|
|
if [ "$SHOW_DIFF" = true ]; then
|
|
echo ""
|
|
echo "=== Git Diff: Local Changes vs Upstream ==="
|
|
echo ""
|
|
git diff HEAD "$UPSTREAM_BRANCH"
|
|
exit 0
|
|
fi
|
|
|
|
# =============================================================================
|
|
# STEP: Clean up class override artifacts before checking for uncommitted changes
|
|
# =============================================================================
|
|
# The manifest's class override system renames framework files to .upstream when
|
|
# an rsx/ override exists. Before updating, we need to:
|
|
# 1. Restore any deleted files (git checkout)
|
|
# 2. Delete any .upstream files (the originals will be restored by git)
|
|
# This ensures git sees a clean state, and the next manifest build will
|
|
# re-apply any overrides with the updated framework files.
|
|
# =============================================================================
|
|
|
|
echo "→ Cleaning up class override artifacts..."
|
|
|
|
# Step 1: Restore deleted files
|
|
DELETED_FILES=$(git status --porcelain 2>&1 | grep "^ D " | sed 's/^ D //' || true)
|
|
if [ -n "$DELETED_FILES" ]; then
|
|
echo " Restoring deleted files..."
|
|
echo "$DELETED_FILES" | while read -r file; do
|
|
if [ -n "$file" ]; then
|
|
git checkout HEAD -- "$file" 2>/dev/null && echo " ✓ Restored: $file" || true
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Step 2: Delete .upstream files (framework files renamed by class override system)
|
|
UPSTREAM_FILES=$(find . -name "*.upstream" -type f 2>/dev/null | grep -v "./rsx/" || true)
|
|
if [ -n "$UPSTREAM_FILES" ]; then
|
|
echo " Removing .upstream override markers..."
|
|
echo "$UPSTREAM_FILES" | while read -r upstream_file; do
|
|
if [ -n "$upstream_file" ] && [ -f "$upstream_file" ]; then
|
|
rm -f "$upstream_file" && echo " ✓ Removed: $upstream_file" || true
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Step 3: Restore files with ONLY use statement changes
|
|
# When classes are overridden in rsx/, Php_Fixer updates use statements in system/ files
|
|
# to point to the Rsx\ namespace. These changes should be reverted before framework update.
|
|
# We only auto-revert files where ALL changes are use statement modifications.
|
|
echo " Checking for auto-fixable use statement changes..."
|
|
|
|
MODIFIED_SYSTEM_FILES=$(git diff --name-only -- . ":(exclude)rsx" 2>/dev/null | grep "\.php$" || true)
|
|
USE_STMT_REVERTED=0
|
|
|
|
if [ -n "$MODIFIED_SYSTEM_FILES" ]; then
|
|
while IFS= read -r modified_file; do
|
|
if [ -z "$modified_file" ] || [ ! -f "$modified_file" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Get the diff for this file, check if ALL changed lines are use statements
|
|
# Changed lines start with + or - (excluding the diff header lines +++ and ---)
|
|
DIFF_CONTENT=$(git diff -- "$modified_file" 2>/dev/null || true)
|
|
|
|
if [ -z "$DIFF_CONTENT" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Extract changed lines (+ or - at start, not +++ or ---)
|
|
# Then check if all of them are use statements or empty
|
|
ALL_USE_STATEMENTS=true
|
|
|
|
while IFS= read -r line; do
|
|
# Skip diff metadata lines
|
|
case "$line" in
|
|
"+++"*|"---"*|"@@"*|"diff "*|"index "*) continue ;;
|
|
esac
|
|
|
|
# Check lines that start with + or - (actual changes)
|
|
case "$line" in
|
|
"+"*|"-"*)
|
|
# Remove the leading +/- and trim whitespace
|
|
content="${line#[+-]}"
|
|
content=$(echo "$content" | sed 's/^[[:space:]]*//')
|
|
|
|
# Empty lines are OK
|
|
if [ -z "$content" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Use statements are OK (with or without leading backslash)
|
|
if echo "$content" | grep -qE "^use[[:space:]]+(\\\\)?[A-Za-z]"; then
|
|
continue
|
|
fi
|
|
|
|
# Any other change means this file has non-use-statement modifications
|
|
ALL_USE_STATEMENTS=false
|
|
break
|
|
;;
|
|
esac
|
|
done <<< "$DIFF_CONTENT"
|
|
|
|
# If all changes were use statements, revert the file
|
|
if [ "$ALL_USE_STATEMENTS" = true ]; then
|
|
if git checkout HEAD -- "$modified_file" 2>/dev/null; then
|
|
echo " ✓ Reverted use statements: $modified_file"
|
|
USE_STMT_REVERTED=$((USE_STMT_REVERTED + 1))
|
|
fi
|
|
fi
|
|
done <<< "$MODIFIED_SYSTEM_FILES"
|
|
fi
|
|
|
|
if [ "$USE_STMT_REVERTED" -gt 0 ]; then
|
|
echo " ✓ Reverted $USE_STMT_REVERTED file(s) with use statement changes"
|
|
fi
|
|
|
|
echo " ✓ Override cleanup complete"
|
|
echo ""
|
|
|
|
# In project mode, check for uncommitted changes outside ./rsx
|
|
if [ "$IS_PROJECT_MODE" = true ]; then
|
|
# Get uncommitted changes (modified, staged, deleted) excluding ./rsx
|
|
UNCOMMITTED_CHANGES=$(git diff --name-only -- . ":(exclude)rsx" 2>&1)
|
|
STAGED_CHANGES=$(git diff --cached --name-only -- . ":(exclude)rsx" 2>&1)
|
|
|
|
# Combine and deduplicate (|| true prevents grep exit code 1 from killing script)
|
|
ALL_CHANGES=$(echo -e "${UNCOMMITTED_CHANGES}\n${STAGED_CHANGES}" | sort -u | grep -v "^$" || true)
|
|
|
|
if [ -n "$ALL_CHANGES" ]; then
|
|
if [ "$STASH_CHANGES" = false ]; then
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo "❌ ERROR: Uncommitted framework changes detected"
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "You are in PROJECT MODE where ./rsx is your application repository."
|
|
echo "Framework files outside ./rsx should NEVER be modified in project mode."
|
|
echo ""
|
|
echo "The following framework files have uncommitted changes:"
|
|
echo ""
|
|
echo "$ALL_CHANGES" | sed 's/^/ /'
|
|
echo ""
|
|
echo "These changes must be resolved before updating the framework."
|
|
echo ""
|
|
echo "OPTIONS:"
|
|
echo ""
|
|
echo " 1. VIEW DIFFERENCES"
|
|
echo " See what changed between your local files and upstream:"
|
|
echo ""
|
|
echo " php artisan rsx:framework:pull --diff"
|
|
echo ""
|
|
echo " 2. STASH CHANGES AND UPDATE (recommended)"
|
|
echo " Your changes will be stashed automatically, then the framework"
|
|
echo " will be updated. You can review or restore the stashed changes after:"
|
|
echo ""
|
|
echo " php artisan rsx:framework:pull --stash"
|
|
echo ""
|
|
echo " After update, review your stashed changes:"
|
|
echo " git stash list"
|
|
echo " git stash show"
|
|
echo " git stash pop (to restore)"
|
|
echo ""
|
|
echo " 3. DISCARD FRAMEWORK CHANGES"
|
|
echo " If these were accidental edits, reset them:"
|
|
echo ""
|
|
echo " git checkout HEAD -- [file paths]"
|
|
echo ""
|
|
echo " Or reset all framework changes:"
|
|
echo " git checkout HEAD -- . ':!rsx'"
|
|
echo ""
|
|
echo " 4. COMMIT THEN UPDATE (framework developers only)"
|
|
echo " If you're intentionally modifying the framework:"
|
|
echo ""
|
|
echo " git add -A"
|
|
echo " git commit -m \"Framework modifications\""
|
|
echo " php artisan rsx:framework:pull"
|
|
echo ""
|
|
echo " 5. FORK THE FRAMEWORK"
|
|
echo " If you need to preserve framework modifications permanently:"
|
|
echo ""
|
|
echo " php artisan rsx:man framework_fork"
|
|
echo ""
|
|
echo " This documents taking full control of the framework codebase."
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo "Note to LLM agents:"
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "You have attempted to update the framework with uncommitted changes present."
|
|
echo ""
|
|
echo "REQUIRED ACTIONS:"
|
|
echo ""
|
|
echo " 1. Show the developer the full list of uncommitted files above"
|
|
echo " 2. Run 'git diff' to show what changed in those files"
|
|
echo " 3. Ask the developer explicitly: 'These framework files were modified."
|
|
echo " Do you want me to discard these changes and update the framework,"
|
|
echo " or stash them and proceed with the update?'"
|
|
echo ""
|
|
echo "You MUST NOT proceed until the developer has made a decision."
|
|
echo "You MUST NOT automatically use --stash without explicit permission."
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
exit 1
|
|
else
|
|
# Stash changes with descriptive message
|
|
echo ""
|
|
echo "⚠️ Stashing uncommitted framework changes..."
|
|
echo ""
|
|
STASH_MESSAGE="Auto-stashed by framework update with --stash on $(date '+%Y-%m-%d %H:%M:%S')"
|
|
|
|
if ! git stash push -u -m "$STASH_MESSAGE" -- . ":(exclude)rsx" 2>&1; then
|
|
echo "ERROR: Failed to stash changes"
|
|
exit 1
|
|
fi
|
|
|
|
echo " ✓ Changes stashed"
|
|
echo ""
|
|
echo "Your changes have been saved. After update completes, you can review them:"
|
|
echo " git stash list"
|
|
echo " git stash show"
|
|
echo " git stash pop (to restore changes)"
|
|
echo ""
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# In framework mode, check for uncommitted changes
|
|
if [ "$IS_PROJECT_MODE" = false ]; then
|
|
# Get uncommitted changes (modified, staged, deleted)
|
|
UNCOMMITTED_CHANGES=$(git diff --name-only 2>&1)
|
|
STAGED_CHANGES=$(git diff --cached --name-only 2>&1)
|
|
|
|
# Combine and deduplicate (|| true prevents grep exit code 1 from killing script)
|
|
ALL_CHANGES=$(echo -e "${UNCOMMITTED_CHANGES}\n${STAGED_CHANGES}" | sort -u | grep -v "^$" || true)
|
|
|
|
if [ -n "$ALL_CHANGES" ]; then
|
|
if [ "$STASH_CHANGES" = false ]; then
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo "❌ ERROR: Uncommitted changes detected"
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "You are in FRAMEWORK MODE where this repository is the framework itself."
|
|
echo "The following files have uncommitted changes:"
|
|
echo ""
|
|
echo "$ALL_CHANGES" | sed 's/^/ /'
|
|
echo ""
|
|
echo "These changes must be resolved before updating the framework."
|
|
echo ""
|
|
echo "OPTIONS:"
|
|
echo ""
|
|
echo " 1. VIEW DIFFERENCES"
|
|
echo " See what changed between your local files and upstream:"
|
|
echo ""
|
|
echo " php artisan rsx:framework:pull --diff"
|
|
echo ""
|
|
echo " 2. STASH CHANGES AND UPDATE (recommended)"
|
|
echo " Your changes will be stashed automatically, then the framework"
|
|
echo " will be updated. You can review or restore the stashed changes after:"
|
|
echo ""
|
|
echo " php artisan rsx:framework:pull --stash"
|
|
echo ""
|
|
echo " After update, review your stashed changes:"
|
|
echo " git stash list"
|
|
echo " git stash show"
|
|
echo " git stash pop (to restore)"
|
|
echo ""
|
|
echo " 3. DISCARD CHANGES"
|
|
echo " If these were accidental edits, reset them:"
|
|
echo ""
|
|
echo " git reset --hard HEAD"
|
|
echo ""
|
|
echo " 4. COMMIT THEN UPDATE"
|
|
echo " If you're intentionally modifying the framework:"
|
|
echo ""
|
|
echo " git add -A"
|
|
echo " git commit -m \"Framework modifications\""
|
|
echo " php artisan rsx:framework:pull"
|
|
echo ""
|
|
echo "════════════════════════════════════════════════════════════════════════════════"
|
|
exit 1
|
|
else
|
|
# Stash changes with descriptive message
|
|
echo ""
|
|
echo "⚠️ Stashing uncommitted changes..."
|
|
echo ""
|
|
STASH_MESSAGE="Auto-stashed by framework update with --stash on $(date '+%Y-%m-%d %H:%M:%S')"
|
|
|
|
if ! git stash push -u -m "$STASH_MESSAGE" 2>&1; then
|
|
echo "ERROR: Failed to stash changes"
|
|
exit 1
|
|
fi
|
|
|
|
echo " ✓ Changes stashed"
|
|
echo ""
|
|
echo "Your changes have been saved. After update completes, you can review them:"
|
|
echo " git stash list"
|
|
echo " git stash show"
|
|
echo " git stash pop (to restore changes)"
|
|
echo ""
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Apply framework updates (skip if already up to date)
|
|
if [ "$ALREADY_UP_TO_DATE" = false ]; then
|
|
# Extract and display changelog
|
|
echo ""
|
|
echo "⚠ RSpade framework has upstream changes"
|
|
echo ""
|
|
|
|
# Get commit subjects, filter out Claude Code attribution and blank lines
|
|
CHANGELOG=$(git log --pretty=format:"%s" HEAD.."$UPSTREAM_BRANCH" 2>&1 | \
|
|
grep -v "Claude Code" | \
|
|
grep -v "Co-Authored-By:" | \
|
|
grep -v "^$" | \
|
|
sed 's/^/ • /')
|
|
|
|
if [ -n "$CHANGELOG" ]; then
|
|
echo "Changelog:"
|
|
echo ""
|
|
echo "$CHANGELOG"
|
|
echo ""
|
|
fi
|
|
|
|
# Show file diff stats (exclude ./rsx if in project mode)
|
|
if [ "$IS_PROJECT_MODE" = true ]; then
|
|
DIFF_STATS=$(git diff --stat HEAD.."$UPSTREAM_BRANCH" -- . ":(exclude)rsx" 2>&1)
|
|
else
|
|
DIFF_STATS=$(git diff --stat HEAD.."$UPSTREAM_BRANCH" 2>&1)
|
|
fi
|
|
|
|
if [ -n "$DIFF_STATS" ]; then
|
|
echo "Files that will be updated:"
|
|
echo ""
|
|
echo "$DIFF_STATS" | sed 's/^/ /'
|
|
echo ""
|
|
fi
|
|
|
|
# Apply updates based on mode
|
|
echo "Applying framework updates..."
|
|
|
|
if [ "$IS_PROJECT_MODE" = true ]; then
|
|
# Project mode: merge with --no-ff (preserves ./rsx via .gitattributes)
|
|
if ! git merge --no-ff "$UPSTREAM_BRANCH" 2>&1; then
|
|
echo "ERROR: Framework update failed."
|
|
echo ""
|
|
|
|
# Show current git state
|
|
GIT_STATUS=$(git status --short 2>&1)
|
|
if [ -n "$GIT_STATUS" ]; then
|
|
echo "Current git state:"
|
|
echo ""
|
|
echo "$GIT_STATUS" | sed 's/^/ /'
|
|
echo ""
|
|
fi
|
|
|
|
echo "Check status: php artisan rsx:framework:status"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Framework updated (./rsx preserved by .gitattributes)"
|
|
|
|
# Remove files that were deleted upstream (git merge doesn't auto-delete)
|
|
echo " → Cleaning up deleted files..."
|
|
DELETED_FILES=$(git diff --name-only --diff-filter=D HEAD~1 HEAD -- rsx/ 2>/dev/null || true)
|
|
if [ -n "$DELETED_FILES" ]; then
|
|
echo "$DELETED_FILES" | while read -r file; do
|
|
if [ -f "$file" ]; then
|
|
rm -f "$file"
|
|
echo " Removed: $file"
|
|
fi
|
|
done
|
|
fi
|
|
else
|
|
# Framework mode: fast-forward only (updates everything including ./rsx)
|
|
MERGE_OUTPUT=$(git merge --ff-only "$UPSTREAM_BRANCH" 2>&1) || {
|
|
if echo "$MERGE_OUTPUT" | grep -q "up to date\|up-to-date"; then
|
|
echo " ✓ Already up to date"
|
|
else
|
|
echo "ERROR: Framework update failed."
|
|
echo ""
|
|
echo "ERROR: Cannot fast-forward: you have local modifications"
|
|
echo ""
|
|
|
|
# Show modified files
|
|
GIT_STATUS=$(git status --short 2>&1)
|
|
if [ -n "$GIT_STATUS" ]; then
|
|
echo "Modified files blocking update:"
|
|
echo ""
|
|
echo "$GIT_STATUS" | sed 's/^/ /'
|
|
echo ""
|
|
fi
|
|
|
|
echo "To resolve:"
|
|
echo ""
|
|
echo " 1. VIEW DIFFERENCES"
|
|
echo " php artisan rsx:framework:pull --diff"
|
|
echo ""
|
|
echo " 2. STASH CHANGES AND UPDATE (recommended)"
|
|
echo " php artisan rsx:framework:pull --stash"
|
|
echo ""
|
|
echo " 3. DISCARD MODIFICATIONS"
|
|
echo " git reset --hard $UPSTREAM_BRANCH"
|
|
echo ""
|
|
echo " 4. COMMIT THEN UPDATE"
|
|
echo " git add -A"
|
|
echo " git commit -m \"Framework modifications\""
|
|
echo " php artisan rsx:framework:pull"
|
|
echo ""
|
|
echo " 5. CHECK STATUS"
|
|
echo " php artisan rsx:framework:status"
|
|
exit 1
|
|
fi
|
|
}
|
|
echo " ✓ Framework updated"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
if [ "$ALREADY_UP_TO_DATE" = true ]; then
|
|
echo "→ Running framework maintenance (migrations and cache rebuild)..."
|
|
else
|
|
echo "✓ Framework updated successfully"
|
|
fi
|
|
echo ""
|
|
|
|
if [ "$IS_PROJECT_MODE" = true ] && [ "$ALREADY_UP_TO_DATE" = false ]; then
|
|
echo "Your application code in ./rsx was preserved."
|
|
echo ""
|
|
fi
|
|
|
|
# Rebuild caches after framework update
|
|
if [ "$NO_REBUILD" = true ]; then
|
|
echo "⚠️ Cleaning caches only (--no-rebuild specified)"
|
|
echo ""
|
|
|
|
if ! php artisan rsx:clean --silent; then
|
|
echo "ERROR: Cache clean failed"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Caches cleaned"
|
|
echo ""
|
|
|
|
echo "⚠ Manifest and bundles NOT rebuilt - you must run manually:"
|
|
echo " php artisan rsx:manifest:build"
|
|
echo " php artisan rsx:bundle:compile"
|
|
echo ""
|
|
else
|
|
echo "⚠️ Regenerating framework caches"
|
|
echo ""
|
|
echo " This rebuild is only required because the framework itself was updated."
|
|
echo " Never run these commands manually unless there are catastrophic errors."
|
|
echo ""
|
|
|
|
# Step 1: Clean caches
|
|
echo "Step 1/4: Cleaning caches..."
|
|
if ! php artisan rsx:clean --silent; then
|
|
echo "ERROR: Cache clean failed"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Caches cleaned"
|
|
echo ""
|
|
|
|
# Step 2: Rebuild manifest
|
|
echo "Step 2/4: Rebuilding manifest..."
|
|
if ! php artisan rsx:manifest:build; then
|
|
echo "ERROR: Manifest rebuild failed"
|
|
echo " Run manually: php artisan rsx:manifest:build"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Manifest rebuilt"
|
|
echo ""
|
|
|
|
# Step 3: Run framework migrations (before bundle compile)
|
|
echo "Step 3/4: Running framework migrations..."
|
|
if ! php artisan migrate --framework-only --force; then
|
|
echo "ERROR: Framework migrations failed"
|
|
echo " Check errors above and fix migration issues"
|
|
echo ""
|
|
echo " Bundle compilation skipped due to migration failure"
|
|
exit 1
|
|
fi
|
|
echo " ✓ Framework migrations completed"
|
|
echo ""
|
|
|
|
# Step 4: Compile bundles (only if migrations succeeded)
|
|
echo "Step 4/4: Compiling all bundles..."
|
|
if ! php artisan rsx:bundle:compile; then
|
|
echo "ERROR: Bundle compilation failed"
|
|
echo " Check errors above and fix bundle issues"
|
|
exit 1
|
|
fi
|
|
echo " ✓ All bundles compiled"
|
|
echo ""
|
|
fi
|
|
|
|
# Set read-only attribute on CLAUDE.dist.md after successful update
|
|
if [ -f "docs/CLAUDE.dist.md" ]; then
|
|
echo "→ Setting read-only attribute on docs/CLAUDE.dist.md..."
|
|
chmod u-w docs/CLAUDE.dist.md 2>/dev/null || true
|
|
echo " ✓ Framework documentation marked read-only"
|
|
echo ""
|
|
fi
|
|
|
|
echo "✅ Framework update complete"
|
|
echo ""
|
|
|
|
exit 0
|