#!/bin/bash

vers=2026.02.02.A
# sync current folder to web folder on web server

echo
echo "Sync to Server version $vers"
echo


# do not sync if flag file is present at root
do_not_sync_file=".do not sync"
switch_verify_allow=
switch_verify_root=1
switch_pingtimeoutsec=1



########################################
##  ABORT
########################################

abort () {
line=$1
msg=$2
echo "ABORT on line $((line-1)): $msg"
exit 1
}



########################################
##  CONFIGURE
########################################

target_path_file=".server_target_path.txt"  # contains something like   root@192.168.1.25;666:/Volumes/WebDrive/sites/mysite.com/thisfoldername
# ";666" specifies port.  uses ssh default if not specified

rsh='/usr/bin/ssh -p :PORT: -o "StrictHostKeyChecking=no"'

allow_file=".allow_source.txt"

rsync_app="/usr/local/bin/rsync_307"  # 2.6.9 chokes on extended attributes like file comments and labels



########################################
##  SWITCHES
########################################

switch_dotfiles=
switch_dryrun=
switch_source=
switch_target=
switch_targetsfile=$target_path_file
switch_targetspost=
while [ "${1:0:1}" == "-" ] ; do
  if [ "$1" == "-n" ] ; then
    shift
    switch_dryrun=1
    echo "accepted switch DRYRUN"
  elif [ "$1" == "-dotfiles" ] ; then
    shift
    switch_dotfiles=1
    echo "accepted switch DOTFILES"
  elif [ "$1" == "-s" ] ; then
    shift
    if [[ (-z "${1:-}") || ("${1:0:1}" == "-") ]] ; then
      abort $LINENO "switch SOURCE rquires a parameter"
    fi
    switch_source="$1"  # "/Users/goofy/Documents/www/mystuff"
    shift
    echo "accepted switch SOURCE with parameter \"$switch_source\""
  elif [ "$1" == "-t" ] ; then
    shift
    if [[ (-z "${1:-}") || ("${1:0:1}" == "-") ]] ; then
      abort $LINENO "switch TARGET rquires a parameter"
    fi
    switch_target="$1"  # "root@192.168.1.11:/Volumes/BigHD/www/mystuff"
    shift
    echo "accepted switch TARGET with parameter \"$switch_target\""
  elif [ "$1" == "-tf" ] ; then
    shift
    if [[ (-z "${1:-}") || ("${1:0:1}" == "-") ]] ; then
      abort $LINENO "switch TARGETS FILE rquires a parameter"
    fi
    switch_targetsfile="$1"  # "/Users/goober/www/servertargets.txt"
    shift
    echo "accepted switch TARGETS FILE with parameter \"$switch_targetsfile\""
  elif [ "$1" == "-tp" ] ; then
    shift
    #if [[ (-z "${1:-}") || ("${1:0:1}" == "-") ]] ; then
    #  abort $LINENO "switch TARGETS POST rquires a parameter"
    #fi
    if [ "${1:0:1}" == "-" ] ; then  # targets post will be blank if we are syncing from the root web folder
      abort $LINENO "switch TARGETS POST rquires a parameter"
    fi
    switch_targetspost="$1"  # "movies/cartoon"
    shift
    echo "accepted switch TARGETS POST with parameter \"$switch_targetspost\""
  else
    abort $LINENO "encountered unexpected switch \"$1\""
  fi
done
echo "all dashed switches processed"
if [ -n "${1:-}" ] ; then
  # legacy, source provided at end without switch
  switch_source="$1"
  shift
fi
if [ $# != 0 ] ; then
  abort $LINENO "encountered $# unexpected parameters $@"
fi



########################################
##  SUMMARIZE SWITCHES
########################################

echo "SWITCH SUMMARY:"
echo "  switch_dotfiles=\"$switch_dotfiles\""
echo "  switch_dryrun=\"$switch_dryrun\""
echo "  switch_source=\"$switch_source\""
echo "  switch_target=\"$switch_target\""
echo "  switch_targetsfile=\"$switch_targetsfile\""
echo "  switch_targetspost=\"$switch_targetspost\""



########################################
##  CD TO SPECIFIED SOURCE
########################################

if [ -z "$switch_source" ] ; then
  source="$(pwd)"
  echo "using CWD \"$source\" for source"
else
  source="$switch_source"
  cd "$source" || exit
  echo "using specified source \"$source\""
fi



########################################
##  IDENTIFY TARGET
########################################

if [ -n "$switch_target" ] ; then
  # use specified target
  target[0]="$switch_target"
  targets=1
  echo "loading switched target \"${target[0]}\""
else
  # no target specified, load from file
  if ! [ -r "$switch_targetsfile" ] ; then
    abort $LINENO "target no specified and target path file \"$switch_targetsfile\" not found"
  fi
  targets=0
  while read -r target[targets] ; do
    echo "loaded target \"${target[targets]}\""
    ((targets++))
  done < "$switch_targetsfile"
fi



########################################
##  EXTRACT IPS/PORTS
########################################

# example target: root@192.168.1.11:/Volumes/Drive2/www/WebRootFolder
# example target: root@192.168.1.11;222:/Volumes/Drive2/www/WebRootFolder

for ((i=0;i<targets;i++)) ; do
  t=${target[i]}
  echo "starting with target[$i]=\"$t\""
  p=${t#*;}  # 222:/Volumes/Drive2/www/WebRootFolder
  echo "p=\"$p\""
  if [ "$p" == "$t" ] ; then
    # no port specified in this target, use default
    port[i]=22
  else
    # extract and configure nonstandard port
    port[i]=${p%:*}  # 222
    x_left=${t%;*}  # root@192.168.1.11
    x_right=${t#*:}  # /Volumes/Drive2/www/WebRootFolder
    target[i]="${x_left}:${x_right}"
  fi
  #rsh[i]=$(echo "$rsh" | sed "s/:PORT:/${port[i]}/g")
  t=${target[i]}
  rsh[i]=${rsh//:PORT:/${port[i]}}
  x=${t#*@}  # 192.168.1.11:/Volumes/Drive2/www/WebRootFolder
  ip[i]=${x%:*}  # 192.168.1.11
  echo "Target $i :"
  echo "  target: \"${target[i]}\""
  echo "  rsh: \"${rsh[i]}\""
  echo "  ip: \"${ip[i]}\""
  echo "  port: \"${port[i]}\""
done



########################################
##  SELECT FIRST AVAILABLE TARGET
########################################

for ((available=0;available<targets;available++)) ; do
  if ping -q -t "$switch_pingtimeoutsec" -c 1 "${ip[available]}" > /dev/null ; then
    # IP returns pings
    echo "${ip[available]} returns pings, will use target \"${target[available]}\" on port \"${port[available]}\""
    break
  else
    echo "${ip[available]} failed to return pings"
  fi
done
if [ "$available" == "$targets" ] ; then
  abort $LINENO "no available targets"
else
  echo "proceeding with available target"
fi



########################################
##  FINALIZE PARAMETERS
########################################

title=${source##*/}

echo "title  = \"$title\""
echo "source = \"$source\""
echo "target = \"${target[available]}\""

if [ -z "$switch_targetspost" ] ; then
  echo "no targets post provided, will use target specified"
else
  echo "  adding target post \"$switch_targetspost\" to target"
  target[available]="${target[available]}${switch_targetspost}"
  echo "target = \"${target[available]}\""
fi

# escape spaces and parentheses for rsync target
#rsync_target=$(echo "$target" | sed 's/ /\\ /g')  # just spaces
#rsync_target=$(echo "$target" | sed 's/ /\\ /g' | sed 's/(/\\(/g' | sed 's/)/\\)/g')  # escape ' ', '(', and ')'
#rsync_target=$(echo "${target[available]}" | sed 's/ /\\ /g' | sed 's/(/\\(/g' | sed 's/)/\\)/g'  | sed "s/'/\\\'/g")  # escape ' ', '(',  ')', '''
rsync_target=$(echo "${target[available]}" | sed 's/ /\\ /g' | sed 's/(/\\(/g' | sed 's/)/\\)/g' | sed "s/'/\\\'/g" | sed 's/\$/\\\$/g')  # escape ' ', '(', ')', ''', '$'

echo "rsync_target = \"$rsync_target\""
echo



########################################
##  VERIFY SOURCE TITLE IS ALLOWED
########################################

if ! [ "$switch_verify_allow" ] ; then
  echo "not switched to verify allow, skipping step"
else
  if [ -f "$allow_file" ] ; then
    echo "removing local allow file \"$allow_file\""
    rm "$allow_file"
  fi
  echo "fetching allow file with CMD: \"$rsync_app\" -rpt --rsh=\"${rsh[available]}\" \"${target[accessible]}/${allow_file}\" \"${source}/${allow_file}\""
  "$rsync_app" -rpt --rsh="${rsh[available]}" "${target[accessible]}/${allow_file}" "${source}/${allow_file}"
  if ! [ -r "$allow_file" ] ; then
    abort $LINENO "allow file \"$allow_file\" missing on target"
  fi
  allow=$(cat "$allow_file")
  rm "$allow_file"
  if [ "$allow" != "$title" ] ; then
    abort $LINENO "allow file on target \"${target[accessible]}\" contains \"$allow\", which doesn't math this title \"$title\""
  fi
  echo "allow file matches title ($title)"
fi



########################################
##  VERIFY ROOT
########################################

if ! [ $switch_verify_root ] ; then
  echo "not switched to verify root, skipping step"
else
  source_folder=${source##*/}
  t=${target[available]}
  target_folder=${t##*/}
  if [ "$source_folder" != "$target_folder" ] ; then
    abort $LINENO "source folder name \"$source_folder\" doesn't match target folder name \"$target_folder\""
  else
    echo "source and folder name match (\"$source_folder\")"
  fi
fi


#abort $LINENO "STOP"



########################################
##  SYNC
########################################

if [ -e "$do_not_sync_file" ] ; then
  echo " do_not_sync_file found, not syncing to server"
  if [ "$switch_dotfiles" ] ; then
    echo "NOT: \"$rsync_app\" -vrptX --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=\".DS_Store\" \"${source}/\" \"${rsync_target}\""
  else
    echo "NOT: \"$rsync_app\" -vrptX --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=\".*\" \"${source}/\" \"${rsync_target}\""
  fi
else
  echo "do_not_sync_file not found, will sync to server"
  if [ $switch_dryrun ] ; then
    echo "dryrun syncing to server"
    if [ "$switch_dotfiles" ] ; then
      echo "CMD: \"$rsync_app\" rsync -n -vrptX --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=NORSYNC --exclude=\".DS_Store\" \"${source}/\" \"${rsync_target}\""
      "$rsync_app" -n -vrptX --delete --progress --rsh="${rsh[available]}" --rsync-path="$rsync_app" --exclude=NORSYNC --exclude=".DS_Store" "${source}/" "${rsync_target}" | grep -v "/$"  # grep defeats progress
    else
      echo "CMD: \"$rsync_app\" rsync -n -vrptX --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=NORSYNC --exclude=\".*\" \"${source}/\" \"${rsync_target}\""
      "$rsync_app" -n -vrptX --delete --progress --rsh="${rsh[available]}" --rsync-path="$rsync_app" --exclude=NORSYNC --exclude=".*" "${source}/" "${rsync_target}" | grep -v "/$"  # grep defeats progress
    fi
  else
    echo "live syncing to server"
    if [ "$switch_dotfiles" ] ; then
      echo "CMD: \"$rsync_app\" -X -vrpt --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=NORSYNC --exclude=\".DS_Store\" \"${source}/\" \"${rsync_target}\""
      "$rsync_app" -X -vrpt --delete --progress --rsh="${rsh[available]}" --rsync-path="$rsync_app" --exclude=NORSYNC --exclude=".DS_Store" "${source}/" "${rsync_target}" | grep -v "/$"  # grep defeats progress
    else
      echo "CMD: \"$rsync_app\" -X -vrpt --delete --progress --rsh=\"${rsh[available]}\" --rsync-path=\"$rsync_app\" --exclude=NORSYNC --exclude=\".*\" \"${source}/\" \"${rsync_target}\""
      "$rsync_app" -X -vrpt --delete --progress --rsh="${rsh[available]}" --rsync-path="$rsync_app" --exclude=NORSYNC --exclude=".*" "${source}/" "${rsync_target}" | grep -v "/$"  # grep defeats progress
    fi
  fi
fi

echo
echo

echo "DONE at $(date)"
echo






