#!/bin/bash # Version: 0.1.0 # Copyright (c) 2023: # Darren 'Tadgy' Austin # Licensed under the terms of the GNU General Public License version 3. # # Automatically fetch and merge (if possible) upstream changes into a local git repository. # What platform we're running on. PLATFORM="$(uname -s)" # Only operate on repositories that are set for maintenance work in ~/.gitconfig. while IFS= read -r REPO; do # Get into the working directory. pushd "$REPO" >/dev/null 2>&1 || { printf "%s: %s\\n" "${0##*/}" "failed to change to working directory '$REPO'" >&2 RET=1 continue } # Skip processing if auto-merging is disabled in this repository. [[ "$(git config --local --get --type bool script.AutoMergeDisabled 2>/dev/null)" != "true" ]] && { # Fetch the latest updates. if git fetch --all --atomic --tags >/dev/null 2>&1; then # Try to merge using fast-forward only, so no clobbering is done. if MERGE="$(git merge --ff-only 2>/dev/null)"; then [[ "$(printf "%s" "$MERGE" | awk '{ print $1; exit }')" == "Updating" ]] && { if [[ "$PLATFORM" == "Linux" ]]; then # Linux, how I love thee. NOW="$(date +'%s%3N')" elif [[ "$PLATFORM" == "Darwin" ]]; then # This sucks... but so does Darwin. NOW="$(perl -e 'use Time::HiRes; printf "%.3f", Time::HiRes::time();')" NOW="${NOW/.}" else printf "%s: %s\\n" "${0##*/}" "unsupported platform: $PLATFORM" >&2 RET=2 break fi git config --local --replace-all --type int script.AutoMergeLast "$NOW" >/dev/null 2>&1 || { printf "%s: %s\\n" "${0##*/}" "updating AutoMergeLast timestamp failed for '$REPO'" >&2 RET=1 } git config --local --replace-all --type bool script.AutoMergeSuccess true >/dev/null 2>&1 || { printf "%s: %s\\n" "${0##*/}" "updating AutoMergeSuccess marker failed for '$REPO'" >&2 RET=1 } } else git config --local --replace-all --type bool script.AutoMergeSuccess false >/dev/null 2>&1 || { printf "%s: %s\\n" "${0##*/}" "updating AutoMergeSuccess marker failed for '$REPO'" >&2 RET=1 } fi else # Mark that the auto-merge failed. printf "%s: %s\\n" "${0##*/}" "git fetch failed for '$REPO'" >&2 git config --local --replace-all --type bool script.AutoMergeSuccess false >/dev/null 2>&1 || { printf "%s: %s\\n" "${0##*/}" "updating AutoMergeSuccess marker failed for '$REPO'" >&2 RET=1 } fi } # Back to where we started... popd >/dev/null 2>&1 || continue done < <(git config --global --get-all maintenance.repo 2>/dev/null) exit "${RET:-0}"