feat(installer): richer disk picker (vendor, model, serial, type)

Replaces the bare `NAME SIZE` lsblk listing in select_disk with a
six-column table — NAME, SIZE, TYPE, VENDOR, MODEL, SERIAL — aligned
via column -t. TYPE is derived from ROTA + TRAN (NVMe / USB / SSD /
HDD). Empty vendor/model/serial fields render as `--` instead of
collapsing the alignment. Filters loop, ram, zram, sr devices.

Roadmap row moves to Shipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-04-25 21:49:36 +01:00
parent c9ff6f26f3
commit bf30cd07d8
2 changed files with 60 additions and 6 deletions

View File

@@ -220,14 +220,68 @@ select_disk() {
return
fi
# Build a richer drive table than the bare `NAME SIZE` lsblk default.
# Columns: NAME, SIZE, TYPE (NVMe/USB/SSD/HDD), VENDOR, MODEL, SERIAL.
# Empty fields render as "--" so column -t can still align them.
local raw rows=""
raw=$(lsblk -d -n -p -o NAME,SIZE,ROTA,TRAN,VENDOR,MODEL,SERIAL 2>/dev/null \
| grep -vE '^(/dev/(loop|ram|zram|sr))')
while IFS= read -r line; do
[[ -z "$line" ]] && continue
# NAME and SIZE are reliably whitespace-free; ROTA/TRAN are short
# tokens; VENDOR/MODEL/SERIAL can carry internal spaces. Pull the
# first four fields off the front, treat the rest as the
# vendor/model/serial trio split via the original lsblk column
# widths — easier to just re-query each device for clean values.
local dev size rota tran
read -r dev size rota tran _ <<<"$line"
local type vendor model serial
case "$tran" in
nvme) type="NVMe" ;;
usb) type="USB" ;;
sata|scsi)
if [[ "$rota" == "1" ]]; then type="HDD"; else type="SSD"; fi
;;
*)
if [[ "$rota" == "1" ]]; then type="HDD"; else type="SSD"; fi
;;
esac
vendor=$(lsblk -d -n -o VENDOR "$dev" 2>/dev/null | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')
model=$(lsblk -d -n -o MODEL "$dev" 2>/dev/null | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')
serial=$(lsblk -d -n -o SERIAL "$dev" 2>/dev/null | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')
[[ -z "$vendor" ]] && vendor="--"
[[ -z "$model" ]] && model="--"
[[ -z "$serial" ]] && serial="--"
# Tab-separated for column -t -s, then collapse internal whitespace
# in MODEL so multi-space brand strings don't break alignment.
rows+=$(printf '%s\t%s\t%s\t%s\t%s\t%s\n' \
"$dev" "$size" "$type" "$vendor" "${model//$'\t'/ }" "$serial")
rows+=$'\n'
done <<<"$raw"
if [[ -z "$rows" ]]; then
error "No installable drives found."
exit 1
fi
info "Available drives:"
echo ""
lsblk -d -n -p -o NAME,SIZE,MODEL | grep -v loop
{
printf 'NAME\tSIZE\tTYPE\tVENDOR\tMODEL\tSERIAL\n'
printf '%s' "$rows"
} | column -t -s $'\t'
echo ""
local drives
drives=$(lsblk -d -n -p -o NAME,SIZE | grep -v loop)
TARGET_DRIVE=$(echo "$drives" | gum choose --header "Select target drive" | awk '{print $1}')
# gum choose gets the same aligned rows so the picker reads like the table.
local picker
picker=$(printf '%s' "$rows" | column -t -s $'\t')
local choice
choice=$(printf '%s\n' "$picker" | gum choose --header "Select target drive")
TARGET_DRIVE=$(awk '{print $1}' <<<"$choice")
if [[ -z "$TARGET_DRIVE" ]]; then
error "No drive selected"