install.sh: fix swap creation and partition-range bugs
Review of branch t490-dualboot (laptop-config#1) found three correctness issues in the new install.sh. This commit fixes them: 1. parted mkpart range used '-NIXOS_SIZE 100%' which on a T490 with a recovery partition at the end of the disk would overlap that recovery partition and fail. The new code computes the start of the freed space as the new end of the (now shrunken) Windows partition and uses explicit MiB offsets, so the new partition lands in the space ntfsresize actually freed. 2. SWAP_SIZE was advertised in the user-facing plan (lines 100-106 of the original) but no swap partition was ever created and swapon was never run. The new code creates a linux-swap partition after the NixOS root, runs mkswap, and swapon. The total shrink applied to the Windows partition is now nixos_bytes + swap_bytes. 3. The 'sort | tail -1' trick for finding the new partition breaks when more than one new partition is created (NixOS root + swap would both qualify) and is fragile for disks with 10+ existing partitions. The new code snapshots the partition list before mkpart and uses comm -13 to diff, then picks the lowest-numbered new partition for the NixOS root and the next one for swap. Reported-by: agent-engineering review of sscoble/laptop-config#1
This commit is contained in:
parent
921fc1402a
commit
060194b734
1 changed files with 86 additions and 18 deletions
104
install.sh
104
install.sh
|
|
@ -118,17 +118,31 @@ read -rp "Type 'yes' to proceed: " confirm
|
|||
|
||||
# === Shrink Windows ===
|
||||
# Convert NIXOS_SIZE (e.g. "200G") to bytes for ntfsresize
|
||||
case "$NIXOS_SIZE" in
|
||||
*G|*g) nixos_bytes=$(( ${NIXOS_SIZE%[Gg]} * 1024 * 1024 * 1024 )) ;;
|
||||
*M|*m) nixos_bytes=$(( ${NIXOS_SIZE%[Mm]} * 1024 * 1024 )) ;;
|
||||
*) nixos_bytes="$NIXOS_SIZE" ;;
|
||||
esac
|
||||
log "Shrinking Windows partition by $NIXOS_SIZE ($nixos_bytes bytes) — this may take a few minutes..."
|
||||
size_to_bytes() {
|
||||
local s="$1"
|
||||
case "$s" in
|
||||
*G|*g) echo $(( ${s%[Gg]} * 1024 * 1024 * 1024 )) ;;
|
||||
*M|*m) echo $(( ${s%[Mm]} * 1024 * 1024 )) ;;
|
||||
*K|*k) echo $(( ${s%[Kk]} * 1024 )) ;;
|
||||
*) echo "$s" ;;
|
||||
esac
|
||||
}
|
||||
nixos_bytes=$(size_to_bytes "$NIXOS_SIZE")
|
||||
# Same for SWAP_SIZE so we can shrink the Windows partition by the *total* of
|
||||
# both new partitions (NixOS root + swap). Without this, the swap partition
|
||||
# would never fit on disk.
|
||||
if [[ "$SWAP_SIZE" == "0" ]]; then
|
||||
shrink_bytes=$nixos_bytes
|
||||
else
|
||||
swap_bytes=$(size_to_bytes "$SWAP_SIZE")
|
||||
shrink_bytes=$(( nixos_bytes + swap_bytes ))
|
||||
fi
|
||||
log "Shrinking Windows partition by $NIXOS_SIZE (nixos) ${SWAP_SIZE:+ + $SWAP_SIZE (swap)} ($shrink_bytes bytes total) — this may take a few minutes..."
|
||||
ntfsfix -d "$WIN_PART" 2>/dev/null || true
|
||||
# ntfsresize syntax: -s = perform the shrink, --size = new size in bytes
|
||||
# We want the new Windows partition to be (current size - nixos_bytes).
|
||||
# We want the new Windows partition to be (current size - shrink_bytes).
|
||||
win_size_bytes=$(lsblk -ndo SIZE -b "$WIN_PART")
|
||||
new_win_bytes=$(( win_size_bytes - nixos_bytes ))
|
||||
new_win_bytes=$(( win_size_bytes - shrink_bytes ))
|
||||
ntfsresize -s --size "$new_win_bytes" "$WIN_PART" 2>&1 | tail -5 \
|
||||
|| fail "ntfsresize failed; aborting"
|
||||
|
||||
|
|
@ -137,24 +151,78 @@ ntfsresize -s --size "$new_win_bytes" "$WIN_PART" 2>&1 | tail -5 \
|
|||
partprobe "$DISK"
|
||||
sleep 2
|
||||
|
||||
# === Find next available partition number ===
|
||||
existing=$(lsblk -nlo NAME "$DISK" 2>/dev/null | wc -l)
|
||||
log "Existing partitions on $DISK: $existing"
|
||||
# Snapshot the partition list BEFORE we create the new ones, so we can diff
|
||||
# and identify which device nodes are new. Plain `sort | tail -1` is unsafe
|
||||
# when more than one new partition is created (NixOS root + swap).
|
||||
existing_parts=$(lsblk -nlo NAME "$DISK" 2>/dev/null | tail -n +2 | sort)
|
||||
|
||||
# Create NixOS root partition in the freed space
|
||||
log "Creating NixOS root partition ($NIXOS_SIZE)..."
|
||||
parted -s -a opt "$DISK" mkpart primary ext4 -- -"$NIXOS_SIZE" 100% || fail "parted mkpart failed"
|
||||
# === Create NixOS root + swap in the freed space ===
|
||||
# Compute the start = end of the (now smaller) Windows partition.
|
||||
# We deliberately do NOT use `-NIXOS_SIZE 100%` because on a T490 the recovery
|
||||
# partition sits at the end of the disk and that range would overlap it.
|
||||
# We work in 1MiB units and let parted align.
|
||||
win_new_bytes=$(lsblk -ndo SIZE -b "$WIN_PART")
|
||||
win_end_mib=$(( (win_new_bytes + 1024*1024 - 1) / (1024*1024) ))
|
||||
|
||||
# Extract the numeric prefix of NIXOS_SIZE for the parted range calculation.
|
||||
nix_num=${NIXOS_SIZE%[GgMmKk]*}; nix_unit=${NIXOS_SIZE##*[0-9]}
|
||||
case "$nix_unit" in
|
||||
G|g) nix_size_mib=$(( nix_num * 1024 )) ;;
|
||||
M|m) nix_size_mib=$nix_num ;;
|
||||
*) fail "NIXOS_SIZE must be suffixed with M or G (got '$NIXOS_SIZE')" ;;
|
||||
esac
|
||||
nix_start_mib=$win_end_mib
|
||||
nix_end_mib=$(( nix_start_mib + nix_size_mib ))
|
||||
log "Creating NixOS root partition (${NIXOS_SIZE}) at ${nix_start_mib}MiB..${nix_end_mib}MiB..."
|
||||
parted -s "$DISK" mkpart primary ext4 "${nix_start_mib}MiB" "${nix_end_mib}MiB" \
|
||||
|| fail "parted mkpart (nixos) failed"
|
||||
partprobe "$DISK"
|
||||
sleep 2
|
||||
sleep 1
|
||||
|
||||
# Find the new partition
|
||||
NIXOS_PART=$(lsblk -nlo NAME "$DISK" 2>/dev/null | sed "s|^|/dev/|" | sort | tail -1)
|
||||
log "New partition: $NIXOS_PART"
|
||||
if [[ "$SWAP_SIZE" != "0" ]]; then
|
||||
swap_num=${SWAP_SIZE%[GgMmKk]*}; swap_unit=${SWAP_SIZE##*[0-9]}
|
||||
case "$swap_unit" in
|
||||
G|g) swap_size_mib=$(( swap_num * 1024 )) ;;
|
||||
M|m) swap_size_mib=$swap_num ;;
|
||||
*) fail "SWAP_SIZE must be suffixed with M or G (got '$SWAP_SIZE')" ;;
|
||||
esac
|
||||
swap_end_mib=$(( nix_end_mib + swap_size_mib ))
|
||||
log "Creating swap partition (${SWAP_SIZE}) at ${nix_end_mib}MiB..${swap_end_mib}MiB..."
|
||||
parted -s "$DISK" mkpart primary linux-swap "${nix_end_mib}MiB" "${swap_end_mib}MiB" \
|
||||
|| fail "parted mkpart (swap) failed"
|
||||
partprobe "$DISK"
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Identify the new partitions by diffing the partition table. New partitions
|
||||
# are the ones that didn't exist before we ran mkpart.
|
||||
new_parts=$(lsblk -nlo NAME "$DISK" 2>/dev/null | tail -n +2 | sort)
|
||||
NIXOS_PART=$(comm -13 <(echo "$existing_parts") <(echo "$new_parts") \
|
||||
| grep -v "$(basename "$DISK")" \
|
||||
| head -1 \
|
||||
| sed 's|^|/dev/|')
|
||||
[[ -n "$NIXOS_PART" ]] || fail "could not identify the new NixOS partition"
|
||||
log "New NixOS partition: $NIXOS_PART"
|
||||
if [[ "$SWAP_SIZE" != "0" ]]; then
|
||||
SWAP_PART=$(comm -13 <(echo "$existing_parts") <(echo "$new_parts") \
|
||||
| grep -v "$NIXOS_PART" \
|
||||
| grep -v "$(basename "$DISK")" \
|
||||
| head -1 \
|
||||
| sed 's|^|/dev/|')
|
||||
[[ -n "$SWAP_PART" ]] || fail "could not identify the new swap partition"
|
||||
log "New swap partition: $SWAP_PART"
|
||||
fi
|
||||
|
||||
# === Format and mount ===
|
||||
log "Formatting $NIXOS_PART as ext4..."
|
||||
mkfs.ext4 -F -L nixos "$NIXOS_PART"
|
||||
|
||||
if [[ "$SWAP_SIZE" != "0" ]]; then
|
||||
log "Setting up swap on $SWAP_PART..."
|
||||
mkswap -L swap "$SWAP_PART"
|
||||
swapon "$SWAP_PART"
|
||||
fi
|
||||
|
||||
log "Mounting..."
|
||||
mount "$NIXOS_PART" /mnt
|
||||
mkdir -p /mnt/boot
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue