#!/bin/sh git_cache() { git -C "${GIT_CACHE_DIR}" $* } init() { set -e local _git_dir="$(git_cache rev-parse --git-dir 2>/dev/null)" [ "$_git_dir" = "." -o "$_git_dir" = ".git" ] || { mkdir -p "${GIT_CACHE_DIR}" git_cache init --bare git_cache config core.compression 1 } set +e } add() { set -e local repo="$1" local name="$(_remote_name $repo)" if ! is_cached "$repo"; then git_cache remote add "$name" "$repo" else echo "git-cache: $url already in cache" fi set +e } update() { set -e local REMOTE=${1:---all} git_cache fetch $REMOTE set +e } is_cached() { set +e local url="$1" local REMOTES="$(git_cache remote show)" for remote in $REMOTES; do [ "$(git_cache ls-remote --get-url $remote)" = "$url" ] && return 0 done set -e return 1 } list() { local REMOTES="$(git_cache remote show)" for remote in $REMOTES; do echo "$(git_cache ls-remote --get-url $remote)" done } drop() { set -e local REMOTE=${1} [ -z "$REMOTE" ] && { echo "usage: git cache drop " exit 1 } local REMOTES="$(git_cache remote show)" for remote in $REMOTES; do [ "$(git_cache ls-remote --get-url $remote)" = "$REMOTE" ] && { git_cache remote remove $remote break } done set +e } _check_commit() { git_cache cat-file -e ${1}^{commit} } _remote_name() { echo "$*" | md5sum | cut -d\ -f1 } clone() { set -e 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 echo "git cache: auto-adding $REMOTE" add "$REMOTE" update "$(_remote_name $REMOTE)" fi fi if _check_commit $2 2>&1; then git_cache tag commit$SHA1 $SHA1 || true # ignore possibly already existing tag git clone --reference "${GIT_CACHE_DIR}" "${GIT_CACHE_DIR}" "${TARGET_PATH}" --branch commit$SHA1 else git clone --reference "${GIT_CACHE_DIR}" "${REMOTE}" "${TARGET_PATH}" git -C "${TARGET_PATH}" checkout $SHA1 fi set +e } 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 " echo " git cache list list cached repositories" echo " git cache drop drop repo from cache" echo " git cache update [] fetch repo (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) ' } [ $# -eq 0 ] && { usage exit 1 } ACTION=$1 shift 1 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