From 2baca40984320e1277382f5c8e9ec12c25c43cb1 Mon Sep 17 00:00:00 2001 From: rope Date: Thu, 13 Aug 2026 14:50:14 +0100 Subject: [PATCH] update: progress bar for the copy step --- common.nix | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/common.nix b/common.nix index 06004de..7d5e046 100644 --- a/common.nix +++ b/common.nix @@ -12,6 +12,40 @@ let flake = "git+https://forg.gregersen.it/rope/nixos"; + # Now that the clients only copy, the copy is the whole wait. nix's own + # --log-format bar prints counters but no gauge, so render one from the json + # log: activity type 103 is the top-level copy-paths, and its type-105 + # progress results carry [done, expected, running, failed] path counts. + # Messages at warning level and above still go through to stderr — otherwise + # folding nix's stderr into the filter would swallow the errors too. + copyBar = pkgs.writeShellScriptBin "nix-copy-bar" '' + set -o pipefail + ${pkgs.jq}/bin/jq -Rr --unbuffered ' + ltrimstr("@nix ") | fromjson? // empty + | if .action == "start" and .type == 103 then "A \(.id)" + elif .action == "result" and .type == 105 then "P \(.id) \(.fields[0]) \(.fields[1])" + elif .action == "msg" and .level <= 2 then "M \(.msg)" + else empty end' | + { + blocks='########################################' + drawn= + while read -r tag rest; do + case "$tag" in + A) copy_id=$rest ;; + M) [ -n "$drawn" ] && printf '\n' && drawn= + printf '%s\n' "$rest" >&2 ;; + P) set -- $rest + [ "$1" = "''${copy_id:-}" ] && [ "''${3:-0}" -gt 0 ] || continue + pct=$(( $2 * 100 / $3 )) + printf '\r[%-40s] %3d%% %d/%d paths' \ + "''${blocks:0:$(( pct * 40 / 100 ))}" "$pct" "$2" "$3" + drawn=1 ;; + esac + done + [ -n "$drawn" ] && printf '\n' + } + ''; + post = "nvd diff $OLD_SYSTEM /run/current-system && (command -v record-update &>/dev/null && record-update $OLD_SYSTEM /run/current-system || true)"; # The server evaluates and builds for itself. @@ -27,7 +61,7 @@ let # fred, not root: root has no key on the server, and require-sigs = false # below is a daemon setting, so the daemon takes the unsigned closure from an # untrusted user just fine. Only the activation needs sudo. - remoteUpdate = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && NEW=$(ssh fred@nordhammer.it \"nix build --refresh --print-out-paths --out-link prebuild-${config.networking.hostName} --option extra-substituters https://attic.xuyh0120.win/lantian --option extra-trusted-public-keys lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc= ${flake}#nixosConfigurations.${config.networking.hostName}.config.system.build.toplevel\") && nix copy --from ssh://fred@nordhammer.it $NEW && sudo nixos-rebuild switch --no-reexec --store-path $NEW && ${post}'"; + remoteUpdate = "bash -c 'set -o pipefail && OLD_SYSTEM=$(readlink /run/current-system) && NEW=$(ssh fred@nordhammer.it \"nix build --refresh --print-out-paths --out-link prebuild-${config.networking.hostName} --option extra-substituters https://attic.xuyh0120.win/lantian --option extra-trusted-public-keys lantian:EeAUQ+W+6r7EtwnmYjeVwx5kOGEBpjlBfPlzGlTNvHc= ${flake}#nixosConfigurations.${config.networking.hostName}.config.system.build.toplevel\") && nix copy --from ssh://fred@nordhammer.it $NEW --log-format internal-json 2>&1 | ${copyBar}/bin/nix-copy-bar && sudo nixos-rebuild switch --no-reexec --store-path $NEW && ${post}'"; in { imports = [