2019-11-06 13:47:23 +01:00
|
|
|
#!/bin/bash
|
2019-11-06 13:49:54 +01:00
|
|
|
|
|
|
|
# git-mirror: Mirror a git repo in leader-followers configuration
|
|
|
|
# Copyright © 2019 Midgard
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify it under the terms of the
|
|
|
|
# GNU Affero General Public License as published by the Free Software Foundation, either version 3
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
|
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
# Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License along with this program.
|
|
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2019-11-06 13:47:23 +01:00
|
|
|
set -euo pipefail
|
|
|
|
IFS=$'\n'
|
|
|
|
|
2020-09-15 12:06:33 +02:00
|
|
|
tor=true
|
|
|
|
if [[ "$1" == "--notor" ]]; then
|
|
|
|
tor=false
|
|
|
|
shift 1
|
|
|
|
fi
|
|
|
|
|
2020-09-15 12:17:36 +02:00
|
|
|
if [[ $# -lt 3 ]]; then
|
|
|
|
echo "Usage: $0 [--notor] <workdir> <leader> <follower...>"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2019-11-06 13:47:23 +01:00
|
|
|
cd "$1"
|
|
|
|
|
|
|
|
leader="$2"
|
|
|
|
shift 2
|
|
|
|
followers=( "$@" )
|
|
|
|
|
|
|
|
echo "Working directory: $PWD"
|
|
|
|
echo "Leader remote: $leader"
|
|
|
|
echo "Follower remotes: ${followers[*]}" | tr '\n' ' '
|
|
|
|
echo; echo
|
|
|
|
|
2020-09-15 12:06:33 +02:00
|
|
|
if [[ $tor == true ]]; then
|
|
|
|
torify git fetch --prune --multiple "$leader"
|
|
|
|
else
|
|
|
|
git fetch --prune --multiple "$leader"
|
|
|
|
fi
|
2019-11-06 13:47:23 +01:00
|
|
|
git fetch --prune --multiple "${followers[@]}"
|
|
|
|
echo
|
|
|
|
|
|
|
|
echo "Leader remote information:"
|
|
|
|
git remote show -n "$leader"
|
|
|
|
echo
|
|
|
|
echo "Follower remotes information:"
|
|
|
|
git remote show -n "${followers[@]}"
|
|
|
|
echo
|
|
|
|
|
|
|
|
branches=( $(git show-ref | sed -n 's| refs/remotes/'"$leader"'/|\t|p') )
|
|
|
|
echo -e "${#branches[*]} branches at leader:"
|
|
|
|
echo "${branches[*]}"
|
|
|
|
|
|
|
|
IFS=$'\t'
|
|
|
|
|
|
|
|
errors=( )
|
|
|
|
|
|
|
|
error() {
|
|
|
|
echo "XXX $1" >&2
|
|
|
|
errors[${#errors[*]}]="$1"
|
|
|
|
}
|
|
|
|
|
2019-11-06 14:08:47 +01:00
|
|
|
ref_exists() {
|
|
|
|
git show-ref --verify --quiet "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
is_ref_at_sha() {
|
|
|
|
sha1="$(git show-ref --verify --hash "$1")"
|
|
|
|
sha2="$2"
|
|
|
|
[[ $sha1 == $sha2 ]]
|
|
|
|
}
|
|
|
|
|
2019-11-06 13:47:23 +01:00
|
|
|
for branchspec in "${branches[@]}"; do
|
|
|
|
set $branchspec
|
|
|
|
leader_sha="$1"
|
|
|
|
branch="$2"
|
2022-05-21 01:43:42 +02:00
|
|
|
if [ "$branch" = HEAD ]; then continue; fi
|
2019-11-06 13:47:23 +01:00
|
|
|
|
|
|
|
for remote in "${followers[@]}"; do
|
|
|
|
echo
|
|
|
|
echo "Updating $remote/$branch"
|
|
|
|
|
|
|
|
follower_ref="refs/remotes/$remote/$branch"
|
2019-11-06 14:08:47 +01:00
|
|
|
|
|
|
|
if ! ref_exists "$follower_ref"; then
|
2019-11-06 14:11:11 +01:00
|
|
|
echo "Branch doesn't yet exist at remote, creating"
|
2022-05-21 01:43:42 +02:00
|
|
|
git checkout "$leader_sha" --
|
2019-11-06 14:08:47 +01:00
|
|
|
git push "$remote" "+HEAD:$branch" || { error "$remote $branch: failed to push"; continue; }
|
|
|
|
|
|
|
|
elif is_ref_at_sha "$follower_ref" "$leader_sha"; then
|
2019-11-06 14:11:11 +01:00
|
|
|
echo "Already up to date"
|
2019-11-06 14:08:47 +01:00
|
|
|
|
2019-11-06 13:47:23 +01:00
|
|
|
else
|
2019-11-06 14:11:11 +01:00
|
|
|
echo "Branch exists at remote, updating"
|
2022-05-21 01:43:42 +02:00
|
|
|
git checkout "$follower_ref" --
|
2019-11-06 13:47:23 +01:00
|
|
|
git merge --ff-only "$leader_sha" || { error "$remote $branch: FF not possible"; continue; }
|
2019-11-06 14:08:47 +01:00
|
|
|
git push "$remote" "+HEAD:$branch" || { error "$remote $branch: failed to push"; continue; }
|
2019-11-06 13:47:23 +01:00
|
|
|
fi
|
|
|
|
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
2019-11-06 13:55:51 +01:00
|
|
|
echo
|
|
|
|
if [[ "${#errors[*]}" -gt 0 ]]; then
|
2019-11-06 13:47:23 +01:00
|
|
|
echo "Errors:"
|
|
|
|
echo "${errors[@]}"
|
|
|
|
else
|
|
|
|
echo "No errors."
|
|
|
|
fi
|