#!/usr/bin/env sh # # Keeps a git directory synced by automatically committing every x seconds. # After y number of runs without changes automatically pushes the directory to a remote. # time in seconds to check for changes to commit TIME_TO_COMMIT=${GS_TIME_TO_COMMIT:-120} # amount of times to check for changes *without changes occurring* to push to origin UNCHANGED_RUNS_TO_PUSH=${GS_UNCHANGED_RUNS_TO_PUSH:-30} # logging verbosity level -- 0=error, 1=info, 2=debug VERBOSITY=${GS_LOG_VERBOSITY:-1} set_target() { [ -z "$GS_TARGETDIR" ] && [ -z "$1" ] && { msg "ERROR: git-sync requires a target directory to keep in sync to be passed in." 0 exit 1 } DIR="${GS_TARGETDIR:-$1}" } pull() { msg "Pulling upstream changes into $DIR" run_git pull --ff-only --ff } commit() { msg "Committing changes to $DIR" run_git add . # shellcheck disable=2039 run_git commit --no-gpg-sign -m "Git sync: $(date +%F_%R) from ${HOSTNAME:-"${HOST:-undefined}"}" } push() { msg "No changes for $((UNCHANGED_RUNS_TO_PUSH * TIME_TO_COMMIT)) seconds, pushing to origin" run_git push } should_commit() { if [ "$(run_git diff-files --name-only | wc -l)" -eq 0 ]; then msg "No changes to commit in $DIR" 2 false else msg "Found changes to commit in $DIR" 2 true fi } should_push() { if [ "$no_change_cycle" -ge "$UNCHANGED_RUNS_TO_PUSH" ]; then true else false fi } should_pull() { run_git fetch # shellcheck disable=1083 if [ "$(run_git rev-parse HEAD)" = "$(run_git rev-parse @{u})" ]; then false else true fi } run_git() { git -C "$DIR" "$@" } # echos its first argument # verbosity level optionally set through second argument # default verbosity 1 (info), can be set to 2 (debug), or 0 (error) msg() { lvl=${2:-1} [ "$lvl" -gt "$VERBOSITY" ] && return 0 echo "$1" } watch_changes() { no_change_cycle=0 while true; do if should_pull; then pull fi if should_commit; then commit no_change_cycle=0 fi if should_push; then push no_change_cycle=-9999 fi msg "No changes for $((no_change_cycle * TIME_TO_COMMIT)) of $((UNCHANGED_RUNS_TO_PUSH * TIME_TO_COMMIT)) seconds, going back to sleep for $((TIME_TO_COMMIT)) seconds." 2 no_change_cycle=$((no_change_cycle + 1)) sleep "$TIME_TO_COMMIT" done } main() { set_target "$1" watch_changes } main "$1"