Preview and organize changes before downloading
Is your feature request related to a problem?
Nix commands can sometimes start downloading a large amount of data without giving the user a clear, structured overview of what is about to be downloaded.
For example, an operation may require several gigabytes of downloads, while the information displayed in the terminal can be difficult to read and understand before the downloads actually begin.
It would be useful to have a clearer overview of the operation beforehand, somewhat similar to the way pacman presents packages and download information before an installation or upgrade.
This is not limited to NixOS system updates. It could be useful for different Nix commands and workflows that involve fetching or building store paths, such as nix profile add, nix-shell, and others.
Proposed solution
The idea is to introduce a preview and organization step before downloading.
The workflow could look something like this:
Evaluation
↓
Preview
↓
Organization / review of changes
↓
Summary
↓
Confirmation
↓
Download / build
↓
ApplyThe preview could provide a structured overview of:
- which packages or derivations are involved;
- how many items will be downloaded;
- the total download size;
- the total size after unpacking;
- potentially, different categories of changes.
The main goal would be to give the user a clear view of what is going to happen before the download starts, making it easier to understand the operation and avoid unexpectedly downloading several gigabytes of data.
Alternative solutions
One possible alternative would be to keep the current command behavior and provide this workflow through an external wrapper around Nix commands.
I wrote a small Bash proof of concept to demonstrate what this could look like:
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
sudo -v
(
while true; do
sudo -n true
sleep 60
kill -0 "$$" 2>/dev/null || exit
done
) 2>/dev/null &
SUDO_KEEPALIVE_PID=$!
trap 'rm -f "$TMPFILE"; kill "$SUDO_KEEPALIVE_PID" 2>/dev/null' EXIT
###############################################################################
# Language
###############################################################################
LANG_CODE="${LC_MESSAGES:-${LANG:-en}}"
if [[ "$LANG_CODE" == fr* ]]; then
TXT_SYNC="Synchronisation des channels..."
TXT_EVAL="Évaluation de la configuration..."
TXT_PACKAGES="Paquets"
TXT_SUMMARY="Résumé"
TXT_DOWNLOAD="Taille totale du téléchargement"
TXT_UNPACKED="Taille totale décompressée"
TXT_CONFIRM="Appliquer ces modifications ? [O/n] "
TXT_REBUILD="Reconstruction du système..."
TXT_CANCEL="Annulé."
TXT_UPTODATE="Le système est déjà à jour."
DEFAULT_REPLY="O"
else
TXT_SYNC="Synchronizing channels..."
TXT_EVAL="Evaluating configuration..."
TXT_PACKAGES="Packages"
TXT_SUMMARY="Summary"
TXT_DOWNLOAD="Total download size"
TXT_UNPACKED="Total unpacked size"
TXT_CONFIRM="Apply these changes? [Y/n] "
TXT_REBUILD="Rebuilding system..."
TXT_CANCEL="Cancelled."
TXT_UPTODATE="System is already up to date."
DEFAULT_REPLY="Y"
fi
###############################################################################
# Arguments
###############################################################################
UPDATE=0
ARGS=()
for arg in "$@"; do
if [[ "$arg" == "--update" ]]; then
UPDATE=1
else
ARGS+=("$arg")
fi
done
###############################################################################
# Update channels
###############################################################################
if (( UPDATE )); then
echo ":: $TXT_SYNC"
sudo nix-channel --update
fi
###############################################################################
# Dry build
###############################################################################
echo ":: $TXT_EVAL"
if ! sudo nixos-rebuild dry-build "${ARGS[@]}" >"$TMPFILE" 2>&1; then
cat "$TMPFILE"
exit 1
fi
###############################################################################
# Packages
###############################################################################
PACKAGES=$(
grep -oE '/nix/store/[^ ]+\.drv' "$TMPFILE" |
sed -E 's#.*/[a-z0-9]{32}-##; s/\.drv$//' |
awk '!seen[$0]++'
)
FETCH_LINE=$(grep "will be fetched" "$TMPFILE" || true)
if [[ -z "$PACKAGES" && -z "$FETCH_LINE" ]]; then
echo "$TXT_UPTODATE"
exit 0
fi
PACKAGE_COUNT=$(printf '%s\n' "$PACKAGES" | grep -c .)
echo ":: $TXT_PACKAGES ($PACKAGE_COUNT)"
echo
if command -v column >/dev/null 2>&1; then
printf '%s\n' "$PACKAGES" | column
else
printf '%s\n' "$PACKAGES"
fi
###############################################################################
# Summary
###############################################################################
echo
echo ":: $TXT_SUMMARY"
echo
if [[ -n "$FETCH_LINE" ]]; then
DOWNLOAD_SIZE=$(echo "$FETCH_LINE" | sed -E 's/.*\(([0-9.]+ [A-Za-z]+) download,.*/\1/')
UNPACKED_SIZE=$(echo "$FETCH_LINE" | sed -E 's/.*, ([0-9.]+ [A-Za-z]+) unpacked.*/\1/')
printf " %-32s %s\n" "$TXT_DOWNLOAD:" "$DOWNLOAD_SIZE"
printf " %-32s %s\n" "$TXT_UNPACKED:" "$UNPACKED_SIZE"
fi
###############################################################################
# Confirmation
###############################################################################
echo
read -rp "$TXT_CONFIRM" ANSWER
ANSWER=${ANSWER:-$DEFAULT_REPLY}
case "$ANSWER" in
[oOyY]*)
echo
echo ":: $TXT_REBUILD"
if command -v nh >/dev/null 2>&1; then
if [[ "${NIXOS_CONFIG:-/etc/nixos/configuration.nix}" == "/etc/nixos/configuration.nix" ]]; then
nh os switch -f '<nixpkgs/nixos>' "${ARGS[@]}"
else
nh os switch -f '<nixpkgs/nixos>' -- \
-I "nixos-config=${NIXOS_CONFIG}" \
"${ARGS[@]}"
fi
elif command -v nom >/dev/null 2>&1; then
sudo nixos-rebuild switch "${ARGS[@]}" |& nom
else
sudo nixos-rebuild switch "${ARGS[@]}"
fi
;;
*)
echo "$TXT_CANCEL"
exit 0
;;
esacAdditional context
The script above is only intended as a proof of concept to illustrate the desired workflow and terminal presentation. It is not intended to prescribe a particular implementation.
The main idea is to make the information available from Nix more readable and actionable before the actual download begins.
Checklist
- checked [latest Nix manual] ([source])
- checked [open feature issues and pull requests] for possible duplicates
- reviewed the [contributing guide]
Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
Source: NixOS/nix