Skip to content

Instantly share code, notes, and snippets.

@brodygov
Created May 17, 2018 02:42
Show Gist options
  • Save brodygov/668bd6041610ac1426022d5b6f82b323 to your computer and use it in GitHub Desktop.
Save brodygov/668bd6041610ac1426022d5b6f82b323 to your computer and use it in GitHub Desktop.
Mirror a git repository under an archival github user's account
#!/bin/bash
set -eu
ARCHIVE_USER="${ARCHIVE_USER-my-archive-user}"
ssh_key="$HOME/.ssh/key.mirror-repo"
usage() {
cat >&2 <<EOM
usage: $(basename "$0") [options] SOURCE_REPO DEST_NAME
SOURCE_REPO: the source repository to copy just <ORG/REPO>, no host
DEST_NAME: the destination repository under $ARCHIVE_USER
Set \$ARCHIVE_USER to the user account where all the repos will be mirrored.
Repos will be cloned under repos/<DATE>/ and not removed afterwards
set DATE=YYYY-MM-DD to override the date used
Github repo creation expects a github.netrc file at repo root:
machine api.github.com login <ARCHIVE_USER> password <PASSWORD-OR-AUTH-TOKEN>
options:
--up: mirror up an existing repo
--no-up: skip upload step
--no-github-ssh: don't automatically use ssh for github.com
--no-create-repo: don't automatically create the repo
--ssh-key KEY: use KEY instead of default $ssh_key
example:
$(basename "$0") someorg/demo f025-someorg-demo
EOM
}
echo_red() {
echo -en '\033[1;31m'
echo -n "$*"
echo -e '\033[m'
}
echo_blue() {
echo -en '\033[1;34m'
echo -n "$*"
echo -e '\033[m'
}
run() {
echo >&2 "+ $*"
"$@"
}
netrc_file="$(dirname "$0")/../github.netrc"
upload=
skip_upload=
github_auto=1
create_repo=1
while [ $# -gt 0 ]; do
case "$1" in
--up)
upload=1
;;
--no-up)
skip_upload=1
;;
--no-github-ssh)
github_auto=
;;
--no-create-repo)
create_repo=
;;
--ssh-key)
ssh_key="$2"
shift
;;
-*)
usage
echo >&2 "Unknown option: $1"
exit 2
;;
*)
break
;;
esac
shift
done
if [ $# -lt 2 ]; then
usage
exit 1
fi
src="$1"
dst="$2"
if [[ $src != *:* ]]; then
echo "Assuming $src is from github.com"
src="[email protected]:$src"
fi
orig_src="$1"
if [[ $github_auto ]]; then
if [[ $src == https://github.com/* ]]; then
echo "Rewriting $src to be SSH / [email protected]"
src="[email protected]:${src:19}"
echo "New URL: $src"
fi
if [[ $dst == https://github.com/$ARCHIVE_USER/* ]]; then
echo "Rewriting $dst to be just basename"
dst="$(basename "$dst")"
fi
fi
if [ ! -e "$ssh_key" ]; then
run ssh-keygen -t rsa -f "$ssh_key"
echo "Generated a new key in $ssh_key"
echo "Please add this key to the $ARCHIVE_USER account"
echo "https://github.com/settings/keys"
cat "$ssh_key"
exit 1
fi
export GIT_SSH_COMMAND="ssh -o identitiesonly=yes -i $ssh_key"
echo_blue "Mirroring..."
echo_blue "from:"
echo_blue " - $src"
echo_blue "to:"
echo_blue " - https://github.com/$ARCHIVE_USER/$dst"
date="${DATE-$(date +%F)}"
cd "$(dirname "$0")/.."
mkdir -vp "repos/$date"
cd "repos/$date"
echo_blue "cloning into $PWD/$dst"
if [ -e "$dst" ]; then
if [ -n "$upload" ]; then
echo "$dst already exists, uploading"
else
echo "$dst already exists, aborting. Pass --up to use existing"
exit 3
fi
else
run git clone --mirror "$src" "$dst"
fi
if [[ $skip_upload ]]; then
echo_blue "--no-up passed, not creating dst repo or uploading"
exit
fi
cd "$dst"
if [[ $create_repo ]]; then
echo_blue "Checking for dst repo existence"
if [ ! -e "$netrc_file" ]; then
echo >&2 "netrc file does not exist: $netrc_file"
echo >&2 "Pass --no-create-repo to skip github API operations"
exit 4
fi
if run curl -sSf --netrc-file "$netrc_file" \
"https://api.github.com/repos/$ARCHIVE_USER/$dst" >/dev/null
then
echo_blue "Repo already exists"
else
echo_blue "Creating target repo"
# create target repo
run curl -sSf --netrc-file "$netrc_file" -d '@-' \
https://api.github.com/user/repos >/dev/null <<EOM
{"name":"$dst", "private":true, "description": "Mirror of $orig_src"}
EOM
sleep 1
fi
else
echo_blue "Skipping repo creation"
fi
if ! run git remote get-url archive >/dev/null; then
run git remote add archive "[email protected]:$ARCHIVE_USER/$dst"
fi
run git push --mirror archive && ret=$? || ret=$?
echo_blue "Done."
echo_blue "https://github.com/$ARCHIVE_USER/$dst"
exit $ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment