#!/bin/bash GIT_SYNCD_CONFIG_DIR=${GIT_SYNCD_CONFIG_DIR:-"$HOME/.config/git-sync"} GIT_SYNCD_CONFIG=${GIT_SYNCD_CONFIG:-"$GIT_SYNCD_CONFIG_DIR/syncd.rc"} git_syncd=$0 git_syncd_repos=() # auto sync exclude regex pattern declare -g -A git_syncd_exclude=() # maximum time seconds between fetching changes and syncing git_syncd_default_sync_timeout=600 declare -g -A git_syncd_sync_timeout=() # number of seconds to wait after deteced change to push git_syncd_default_sync_delay=300 declare -g -A git_syncd_sync_delay=() sync() { echo "starting sync.." cd "$repo" && git-sync -n -s || notify-send "Sync failed for $repo" } watcher() { repo=$1 echo $repo ${git_syncd_exclude[@]} ${git_syncd_exclude[$repo]} exclude=${git_syncd_exclude[$repo]:-'\.git'} sync_delay=${git_syncd_sync_delay[$repo]:-$git_syncd_default_sync_delay} sync_timeout=${git_syncd_sync_timeout[$repo]:-$git_syncd_default_sync_timeout} sync "$repo" timeout=$sync_timeout while true; do if [ ! -e "$repo" ]; then echo "Repo does not exist" echo "sleeping (${timeout}s)" sleep $timeout continue fi echo "watching (${timeout}s)" file=$(timeout "$timeout" wd "$repo" inotifywait "." -r \ -e modify,move,create,delete --exclude "$exclude" 2>/dev/null) rc=$? if [ ! -z "$file" ]; then echo "inotify wake: $file" timeout=$sync_delay elif [ $rc -eq 124 ]; then sync "$repo" timeout=$sync_timeout fi sleep 1 done } log_prefix() { repo="$1" repo_name=$(basename "$repo") repo_dir_name=$(basename $(dirname "$repo")) while read -r line; do prefix="$(date "+%Y-%m-%d %T")" #$repo_dir_name/$repo_name" prefix="$(echo "$prefix" | tr -d "\"" | tr -d "'")" echo "[$prefix] $line" done } kill_all() { pkill -A -9 git-syncd } git_syncd_watchers=() kill_watchers() { kill_all return fail=0 for pid in "${git_syncd_watchers[@]}"; do echo "killing $pid.." >&2 pkill -P "$pid" &>/dev/null waitpid -t 10 "$pid" &>/dev/null kill -0 -P "$pid" &>/dev/null && notify-send "Failed to kill git-syncd watcher" && fail=1 done [ $fail -ne 0 ] && exit 1 git_syncd_watchers=() } start_watchers() { for repo in "${git_syncd_repos[@]}"; do echo "watching '$repo'.." $git_syncd watch "$repo" & sleep 1 # wait a bit git_syncd_watchers+=($!) done } load_config() { git_syncd_repos=() declare -g -A git_syncd_exclude=() declare -g -A git_syncd_sync_delay=() declare -g -A git_syncd_sync_timeout=() if [ -e "$GIT_SYNCD_CONFIG" ]; then echo "sourcing '$GIT_SYNCD_CONFIG'.." source "$GIT_SYNCD_CONFIG" fi } if [ "$1" = "watch" ]; then shift repo="$1"; shift repo_dir_name="$(basename $(dirname "$repo"))" repo_name="$(basename "$repo")" log_path="$HOME/.log/git-sync/$repo_dir_name" mkdir -p "$log_path" load_config watcher "$repo" 2>&1 | log_prefix "$repo" > "$log_path/$repo_name" exit fi load_config trap kill_all EXIT start_watchers while true; do file=$(inotifywait --format "%w%f" -e modify,delete "$GIT_SYNCD_CONFIG") if [ ! -z "$file" ]; then mod_path="$(realpath "$file" 2>/dev/null)" config_path="$(realpath "$GIT_SYNCD_CONFIG" 2>/dev/null)" echo "config $mod_path $config_path" if [ "$mod_path" = "$config_path" -o "$mod_path" = "$config_path~" ]; then kill_watchers load_config start_watchers fi fi sleep 2 done