You've already forked guix-tribes
7dec823794
Source: guix-tribes master2ea4cae872Base: previous supertest-dev4fee530b68Mode: tree sync, preserving dev channel authorization
269 lines
6.7 KiB
Bash
Executable File
269 lines
6.7 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -eu
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: update-tribes-pin [options] [rev]
|
|
|
|
Pin guix-tribes to a Tribes commit and refresh all fixed-output hashes.
|
|
|
|
By default, REV is "master" resolved from the local Tribes checkout. Hashing and
|
|
Guix builds run with local `guix` unless --build-host is provided.
|
|
|
|
Options:
|
|
--tribes-repo PATH Local Tribes git checkout
|
|
--guix-repo PATH Local guix-tribes checkout
|
|
--build-host HOST SSH host used for Guix builds and hashing
|
|
-h, --help Show this help
|
|
EOF
|
|
}
|
|
|
|
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
default_guix_repo=$(CDPATH= cd -- "$script_dir/.." && pwd)
|
|
default_tribes_repo=$(CDPATH= cd -- "$default_guix_repo/../tribes" && pwd)
|
|
|
|
tribes_repo=$default_tribes_repo
|
|
guix_repo=$default_guix_repo
|
|
build_host=
|
|
rev=master
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--tribes-repo)
|
|
tribes_repo=$2
|
|
shift 2
|
|
;;
|
|
--guix-repo)
|
|
guix_repo=$2
|
|
shift 2
|
|
;;
|
|
--build-host)
|
|
build_host=$2
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
-*)
|
|
printf 'Unknown option: %s\n' "$1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
*)
|
|
rev=$1
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ "$#" -gt 0 ]; then
|
|
printf 'Unexpected arguments: %s\n' "$*" >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
|
|
source_file=$guix_repo/tribes/packages/source.scm
|
|
|
|
if [ ! -d "$tribes_repo/.git" ]; then
|
|
printf 'Tribes repo not found: %s\n' "$tribes_repo" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$source_file" ]; then
|
|
printf 'guix-tribes source file not found: %s\n' "$source_file" >&2
|
|
exit 1
|
|
fi
|
|
|
|
require_tool() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
printf 'Missing required tool: %s\n' "$1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
require_tool env
|
|
require_tool git
|
|
require_tool tar
|
|
require_tool perl
|
|
require_tool mktemp
|
|
|
|
if [ -n "$build_host" ]; then
|
|
use_remote=true
|
|
else
|
|
use_remote=false
|
|
require_tool guix
|
|
fi
|
|
|
|
commit=$(git -C "$tribes_repo" rev-parse "$rev^{commit}")
|
|
version=$(env LC_ALL=C perl -0ne 'print $1 if /\(git-version "([^"]+)"/' "$source_file")
|
|
|
|
if [ -z "$version" ]; then
|
|
printf 'Could not read Tribes version from %s\n' "$source_file" >&2
|
|
exit 1
|
|
fi
|
|
|
|
local_tmp=$(mktemp -d "${TMPDIR:-/tmp}/tribes-pin.XXXXXX")
|
|
remote_tmp=
|
|
|
|
cleanup() {
|
|
if [ -n "${remote_tmp:-}" ]; then
|
|
ssh "$build_host" "rm -rf '$remote_tmp'" >/dev/null 2>&1 || true
|
|
fi
|
|
rm -rf "$local_tmp"
|
|
}
|
|
|
|
trap cleanup EXIT INT TERM
|
|
|
|
mkdir -p "$local_tmp/tribes-source"
|
|
git -C "$tribes_repo" archive "$commit" | tar -x -C "$local_tmp/tribes-source"
|
|
|
|
setup_remote() {
|
|
require_tool rsync
|
|
require_tool ssh
|
|
|
|
if [ -z "${remote_tmp:-}" ]; then
|
|
printf 'Using build host %s.\n' "$build_host" >&2
|
|
remote_tmp=$(ssh "$build_host" 'mktemp -d /tmp/tribes-pin.XXXXXX')
|
|
|
|
rsync -az --delete --exclude .git "$guix_repo/" "$build_host:$remote_tmp/guix-tribes/"
|
|
rsync -az --delete "$local_tmp/tribes-source/" "$build_host:$remote_tmp/tribes-source/"
|
|
fi
|
|
|
|
source_root=$remote_tmp/tribes-source
|
|
guix_load_path=$remote_tmp/guix-tribes
|
|
source_hash=$(ssh "$build_host" "guix hash -rx '$source_root'" | tr -d '\r')
|
|
}
|
|
|
|
if [ "$use_remote" = true ]; then
|
|
setup_remote
|
|
else
|
|
source_root=$local_tmp/tribes-source
|
|
guix_load_path=$guix_repo
|
|
source_hash=$(guix hash -rx "$source_root" | tr -d '\r')
|
|
fi
|
|
|
|
run_scheme() {
|
|
name=$1
|
|
body=$2
|
|
|
|
if [ "$use_remote" = true ]; then
|
|
ssh "$build_host" "cat > '$remote_tmp/$name.scm' <<'EOF'
|
|
$body
|
|
EOF"
|
|
|
|
ssh "$build_host" "guix build -L '$guix_load_path' -f '$remote_tmp/$name.scm' --no-grafts 2>&1" || true
|
|
else
|
|
scheme_file=$local_tmp/$name.scm
|
|
cat > "$scheme_file" <<EOF
|
|
$body
|
|
EOF
|
|
|
|
guix build -L "$guix_load_path" -f "$scheme_file" --no-grafts 2>&1 || true
|
|
fi
|
|
}
|
|
|
|
extract_hash() {
|
|
env LC_ALL=C perl -ne '
|
|
if (s/.*\bgot:\s*([0-9a-z]{52}).*/$1/) {
|
|
chomp;
|
|
$hash = $_;
|
|
} elsif (s/.*\bactual hash:\s*([0-9a-z]{52}).*/$1/) {
|
|
chomp;
|
|
$hash = $_;
|
|
}
|
|
END {
|
|
if (defined $hash) {
|
|
print $hash;
|
|
} else {
|
|
exit 1;
|
|
}
|
|
}
|
|
'
|
|
}
|
|
|
|
dummy_hash=0000000000000000000000000000000000000000000000000000
|
|
|
|
raw_mix_deps_output() {
|
|
run_scheme raw-mix-deps "(use-modules (guix gexp) (tribes packages source))
|
|
(fetch-mix-deps
|
|
(local-file \"$source_root\" #:recursive? #t)
|
|
#:name \"tribes-mix-deps-raw\"
|
|
#:version \"$version\"
|
|
#:sha256 \"$dummy_hash\")"
|
|
}
|
|
|
|
mix_deps_output() {
|
|
run_scheme mix-deps "(use-modules (guix gexp) (tribes packages source))
|
|
(tribes-mix-deps
|
|
(local-file \"$source_root\" #:recursive? #t)
|
|
#:name \"tribes-mix-deps\"
|
|
#:version \"$version\"
|
|
#:raw-sha256 \"$raw_mix_hash\"
|
|
#:sha256 \"$dummy_hash\")"
|
|
}
|
|
|
|
npm_deps_output() {
|
|
run_scheme npm-deps "(use-modules (guix gexp) (tribes packages source))
|
|
(fetch-npm-deps
|
|
(local-file \"$source_root\" #:recursive? #t)
|
|
#:mix-fod-deps
|
|
(tribes-mix-deps
|
|
(local-file \"$source_root\" #:recursive? #t)
|
|
#:name \"tribes-mix-deps\"
|
|
#:version \"$version\"
|
|
#:raw-sha256 \"$raw_mix_hash\"
|
|
#:sha256 \"$mix_hash\")
|
|
#:name \"tribes-npm-deps\"
|
|
#:version \"$version\"
|
|
#:sha256 \"$dummy_hash\")"
|
|
}
|
|
|
|
hash_failure_hint() {
|
|
label=$1
|
|
output=$2
|
|
|
|
printf 'Failed to extract %s hash.\n' "$label" >&2
|
|
if [ "$use_remote" = false ]; then
|
|
printf 'Local Guix did not complete the hash refresh. To run this step on a build host, rerun with --build-host HOST.\n' >&2
|
|
else
|
|
printf 'Build host Guix did not complete the hash refresh.\n' >&2
|
|
fi
|
|
printf '%s\n' "$output" >&2
|
|
exit 1
|
|
}
|
|
|
|
raw_output=$(raw_mix_deps_output)
|
|
raw_mix_hash=$(printf '%s\n' "$raw_output" | extract_hash) || hash_failure_hint 'raw mix deps' "$raw_output"
|
|
|
|
mix_output=$(mix_deps_output)
|
|
mix_hash=$(printf '%s\n' "$mix_output" | extract_hash) || hash_failure_hint 'prepared mix deps' "$mix_output"
|
|
|
|
npm_output=$(npm_deps_output)
|
|
npm_hash=$(printf '%s\n' "$npm_output" | extract_hash) || hash_failure_hint 'npm deps' "$npm_output"
|
|
|
|
COMMIT=$commit \
|
|
SOURCE_HASH=$source_hash \
|
|
RAW_MIX_HASH=$raw_mix_hash \
|
|
MIX_HASH=$mix_hash \
|
|
NPM_HASH=$npm_hash \
|
|
env LC_ALL=C perl -0pi -e '
|
|
s/\(define %tribes-raw-mix-deps-sha256\n "[^"]+"\)/(define %tribes-raw-mix-deps-sha256\n "$ENV{RAW_MIX_HASH}")/;
|
|
s/\(define %tribes-mix-deps-sha256\n "[^"]+"\)/(define %tribes-mix-deps-sha256\n "$ENV{MIX_HASH}")/;
|
|
s/\(define %tribes-npm-deps-sha256\n "[^"]+"\)/(define %tribes-npm-deps-sha256\n "$ENV{NPM_HASH}")/;
|
|
s/\(define %tribes-commit\n "[^"]+"\)/(define %tribes-commit\n "$ENV{COMMIT}")/;
|
|
s/\(define %tribes-source-sha256\n "[^"]+"\)/(define %tribes-source-sha256\n "$ENV{SOURCE_HASH}")/;
|
|
' "$source_file"
|
|
|
|
printf 'Updated %s\n' "$source_file"
|
|
printf 'commit: %s\n' "$commit"
|
|
printf 'source sha256: %s\n' "$source_hash"
|
|
printf 'raw mix deps sha256: %s\n' "$raw_mix_hash"
|
|
printf 'mix deps sha256: %s\n' "$mix_hash"
|
|
printf 'npm deps sha256: %s\n' "$npm_hash"
|