89 lines
2.5 KiB
Bash
Executable File
89 lines
2.5 KiB
Bash
Executable File
#! /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
|