fix: close the four known installer bugs (DU-H1, DU-H2, BUG-1, BUG-2)
- DU-H1: flags are parsed wherever they sit, so `install --unattended` and `--unattended install` are the same run; any unknown flag, word, or subcommand exits 2 to stderr before a package manager is touched. - DU-H2: every download lands in one private mktemp -d (mode 700) workdir per run, is checked non-empty before sudo tar sees it, and an EXIT/INT/TERM trap cleans up. No fixed /tmp paths remain. - BUG-1: ^t is now toggle-shown — it ticks only the rows the active filter is showing, and @needs expansion stops at the first invasive row, so an invasive package can never be ticked off-screen. - BUG-2: ^t journals what it added, so a second ^t over the same shown set unticks exactly that set; the bind no longer clears the query. - lab: the type verb polls fzf's reported query to a deadline instead of a fixed sleep; marks_settled retries within its deadline. Suite 256/0 host, 214/0 docker (ubuntu:24.04), mutations 24/24 killed (six new mutants re-introduce each bug and all die), lab 6/6 green.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# what: the parser stops at the subcommand again, so flags after it are dropped
|
||||
# why: DU-H1 as it shipped: `dotup install --unattended` ran a FULL ATTENDED install and said nothing, which is how invasive packages reached a machine that had asked for the safe defaults
|
||||
# kills: install --unattended refuses invasive too
|
||||
# run: unit
|
||||
<<<OLD
|
||||
CMD=
|
||||
endopts=0
|
||||
n=$#; i=0
|
||||
while [ "$i" -lt "$n" ]; do
|
||||
i=$((i + 1)); a=$1; shift
|
||||
if [ "$endopts" -eq 0 ]; then
|
||||
case $a in
|
||||
--) endopts=1; continue ;;
|
||||
--unattended) UNATTENDED=1; ASSUME_YES=1; continue ;;
|
||||
--print|-n) DRYRUN=1; continue ;;
|
||||
--yes|-y) ASSUME_YES=1; continue ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
-?*) err "unknown flag: $a"; usage; exit 2 ;;
|
||||
esac
|
||||
fi
|
||||
# The first bare word is the subcommand; every later one is an operand,
|
||||
# rotated to the back of "$@" so the dispatch below reads them in the order
|
||||
# they were typed with the flags taken out from between them.
|
||||
if [ -z "$CMD" ]; then CMD=$a; else set -- "$@" "$a"; fi
|
||||
done
|
||||
|
||||
# What each subcommand accepts. -1 is "as many as you like". An unknown
|
||||
# subcommand, or one word more than a subcommand can use, is the same class of
|
||||
# mistake as an unknown flag and gets the same answer: say so, and stop.
|
||||
# This list and the dispatch below must name the same commands.
|
||||
amin=0; amax=0
|
||||
case ${CMD:-run} in
|
||||
run|pick|install|private|render|expand-all|plan|preflight|fzf-path) ;;
|
||||
toggle|toggle-shown|expand) amax=-1 ;;
|
||||
preset|explain|resolve) amax=1 ;;
|
||||
vercmp) amin=2; amax=2 ;;
|
||||
*) err "unknown command: $CMD"; usage; exit 2 ;;
|
||||
esac
|
||||
[ "$#" -ge "$amin" ] || { err "${CMD:-run} needs $amin argument(s), got $#"; usage; exit 2; }
|
||||
[ "$amax" -lt 0 ] || [ "$#" -le "$amax" ] || {
|
||||
err "${CMD:-run} takes at most $amax argument(s), got $#:$(printf ' %s' "$@")"
|
||||
usage; exit 2; }
|
||||
<<<NEW
|
||||
CMD=
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--unattended) UNATTENDED=1; ASSUME_YES=1 ;;
|
||||
--print|-n) DRYRUN=1 ;;
|
||||
--yes|-y) ASSUME_YES=1 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
--*) err "unknown flag: $1"; usage; exit 2 ;;
|
||||
*) CMD=$1; shift; break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
<<<END
|
||||
Reference in New Issue
Block a user