-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit-mirror.sh
executable file
·88 lines (67 loc) · 2.89 KB
/
git-mirror.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/bin/sh
set -e -o pipefail
DEST_REPO=$1
UPSTREAM_REPO=$2
if [[ -z "${DEST_REPO}" && -z "${UPSTREAM_REPO}" ]]; then
printf "Both destination and source are empty; nothing to be done.\n" >&2
exit 0
fi
if [[ -z "${DEST_REPO}" ]]; then
DEST_REPO="${GITHUB_REPOSITORY}"
fi
if [[ -z "${UPSTREAM_REPO}" ]]; then
UPSTREAM_REPO="${GITHUB_REPOSITORY}"
fi
if [[ "${DEST_REPO}" == "${UPSTREAM_REPO}" ]]; then
printf "Destination and source are the same; nothing to be done.\n" >&2
exit 0
fi
if ! printf ${UPSTREAM_REPO} | grep -Eq ':|@|\.git\/?$'; then
printf "UPSTREAM_REPO does not seem to be a valid git URI, assuming it's a GitHub repo\n" >&2
printf "Originally: %s\n" "${UPSTREAM_REPO}" >&2
if [[ -f "${HOME}/.ssh/src_rsa" ]]; then
UPSTREAM_REPO="[email protected]:${UPSTREAM_REPO}.git"
GIT_SSH_COMMAND="ssh -v"
else
UPSTREAM_REPO="https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${UPSTREAM_REPO}.git"
fi
printf "Now: %s \n" "${UPSTREAM_REPO}" >&2
fi
if ! printf ${DEST_REPO} | grep -Eq ':|@|\.git\/?$'; then
printf "DEST_REPO does not seem to be a valid git URI, assuming it's a GitHub repo\n" >&2
printf "Originally: %s\n" "${DEST_REPO}" >&2
if [[ -f "${HOME}/.ssh/dst_rsa" ]]; then
DEST_REPO="[email protected]:${DEST_REPO}.git"
GIT_SSH_COMMAND="ssh -v"
else
DEST_REPO="https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${DEST_REPO}.git"
fi
printf "Now: %s \n" "${DEST_REPO}" >&2
fi
set -u
mirrordir="${RUNNER_TEMP}/$(basename "${GITHUB_REPOSITORY}")"
mkdir -p "$mirrordir"
cd "$mirrordir"
git init --bare --quiet
printf "Adding upstream %s\n" "${UPSTREAM_REPO}" >&2
git remote add upstream --mirror=fetch "${UPSTREAM_REPO}"
printf "Adding upstream %s\n" "${DEST_REPO}" >&2
git remote add origin --mirror=push "${DEST_REPO}"
git remote --verbose
printf "Getting upstream\n" >&2
git -c core.sshCommand="/usr/bin/ssh -i ~/.ssh/src_rsa" fetch --quiet upstream
printf "Pushing changes from upstream to origin\n" >&2
# check whether the destination looks like a GitHub repository by replacing all
# ':' with '/' so that dirname can be used to strip off the repository and org
# and test against the portion that remains.
if [[ "$(dirname "$(dirname "$(printf "%s" "${DEST_REPO}" | tr ':' '/')")")" =~ 'github.com$' ]]; then
# unset mirror on origin so that refspecs can be used.
git config --unset remote.origin.mirror
# get the refspecs for updating the destination
refspecs=$(git -c core.sshCommand="/usr/bin/ssh -i ~/.ssh/dst_rsa" push --dry-run --porcelain --prune origin '+refs/*:refs/*' | grep '^[- +*!=]' | cut -f 2)
# strip any refspec that would affect a hidden branch (i.e. a pull request ref) in the destination
refspecs="$(printf "%s" "${refspecs}" | grep -v :refs/pull/)"
printf "%s" "${refspecs}" | xargs git -c core.sshCommand="/usr/bin/ssh -i ~/.ssh/dst_rsa" push --force origin
else
git -c core.sshCommand="/usr/bin/ssh -i ~/.ssh/dst_rsa" push origin
fi