#!/usr/bin/env bash # Author: Julien Gautier # Organization: AdAstra # Project: adastra_scripts # ################################################################################ # Directory Sync Utility Script # # Watches a local directory for file changes and syncs them to a remote host # via SCP in real time. On exit (Ctrl+C), resets the remote repository and # clears the remote cache. # # Usage: ./dir-sync.sh [OPTIONS] # # Options: # -s, --source Local directory absolute path # -d, --dest Remote directory absolute path # -r, --remote-host Remote SSH host # -h, --help Print this help # # Examples: # ./dir-sync.sh -s /var/www/myapp/ -d /var/www/myapp/ -r myserver # ./dir-sync.sh -s ~/projects/app/ -d /srv/app/ -r devhost # # Requirements: # fswatch, scp, ssh # ################################################################################ # --- Configuration ----------------------------------------------------------- DEFAULT_LOCAL_PATH='/path/to/local/dir/' DEFAULT_REMOTE_PATH='/path/to/remote/dir/' DEFAULT_HOST='devhost' # --- Colors ------------------------------------------------------------------ NONE='\033[0m' BOLD='\033[1m' GREEN='\033[0;32m' YELLOW='\033[0;33m' RED='\033[0;31m' BLUE='\033[0;34m' CYAN='\033[0;36m' MAGENTA='\033[0;35m' BBLUE='\033[1;94m' # --- Usage ------------------------------------------------------------------- usage() { echo -e " ${BOLD}NAME${NONE} dir-sync — Synchronize a local folder to a remote host ${BOLD}SYNOPSIS${NONE} bash $0 [OPTION]... ${BOLD}OPTIONS${NONE} -h, --help Print this help -s, --source Local directory absolute path -d, --dest Remote directory absolute path -r, --remote-host Remote SSH host ${RED}Example:${NONE} $0 -s /path/to/local/ -d /path/to/remote/ -r sshhost " } # --- Prerequisite checks ----------------------------------------------------- check_deps() { local missing=0 for cmd in fswatch scp ssh; do if ! command -v "$cmd" &>/dev/null; then echo -e "${RED}✗ Missing required command: ${cmd}${NONE}" missing=1 fi done [ "$missing" -eq 0 ] || exit 1 } # --- Cleanup (runs on INT/TERM) ---------------------------------------------- cleanup() { echo -e "\n${CYAN}♻️ Resetting remote repository...${NONE}" echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; git reset --hard\"${NONE}" ssh "$host" "cd '${dir_remote}'; git reset --hard" echo -e "\n${CYAN}🗑️ Clearing remote cache...${NONE}" echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; composer front-cache-clear\"${NONE}" ssh "$host" "cd '${dir_remote}'; composer front-cache-clear" wait echo -e "\n${GREEN}✔ Done.${NONE}" exit 0 } # --- Sync a single file ------------------------------------------------------ sync_file() { local local_path="$1" local remote_path="${local_path/$dir_local/$dir_remote}" echo -e "\n${CYAN}🔄 Syncing ${YELLOW}${local_path/$dir_local/}${NONE}" echo -e "\$> ${MAGENTA}scp '${local_path}' ${host}:'${remote_path}'${NONE}" scp "${local_path}" "${host}:${remote_path}" } # --- Main -------------------------------------------------------------------- clear echo -e "${BBLUE}🔎 Starting $0${NONE}" echo -e "${BLUE}-------------------------------${NONE}" check_deps dir_local='' dir_remote='' host='' while [[ $# -gt 0 ]]; do case "$1" in -h|--help) usage; exit 0 ;; -s|--source) dir_local="$2"; shift 2 ;; -d|--dest) dir_remote="$2"; shift 2 ;; -r|--remote-host) host="$2"; shift 2 ;; *) echo -e "${RED}✗ Unknown option: $1${NONE}" usage exit 1 ;; esac done if [[ -z "$dir_local" ]]; then dir_local="$DEFAULT_LOCAL_PATH" echo -e "${YELLOW}⚠ Local path: ${dir_local} (default)${NONE}" else echo -e "${GREEN}⚙️ Local path: ${dir_local}${NONE}" fi if [[ -z "$dir_remote" ]]; then dir_remote="$DEFAULT_REMOTE_PATH" echo -e "${YELLOW}⚠ Remote path: ${dir_remote} (default)${NONE}" else echo -e "${GREEN}⚙️ Remote path: ${dir_remote}${NONE}" fi if [[ -z "$host" ]]; then host="$DEFAULT_HOST" echo -e "${YELLOW}⚠ Remote host: ${host} (default)${NONE}" else echo -e "${GREEN}⚙️ Remote host: ${host}${NONE}" fi trap cleanup INT TERM echo -e "\n${BBLUE}⏳ Watching for changes...${NONE}" echo -e "${BLUE}-----------------------------${NONE}" while IFS= read -r file; do if [[ "$file" == "NoOp" ]]; then echo -e "\n${CYAN}🗑️ Clearing remote cache...${NONE}" echo -e "\$> ${MAGENTA}ssh ${host} \"cd '${dir_remote}'; composer front-cache-clear\"${NONE}" ssh "$host" "cd '${dir_remote}'; composer front-cache-clear" echo -e "\n${BBLUE}⏳ Watching for changes...${NONE}" echo -e "${BLUE}-----------------------------${NONE}" else sync_file "$file" & fi done < <(fswatch --batch-marker -0 --exclude '.git/' "$dir_local" | tr '\0' '\n')