Skip to content

Instantly share code, notes, and snippets.

@boricj
Created May 24, 2024 21:58
Show Gist options
  • Save boricj/909d3df166af8c5c2fe9fa66bdce8b72 to your computer and use it in GitHub Desktop.
Save boricj/909d3df166af8c5c2fe9fa66bdce8b72 to your computer and use it in GitHub Desktop.
git-proxy-cache
#!/bin/bash
set -e
#
# Git read-only remote cache for SSH.
#
# This script is to be used as a shell for a dedicated Git user. Each time a
# clone/pull is attempted on the cache, it will either:
# * fetch everything from the remote if it has already been cloned, or
# * attempt to clone the remote.
#
# The local repository will then be used as a source to satisfy the request.
# The end-result is a local cache for remote Git repositories which will most
# of the time fetch almost nothing from the remote even if the client makes a
# full clone.
#
ROOT_PATH='/var/lib/git'
BANNER='Git proxy cache server.'
>&2 echo "mirror: $BANNER"
# Expand command line arguments and eat extra quotes
set -- $(echo "$@" | sed -e "s/'//g")
# Eat -c
if [ "$1" == '-c' ]
then
shift 1
fi
if [[ "$1" == 'git-upload-archive' || "$1" == 'git-upload-pack' ]]
then
REPO_URL="${@: -1}"
>&2 echo "mirror: Processing download request of '$REPO_URL'."
# Sanity check the URL.
if [[ "$REPO_URL" =~ \.\. ]]
then
>&2 echo "mirror: error: invalid request $REPO_URL"
exit 1
fi
# Remove leading slash.
if [[ "$REPO_URL" =~ ^/ ]]
then
REPO_URL="${REPO_URL:1}"
fi
# Grab on-disk path by stripping out protocol and username.
REPO_PATH="$ROOT_PATH/$(echo "$REPO_URL" | cut -f3- -d'/' | cut -f2- -d'@' | tr A-Z a-z)"
LOCK_PATH="$(dirname "$REPO_PATH")/.lock.$(basename "$REPO_PATH")"
mkdir -p "$(dirname "$REPO_PATH")"
# Clone or fetch to update the local repository.
if [ ! -d "$REPO_PATH/objects" ]
then
>&2 echo "mirror: Cloning from remote $REPO_URL"
flock "$LOCK_PATH" git clone --progress --mirror "$REPO_URL" "$REPO_PATH"
>&2 echo "mirror: Cloning done."
else
>&2 echo "mirror: Fetching from remote $(cd "$REPO_PATH" && git remote get-url origin)"
(cd "$REPO_PATH" && flock "$LOCK_PATH" git fetch --append) >/dev/null
>&2 echo "mirror: Fetching done."
fi
# Local repository is up to date, serve request from it.
>&2 echo "mirror: Running command: $1 $REPO_PATH"
exec "$1" "$REPO_PATH"
elif [ "$1" == git-receive-pack ]
then
>&2 echo "mirror: error: This is a read-only Git cache, upload request denied."
else
>&2 echo "mirror: error: Unknown command '$1'."
fi
# If we get here then we failed.
exit 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment