#!/bin/sh git_cache() { git -C "${GIT_CACHE_DIR}" $* } init() { set -ex local _git_dir="$(git_cache rev-parse --git-dir 2>/dev/null)" test "$_git_dir" == "." -o "$_git_dir" == ".git" || { mkdir -p "${GIT_CACHE_DIR}" git_cache init --bare git_cache config core.compression 1 } set +ex } add() { set -ex if [ $# -eq 1 ]; then local repo="$1" local name="$(_remote_name $repo)" else local repo="$1" local name="$2" fi if ! is_cached "$repo"; then git_cache remote add "$name" "$repo" else echo "git-cache: $url already in cache" fi set +ex } update() { set -ex local REMOTE=${1:---all} git_cache fetch $REMOTE set +ex } is_cached() { set +ex local url="$1" local REMOTES="$(git_cache remote show)" for remote in $REMOTES; do test "$(git_cache remote get-url $remote)" == "$url" && return 0 done set -ex return 1 } list() { local REMOTES="$(git_cache remote show)" for remote in $REMOTES; do echo "${remote}: $(git_cache remote get-url $remote)" done } drop() { set -ex local REMOTE=${1} [ -z "$REMOTE" ] && { echo "usage: git cache drop " exit 1 } git_cache remote remove $REMOTE set +ex } _check_commit() { git_cache cat-file -e ${1}^{commit} } _remote_name() { basename "$*" .git } clone() { set -ex local REMOTE="${1}" local SHA1="${2}" local REMOTE_NAME="$(_remote_name $REMOTE)" local TARGET_PATH="${3:-${REMOTE_NAME}}" if [ "$GIT_CACHE_AUTOADD" == "1" ]; then if ! is_cached "$REMOTE"; then add "$REMOTE" update "$(_remote_name $REMOTE)" fi fi if _check_commit $2 2>&1; then git init "${TARGET_PATH}" git_cache tag commit$SHA1 $SHA1 || true # ignore possibly already existing tag git -C "${TARGET_PATH}" fetch --tags --depth=1 "${GIT_CACHE_DIR}" refs/tags/commit$SHA1 git -C "${TARGET_PATH}" checkout FETCH_HEAD else git clone "${REMOTE}" "${TARGET_PATH}" git -C "${TARGET_PATH}" checkout $SHA1 fi set +ex } usage() { echo "git cache uses a bare git repository containing all objects from multiple" echo "upstream git repositories." echo "" echo "usage:" echo "" echo " git cache init initialize git cache" echo " git cache add [] add repository with name " echo " (if no name given, use \"basename $url .git\"" echo " git cache list list cached repositories" echo " git cache drop drop repo from cache" echo " git cache update [] fetch repo named (or all)" echo " git cache clone clone repository from cache" echo " git cache show-path print's the path that can be used as " echo " '--reference' parameter" echo "" echo "To retrieve objects from cache (will use remote repository if needed):" echo ' git clone --reference $(git cache show-path) ' } ACTION=$1 shift export GIT_CACHE_DIR=${GIT_CACHE_DIR:-${HOME}/.gitcache} case $ACTION in init) init $* ;; add) add $* ;; update) update $* ;; list) list $* ;; drop) drop $* ;; show-path) echo ${GIT_CACHE_DIR} ;; clone) clone $* ;; *) usage ;; esac