Got some useful clues from local git hook for “git remote update” question.
The idea is to update this repository with git remote update
wrapped into a script that launches the post-receive
hook. remote-update.sh
:
#!/bin/bash
git_dir=$(git rev-parse --git-dir) || exit
cd "$git_dir"
declare -A before after all
# create the 'before' list
while read commit_hash refspec; do
before[$refspec]="$commit_hash"
all[$refspec]=''
done < <(git show-ref --heads)
# do the remote update
git remote update --prune
# create the 'after' list
while read commit_hash refspec; do
after[$refspec]="$commit_hash"
all[$refspec]=''
done < <(git show-ref --heads)
# see if there were any changes, and if so, run the post-receive hook
changes=0
for refspec in "${!all[@]}"; do
[ "${before[$refspec]}" != "${after[$refspec]}" ] && { changes=1; break; }
done
if [ "$changes" == "1" ]; then
none="$(printf "%0.s0" {1..40})" # forty zeroes, or git's "don't care" ref
for refspec in "${!all[@]}"; do
# if the refspec changed, pass it to the post-receive hook
[ "${before[$refspec]}" != "${after[$refspec]}" ] && \
echo "${before[$refspec]:-$none} ${after[$refspec]:-$none} $refspec"
done | GIT_DIR="$git_dir" hooks/post-receive
fi
And since I've got only post-receive
and update
hooks, a partial (because it ignores errors) simulation of the update
hook inside post-receive
can go like that:
#!/bin/bash
while read oldrev newrev refname; do
GIT_DIR="$GIT_DIR" hooks/update "$refname" "$oldrev" "$newrev"
done
Of course it can be done properly and prevent fetching on failures.
Any cleaner solutions?