4043787a58
- 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.
57 lines
2.1 KiB
Plaintext
57 lines
2.1 KiB
Plaintext
# 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
|