138 lines
3.2 KiB
Plaintext
138 lines
3.2 KiB
Plaintext
|
|
#!/bin/sh
|
|||
|
|
set -eu
|
|||
|
|
|
|||
|
|
name="fetchpijul"
|
|||
|
|
remote=
|
|||
|
|
channel="main"
|
|||
|
|
change=
|
|||
|
|
state=
|
|||
|
|
exp_hash=
|
|||
|
|
|
|||
|
|
usage() {
|
|||
|
|
echo "Usage: nix-prefetch-pijul [options] [REMOTE] [STATE [EXPECTED-HASH]]"
|
|||
|
|
echo
|
|||
|
|
echo "Options:"
|
|||
|
|
echo " --name <NAME> Symbolic store path name to use for the result."
|
|||
|
|
echo " --remote <REMOTE> URL for the Pijul repository."
|
|||
|
|
echo " --change <CHANGE> Clone a specific change."
|
|||
|
|
echo " --state <STATE> Clone a specific state."
|
|||
|
|
echo " --channel <CHANNEL> Channel name (default: ‘main’)."
|
|||
|
|
echo " --hash <HASH> Expected hash."
|
|||
|
|
echo " --help Show this help message."
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Argument parsing
|
|||
|
|
while [ $# -gt 0 ]; do
|
|||
|
|
case "$1" in
|
|||
|
|
--name)
|
|||
|
|
name="$2"; shift 2 ;;
|
|||
|
|
--remote)
|
|||
|
|
remote="$2"; shift 2 ;;
|
|||
|
|
--channel)
|
|||
|
|
channel="$2"; shift 2 ;;
|
|||
|
|
--change)
|
|||
|
|
change="$2"; shift 2 ;;
|
|||
|
|
--state)
|
|||
|
|
state="$2"; shift 2 ;;
|
|||
|
|
--hash)
|
|||
|
|
exp_hash="$2"; shift 2 ;;
|
|||
|
|
--help)
|
|||
|
|
usage; exit 0 ;;
|
|||
|
|
*)
|
|||
|
|
# Positional arguments
|
|||
|
|
if [ -z "$remote" ]; then
|
|||
|
|
remote="$1"
|
|||
|
|
shift
|
|||
|
|
elif [ -z "$state" ]; then
|
|||
|
|
state="$1"
|
|||
|
|
shift
|
|||
|
|
elif [ -z "$exp_hash" ]; then
|
|||
|
|
exp_hash="$1"
|
|||
|
|
shift
|
|||
|
|
else
|
|||
|
|
echo "Error: Too many arguments" >&2
|
|||
|
|
usage
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
;;
|
|||
|
|
esac
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
if [ -z "$remote" ]; then
|
|||
|
|
echo "Error: URL for remote is required." >&2
|
|||
|
|
echo >&2
|
|||
|
|
usage
|
|||
|
|
exit 1
|
|||
|
|
elif [ -n "$change" -a -n "$state" ]; then
|
|||
|
|
echo "Error: Only one of ‘change’ or ‘state’ can be set" >&2
|
|||
|
|
echo >&2
|
|||
|
|
usage
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
hash=
|
|||
|
|
hash_algo="${NIX_HASH_ALGO:-"sha256"}"
|
|||
|
|
hash_format="${hashFormat:-"--base32"}"
|
|||
|
|
final_path=
|
|||
|
|
|
|||
|
|
# If the hash was given, a file with that hash may already be in the
|
|||
|
|
# store.
|
|||
|
|
if [ -n "$exp_hash" ]; then
|
|||
|
|
final_path=$(nix-store --print-fixed-path --recursive "$hash_algo" "$exp_hash" "$name")
|
|||
|
|
if ! nix-store --check-validity "$final_path" 2> /dev/null; then
|
|||
|
|
final_path=""
|
|||
|
|
fi
|
|||
|
|
hash="$exp_hash"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# If we don’t know the hash or a path with that hash doesn’t exist,
|
|||
|
|
# download the file and add it to the store.
|
|||
|
|
if [ -z "$final_path" ]; then
|
|||
|
|
tmp_clone="$(realpath "$(mktemp -d --tmpdir pijul-clone-tmp-XXXXXXXX)")"
|
|||
|
|
trap "rm -rf \"$tmp_clone\"" EXIT
|
|||
|
|
|
|||
|
|
clone_args="--channel $channel"
|
|||
|
|
if [ -n "$change" ]; then
|
|||
|
|
clone_args="$clone_args --change $change"
|
|||
|
|
elif [ -n "$state" ]; then
|
|||
|
|
clone_args="$clone_args --state $state"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
cd "$tmp_clone"
|
|||
|
|
pijul clone $clone_args "$remote" "$name"
|
|||
|
|
rm -rf "$tmp_clone/$name/.pijul"
|
|||
|
|
|
|||
|
|
hash="$(nix-hash --type "$hash_algo" "$hash_format" "$tmp_clone/$name")"
|
|||
|
|
final_path=$(nix-store --add-fixed --recursive "$hash_algo" "$tmp_clone/$name")
|
|||
|
|
|
|||
|
|
if [ -n "$exp_hash" -a "$exp_hash" != "$hash" ]; then
|
|||
|
|
echo "Hash mismatch for “$remote” @ “$channel”" >&2
|
|||
|
|
echo "Expected: $exp_hash" >&2
|
|||
|
|
echo "Got: $hash" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
json_escape() {
|
|||
|
|
printf '%s' "$1" | jq -Rs .
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cat <<EOF
|
|||
|
|
{
|
|||
|
|
"remote": $(json_escape "$remote"),
|
|||
|
|
"channel": $(json_escape "$channel"),
|
|||
|
|
EOF
|
|||
|
|
if [ -n "$change" ]; then cat <<EOF
|
|||
|
|
"change": "$(json_escape "$change")",
|
|||
|
|
EOF
|
|||
|
|
elif [ -n "$state" ]; then cat <<EOF
|
|||
|
|
"state": "$(json_escape "$state")",
|
|||
|
|
EOF
|
|||
|
|
fi; cat <<EOF
|
|||
|
|
"path": "$final_path",
|
|||
|
|
$(json_escape "$hash_algo"): $(json_escape "$hash"),
|
|||
|
|
"hash": "$(nix-hash --to-sri --type "$hash_algo" "$hash")"
|
|||
|
|
}
|
|||
|
|
EOF
|
|||
|
|
# vim: noet ci pi sts=0
|