dot

vizie's NixOS desktop: Hyprland, CachyOS kernel and gaming tweaks

129 lines4342 bytesexecutable
1#!/usr/bin/env bash
2# Updates NixOS from a throwaway worktree of this repo, so the checkout you edit in
3# is left alone until the update is done. Started from the "Desktop" half of the
4# control centre's update tile in a kitty window (installed as `nixos-update`,
5# modules/home/packages.nix, which sets DOT_REPO).
6#
7# 1. a temporary worktree of main, with the commits git.granstrm.com made since
8# (the nightly CachyOS kernel, flake.nix's `ci`)
9# 2. nix flake update of every input but the kernel's, committed there: the kernel
10# is the one git.granstrm.com built, and comes from its binary cache
11# 3. nixos-rebuild build, then nvd's list of what changed against the running system
12# 4. asks before going on; then pushes the commit, installs it as the next boot
13# entry (nixos-rebuild boot), brings your checkout's main up to date and reboots
14#
15# If anything fails, the window stays open until you press Enter, and nothing is
16# rebooted.
17set -E
18
19repo=${DOT_REPO:-$HOME/git/dot}
20tmp=""
21
22step() { printf '\n\e[1;34m==> %s\e[0m\n' "$*"; }
23note() { printf '\e[1;33m%s\e[0m\n' "$*"; }
24wait_close() { read -rp "Press Enter to close. " _ || true; }
25
26die() {
27 trap - ERR
28 printf '\n\e[1;31m%s\e[0m\n' "$*"
29 wait_close
30 exit 1
31}
32
33cleanup() {
34 if [ -n "$tmp" ]; then
35 git -C "$repo" worktree remove --force "$tmp" 2>/dev/null || true
36 rm -rf "$tmp"
37 tmp=""
38 fi
39}
40
41trap 'die "The update failed (see above). Nothing was rebooted."' ERR
42trap cleanup EXIT
43
44step "Fetching $repo"
45git -C "$repo" worktree prune
46git -C "$repo" fetch origin main
47main=$(git -C "$repo" rev-parse main)
48# git.granstrm.com's own commits (the kernel) are taken as they are; your own on
49# main that it doesn't have yet are pushed with the update.
50if git -C "$repo" merge-base --is-ancestor main origin/main; then
51 base=$(git -C "$repo" rev-parse origin/main)
52elif git -C "$repo" merge-base --is-ancestor origin/main main; then
53 base=$main
54else
55 die "main in $repo and origin/main have diverged; rebase main first."
56fi
57ahead=$(git -C "$repo" rev-list --count origin/main..main)
58dirty=$(git -C "$repo" status --porcelain)
59
60tmp=$(mktemp -d -t dot-update.XXXXXX)
61step "Creating a worktree of main in $tmp"
62git -C "$repo" worktree add --detach "$tmp" "$base"
63cd "$tmp" || die "Could not enter $tmp."
64
65step "Updating flake inputs (all but the kernel's)"
66mapfile -t inputs < <(jq -r '.nodes.root.inputs | keys[] | select(. != "nix-cachyos-kernel")' flake.lock)
67nix flake update --commit-lock-file "${inputs[@]}"
68
69kernel=$(nix eval --raw "$tmp#nixosConfigurations.desktop.config.boot.kernelPackages.kernel")
70if ! nix path-info "$kernel" >/dev/null 2>&1 &&
71 ! nix path-info --store https://cache.git.granstrm.com "$kernel" >/dev/null 2>&1; then
72 note "The kernel isn't in git.granstrm.com's cache: its CI hasn't built it yet, or failed"
73 note "(https://git.granstrm.com/dot). It would compile here, which takes a while."
74 read -rp "Compile it here? [y/N] " answer || answer=""
75 case $answer in
76 [yY]*) ;;
77 *)
78 echo "Nothing was changed."
79 sleep 1
80 exit 0
81 ;;
82 esac
83fi
84
85step "Building"
86nixos-rebuild build --flake "$tmp"
87if [ "$(readlink -f "$tmp/result")" = "$(readlink -f /run/current-system)" ]; then
88 printf '\nEverything is already up to date.\n'
89 wait_close
90 exit 0
91fi
92
93step "What changes"
94git --no-pager log --format='%s%n%n%b' "$main..HEAD"
95nvd diff /run/current-system "$tmp/result"
96
97echo
98[ -z "$dirty" ] || note "Uncommitted changes in $repo are not part of this update."
99[ "$ahead" -eq 0 ] || note "main has $ahead commit(s) not on git.granstrm.com yet; they are pushed too."
100read -rp "Commit, push, install and reboot? [y/N] " answer || answer=""
101case $answer in
102 [yY]*) ;;
103 *)
104 echo "Nothing was changed."
105 sleep 1
106 exit 0
107 ;;
108esac
109
110step "Pushing"
111git push origin HEAD:main
112
113step "Installing as the next boot entry"
114nixos-rebuild boot --sudo --flake "$tmp"
115
116step "Updating main in $repo"
117commit=$(git rev-parse HEAD)
118if [ "$(git -C "$repo" symbolic-ref --quiet --short HEAD)" = main ]; then
119 git -C "$repo" merge --ff-only "$commit"
120else
121 git -C "$repo" update-ref refs/heads/main "$commit" "$main"
122fi
123cd "$repo"
124cleanup
125
126trap 'printf "\nReboot cancelled. The update boots next time.\n"; wait_close; exit 0' INT
127step "Rebooting in 5 seconds (Ctrl+C to cancel)"
128sleep 5
129systemctl reboot