From dfad67c00dedf9c6bcba697e9021e9023170e00b Mon Sep 17 00:00:00 2001 From: tv Date: Tue, 30 Jun 2015 00:15:03 +0200 Subject: fetchgit -> prefetch --- bin/prefetch | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100755 bin/prefetch (limited to 'bin/prefetch') diff --git a/bin/prefetch b/bin/prefetch new file mode 100755 index 000000000..a87dd1899 --- /dev/null +++ b/bin/prefetch @@ -0,0 +1,88 @@ +#! /bin/sh +# +# usage: prefetch repo_name out_link +# +# Make the specified repository available as out_link. +# +set -euf + +repo_name=$1 +out_link=$2 + +if test "$repo_name" != nixpkgs; then + echo "prefetch: cannot fetch $repo_name, yet" >&2 + exit -1 +fi + +git_rev=$(nixos-query nixpkgs.rev) +git_url=$(nixos-query nixpkgs.url) +dirty=$(nixos-query nixpkgs.dirty) + +case $dirty in true) + ln -snf "$git_url" "$out_link" + echo "prefetch: using $git_url as it is" >&2 + exit +esac + +# Put all bases in the same place as out_link. +# Notice how out_link must not clash with cache_dir and work_dir. +cache_base=$(dirname "$out_link") +work_base=$(dirname "$out_link") + +# cache_dir points to a (maybe non-existent) directory, where a shared cache of +# the repository should be maintained. The shared cache is used to create +# multiple working trees of the repository. +cache_dir=$cache_base/$(echo "$git_url" | urlencode) + +# work_dir points to a (maybe non-existent) directory, where a specific +# revision of the repository is checked out. +work_dir=$work_base/$(echo "$git_rev" | urlencode) + +cache_git() { + git --git-dir="$cache_dir" "$@" +} + +work_git() { + git -C "$work_dir" "$@" +} + +is_up_to_date() { + test -d "$cache_dir" && + test -d "$work_dir" && + test "$(cache_git rev-parse --verify "$git_rev")" = "$git_rev" && + test "$(work_git rev-parse --verify HEAD)" = "$git_rev" +} + +# Notice how the remote name "origin" has been chosen arbitrarily, but must be +# kept in sync with the default value of nixpkgs.rev. +if ! is_up_to_date; then + if ! test -d "$cache_dir"; then + mkdir -p "$cache_dir" + cache_git init --bare + fi + if ! cache_git_url=$(cache_git config remote.origin.url); then + cache_git remote add origin "$git_url" + elif test "$cache_git_url" != "$git_url"; then + cache_git remote set-url origin "$git_url" + fi + cache_git fetch origin + if ! test -d "$work_dir"; then + git clone -n --shared "$cache_dir" "$work_dir" + fi + commit_name=$(cache_git rev-parse --verify "$git_rev") + work_git checkout "$commit_name" -- "$(readlink -f "$work_dir")" + work_git checkout -q "$commit_name" + work_git submodule init + work_git submodule update +fi +work_git clean -dxf + +# Relative links are nicer, and actually we know that work_dir and out_link are +# the same. But, for robustness, check anyway.. :) +if test "$(dirname "$work_dir")" = "$(dirname "$out_link")"; then + ln -snf "$(basename "$work_dir")" "$out_link" +else + ln -snf "$work_dir" "$out_link" +fi + +echo "prefetch: using $git_url $(work_git log --oneline -n1)" >&2 -- cgit v1.2.3