#!/bin/bash # ============================================ # sync.sh - Host-to-Container code sync script # ============================================ # Syncs code from /var/www/source (bind mount from host) # to /var/www/html (container-native filesystem, fast I/O). # # Usage: # sync.sh init - Perform initial full sync, then exit # sync.sh watch - Run periodic incremental sync (blocking) # sync.sh - Same as: init + watch # # Environment variables: # SYNC_INTERVAL - Polling interval in seconds (default: 3) # SYNC_EXTRAS - Additional rsync exclude patterns (space-separated) # ============================================ SOURCE_DIR="/var/www/source/" TARGET_DIR="/var/www/html/" SYNC_INTERVAL=${SYNC_INTERVAL:-3} # Build rsync exclude patterns build_exclude_args() { EXCLUDE_ARGS=( --exclude='.git' --exclude='.gitignore' --exclude='.sisyphus' --exclude='.opencode' --exclude='.agents' --exclude='.docker-dev-sync' --exclude='.docker-dev.env' --exclude='.docker-dev' --exclude='docker-dev' --exclude='docker-dev-sync' --exclude='node_modules' --exclude='runtime' --exclude='.idea' --exclude='.vscode' --exclude='*.sock' --exclude='.env' # vendor is managed by Docker build (composer install), do not overwrite --exclude='vendor' ) # Add extra excludes if provided if [ -n "$SYNC_EXTRAS" ]; then for pattern in $SYNC_EXTRAS; do EXCLUDE_ARGS+=(--exclude="$pattern") done fi } # Sync .env separately (excluded from rsync to avoid overwriting on rebuild) sync_env() { if [ -f "/var/www/source/.env" ]; then cp /var/www/source/.env /var/www/html/.env 2>/dev/null fi } # rsync common flags # --no-perms --no-owner --no-group: don't preserve source permissions (Windows mounts have bad perms) RSYNC_FLAGS="-a --no-perms --no-owner --no-group" # ---- Initial full sync ---- do_init() { build_exclude_args echo "============================================" echo "[sync] Starting initial full sync..." echo "[sync] Source: ${SOURCE_DIR}" echo "[sync] Target: ${TARGET_DIR}" echo "============================================" rsync ${RSYNC_FLAGS} --delete "${EXCLUDE_ARGS[@]}" "$SOURCE_DIR" "$TARGET_DIR" if [ $? -eq 0 ]; then echo "[sync] Initial sync complete." else echo "[sync] WARNING: Initial sync had errors (source may not be mounted yet)." fi sync_env } # ---- Periodic incremental sync (blocking) ---- do_watch() { build_exclude_args echo "[sync] Starting periodic sync (interval: ${SYNC_INTERVAL}s)..." while true; do sleep "$SYNC_INTERVAL" # Check if source directory is mounted and accessible if [ ! -d "/var/www/source" ]; then continue fi # Incremental sync (only changed files) rsync ${RSYNC_FLAGS} --delete "${EXCLUDE_ARGS[@]}" "$SOURCE_DIR" "$TARGET_DIR" 2>/dev/null # Sync .env separately sync_env done } # ---- Main ---- MODE="${1:-all}" case "$MODE" in init) do_init ;; watch) do_watch ;; all|"") do_init do_watch ;; *) echo "Usage: $0 [init|watch]" echo " init - Initial full sync, then exit" echo " watch - Periodic incremental sync (blocking)" echo " (no args) - init + watch" exit 1 ;; esac