···11+#!/usr/bin/env bash
22+set -euo pipefail
33+44+# Three hashes move together (src, frontend npmDepsHash, server vendorHash),
55+# and src is wrapped in applyPatches, so nix-update can't do this one.
66+owner=schej-it
77+repo=timeful.app
88+branch=main
99+attr=timeful
1010+1111+# Run by update-pkgs from the flake root ($0 is a read-only store copy).
1212+pkg=pkgs/timeful/package.nix
1313+# Linux-only package: always evaluate/build the x86_64-linux variant.
1414+build_attr=".#packages.x86_64-linux.$attr"
1515+1616+new_rev=$(curl -fsSL "https://api.github.com/repos/$owner/$repo/commits/$branch" | jq -r .sha)
1717+old_rev=$(sed -n 's|^ *rev = "\([^"]*\)";|\1|p' "$pkg")
1818+if [ "$old_rev" = "$new_rev" ]; then
1919+ echo "$attr: already up to date ($new_rev)"
2020+ exit 0
2121+fi
2222+2323+new_date=$(curl -fsSL "https://api.github.com/repos/$owner/$repo/commits/$new_rev" | jq -r .commit.committer.date | cut -d T -f1)
2424+new_version="0-unstable-$new_date"
2525+2626+# Portable in-place sed (BSD and GNU).
2727+edit() {
2828+ local tmp
2929+ tmp=$(mktemp)
3030+ sed "$@" "$pkg" >"$tmp"
3131+ cat "$tmp" >"$pkg"
3232+ rm -f "$tmp"
3333+}
3434+3535+# Bump rev + version and blank every hash: with the old ones in place nix
3636+# reuses the cached FODs and the build "succeeds" on stale code.
3737+edit \
3838+ -e "s|^\( *\)rev = \".*\";|\1rev = \"$new_rev\";|" \
3939+ -e "s|^\( *\)version = \".*\";|\1version = \"$new_version\";|" \
4040+ -e "s|^\( *\)hash = \".*\";|\1hash = \"\";|" \
4141+ -e "s|^\( *\)npmDepsHash = \".*\";|\1npmDepsHash = \"\";|" \
4242+ -e "s|^\( *\)vendorHash = \".*\";|\1vendorHash = \"\";|"
4343+4444+update_hash() {
4545+ local field=$1 new=$2
4646+ edit -e "s|^\( *\)$field = \"[^\"]*\";|\1$field = \"$new\";|"
4747+}
4848+4949+# The probe build is *expected* to fail (hash mismatch); `|| true` keeps
5050+# pipefail/errexit from turning that into an empty `got`. awk must not
5151+# `exit` early or tee dies of SIGPIPE and takes the pipeline with it.
5252+probe_hash() {
5353+ { nix build --no-link "$build_attr$1" 2>&1 || true; } | tee /dev/stderr \
5454+ | awk '/got:/ && !seen { print $2; seen = 1 }' || true
5555+}
5656+5757+# Probe each FOD on its own so a hash is never attributed to the wrong field.
5858+for spec in hash:.src npmDepsHash:.frontend.npmDeps vendorHash:.goModules; do
5959+ field=${spec%%:*}
6060+ sub=${spec#*:}
6161+ got=$(probe_hash "$sub")
6262+ if [ -z "$got" ]; then
6363+ echo "$attr: no hash reported for $field" >&2
6464+ exit 1
6565+ fi
6666+ update_hash "$field" "$got"
6767+ echo "$attr: $field → $got"
6868+done
6969+7070+echo "$attr: updated to $new_rev ($new_version)"
7171+nix build --no-link "$build_attr"