From 772657253f5073e8cf3f1b902a7eab83663810b6 Mon Sep 17 00:00:00 2001
From: Kaspar Schleiser <kaspar@schleiser.de>
Date: Sun, 20 Mar 2016 12:40:20 +0100
Subject: [PATCH] dist: tools: add git-cache

---
 Makefile.include         |   2 +
 Makefile.vars            |   1 +
 dist/tools/git/README.md |  21 +++++++
 dist/tools/git/git-cache | 121 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 dist/tools/git/README.md
 create mode 100755 dist/tools/git/git-cache

diff --git a/Makefile.include b/Makefile.include
index 4decf6ed66..2e88239992 100644
--- a/Makefile.include
+++ b/Makefile.include
@@ -20,6 +20,8 @@ RIOTPKG ?= $(RIOTBASE)/pkg
 RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd)
 RIOTPROJECT := $(abspath $(RIOTPROJECT))
 
+GITCACHE:=$(RIOTBASE)/dist/tools/git/git-cache
+
 # Include Docker settings near the top because we need to build the environment
 # command line before some of the variable origins are overwritten below when
 # using abspath, strip etc.
diff --git a/Makefile.vars b/Makefile.vars
index d9de961a43..d7d4c7654f 100644
--- a/Makefile.vars
+++ b/Makefile.vars
@@ -43,6 +43,7 @@ export SIZE                  # The command to read to size of the ELF sections.
 export UNDEF                 # Set by the BOARD's and CPU's Makefile.include, this contains object files with must not be used in the ELFFILE even if the if no call to the functions.
 export WERROR                # Treat all compiler warnings as errors if set to 1 (see -Werror flag in GCC manual)
 
+export GITCACHE              # path to git-cache executable
 export FLASHER               # The command to call on "make flash".
 export FFLAGS                # The parameters to supply to FLASHER.
 export TERMPROG              # The command to call on "make term".
diff --git a/dist/tools/git/README.md b/dist/tools/git/README.md
new file mode 100644
index 0000000000..430b5d890b
--- /dev/null
+++ b/dist/tools/git/README.md
@@ -0,0 +1,21 @@
+# Overview
+
+This directory contains some git tools used by RIOT's build system
+
+## git-cache
+
+Simple git caching script, from https://github.com/kaspar030/git-cache
+If git-cache is unconfigured, the script pulls from the given remote location.
+
+In order to set up the cache, do:
+
+- install the git-cache binary into path.
+  This will make the script available as "git cache ...".
+  Alternatively, directly execute it.
+- run "git cache init", which initializes a git cache in ${HOME}/.gitcache.
+  The used path can be overridden using the "GIT_CACHE_DIR" environment
+  variable.
+  The cache repository will be used to cache multiple remote repositories.
+- add a repository to the cache: "git cache add \<name\> \<URL\>
+- whenever needed (at least once after adding a repository),
+  run "git cache update"
diff --git a/dist/tools/git/git-cache b/dist/tools/git/git-cache
new file mode 100755
index 0000000000..7dc7a6cadb
--- /dev/null
+++ b/dist/tools/git/git-cache
@@ -0,0 +1,121 @@
+#!/bin/sh
+
+git_cache() {
+    git -C "${GIT_CACHE_DIR}" $*
+}
+
+init() {
+    set -ex
+    test -d "${GIT_CACHE_DIR}/.git" || {
+        mkdir -p "${GIT_CACHE_DIR}"
+
+        git_cache init --bare
+        git_cache config core.compression 1
+    }
+    set +ex
+}
+
+add() {
+    set -ex
+    git_cache remote add $1 $2
+    set +ex
+}
+
+update() {
+    set -ex
+    local REMOTE=${1:---all}
+    git_cache fetch $REMOTE
+    set +ex
+}
+
+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 <name>"
+        exit 1
+    }
+    git_cache remote remove $REMOTE
+    set +ex
+}
+
+_check_commit() {
+    git_cache cat-file -e ${1}^{commit}
+}
+
+clone() {
+    set -ex
+    local REMOTE="${1}"
+    local SHA1="${2}"
+    local REMOTE_NAME="$(basename $REMOTE)"
+    local TARGET_PATH="${3:-${REMOTE_NAME}}"
+
+    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 --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 <name> <url>    add repository <url> with name <name>"
+    echo "    git cache list                list cached repositories"
+    echo "    git cache drop <name>         drop repo from cache"
+    echo "    git cache update [<name>]     fetch repo named <name> (or all)"
+    echo "    git cache clone <url> <SHA1>  clone repository <url> 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) <repo>'
+}
+
+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
-- 
GitLab