Last active
January 21, 2018 04:03
-
-
Save jodersky/19f81db9feeb8b8a778298eb065d084a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Manage a collection of github mirrors. | |
# | |
# This script provides functionality to clone and update git | |
# repositories as mirrors. The update functionality is silent on | |
# successful updates and is designed to be called in an automated way, | |
# such as with cron. | |
# | |
# All mirror repositories are assumed to be contained under one base | |
# directory (by default ~/public_git), configurable via a flag. | |
set -o errexit | |
print_usage() { | |
echo "git mirror [--base=<base_dir>] [update [repo...]]" | |
echo "git mirror [--base=<base_dir>] clone <url>" | |
} | |
opts=$(getopt -o hb: --long help,base: -n 'git-mirror' -- "$@") | |
eval set -- "$opts" | |
base_dir="$HOME/public_git" | |
action="update" | |
urls=() | |
repo_dirs=() | |
while true; do | |
case "$1" in | |
-h|--help) print_usage; exit 0 ;; | |
-b|--base) | |
shift | |
base_dir="$1" | |
shift | |
;; | |
--) shift; break ;; | |
*) echo "Option parse error"; exit 1; ;; | |
esac | |
done | |
while true; do | |
case "$1" in | |
update|"") | |
action="update" | |
if [[ "$#" -gt 1 ]]; then | |
shift | |
for repo_name in "$@"; do | |
repo_dirs+=("$base_dir/$repo_name") | |
done | |
else | |
while IFS= read -r -d '' repo_dir; do | |
repo_dirs+=("$repo_dir") | |
done < <(find "$base_dir" -maxdepth 1 -type d -name '*.git' -print0) | |
fi | |
break | |
;; | |
clone) | |
action="clone" | |
[ "$#" -gt 1 ] || (print_usage ; exit 1) | |
shift | |
urls=("$@") | |
break | |
;; | |
*) | |
print_usage | |
exit 1 | |
esac | |
done | |
update_mirror() { | |
local repo_dir="$1" | |
local repo_url | |
repo_url=$(git --git-dir="$repo_dir" config --get remote.origin.url) | |
# Fetch from remote and update upstream refs | |
git --git-dir="$repo_dir" remote update --prune > /dev/null | |
# Get additional information for certain upstream repos | |
local host | |
host=$(echo "$repo_url" \ | |
| sed -n --regexp-extended 's|https?://([^/]*).*|\1|p') | |
case "$host" in | |
github.com) | |
local slug | |
slug=$(echo "$repo_url" \ | |
| perl -pe 's|^https?://github.com/(.*?)(\.git)?$|\1|p') | |
local username | |
username=$(echo "$slug" | sed -nr 's|([^/]*)/.*|\1|p') | |
local repo | |
repo=$(echo "$slug" | sed -nr 's|[^/]*/(.*)|\1|p') | |
curl --silent --show-error \ | |
"https://api.github.com/repos/$username/$repo" \ | |
| jq .description --raw-output > "$repo_dir/description" | |
;; | |
*) | |
;; | |
esac | |
} | |
case "$action" in | |
update) | |
for repo_dir in "${repo_dirs[@]}"; do | |
update_mirror "$repo_dir" || echo "Error updating $repo_dir" >&2 | |
done | |
;; | |
clone) | |
for repo_url in "${urls[@]}"; do | |
git -C "$base_dir" clone --mirror "$repo_url" | |
done | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment