#! /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