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:
@@ -3,7 +3,7 @@
|
||||
# kills: the tarball is extracted where the symlink points
|
||||
# run: unit
|
||||
<<<OLD
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf /tmp/nvim.tgz -C /opt/nvim --strip-components=1" \
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf '$WORKDIR/nvim.tgz' -C /opt/nvim --strip-components=1" \
|
||||
<<<NEW
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf /tmp/nvim.tgz -C /opt/nvim-TYPO --strip-components=1" \
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf '$WORKDIR/nvim.tgz' -C /opt/nvim-TYPO --strip-components=1" \
|
||||
<<<END
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,9 @@
|
||||
# what: an unrecognised flag is skipped instead of stopping the run
|
||||
# why: the other half of DU-H1 -- a parser that shrugs at `--unatended` installs a different set of packages than the operator asked for, with no way to tell
|
||||
# kills: an unknown flag after the subcommand is refused
|
||||
# run: unit
|
||||
<<<OLD
|
||||
-?*) err "unknown flag: $a"; usage; exit 2 ;;
|
||||
<<<NEW
|
||||
-?*) continue ;;
|
||||
<<<END
|
||||
@@ -0,0 +1,13 @@
|
||||
# what: the neovim tarball is downloaded to and extracted from /tmp/nvim.tgz again
|
||||
# why: DU-H2: a fixed name in a world-writable directory, unpacked by `sudo tar` -- anyone on the box can pre-create it as a symlink or swap it between the two commands and have tar write their content as root
|
||||
# kills: no download is written to a fixed /tmp path
|
||||
# run: unit
|
||||
<<<OLD
|
||||
run_sh "{ curl -fsSL '$b/nvim-linux-$a.tar.gz' -o '$WORKDIR/nvim.tgz' || curl -fsSL '$b/nvim-linux64.tar.gz' -o '$WORKDIR/nvim.tgz'; } && [ -s '$WORKDIR/nvim.tgz' ]" \
|
||||
|| { note_fail "$key" "tarball download failed or arrived empty"; continue; }
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf '$WORKDIR/nvim.tgz' -C /opt/nvim --strip-components=1" \
|
||||
<<<NEW
|
||||
run_sh "curl -fsSL '$b/nvim-linux-$a.tar.gz' -o /tmp/nvim.tgz || curl -fsSL '$b/nvim-linux64.tar.gz' -o /tmp/nvim.tgz" \
|
||||
|| { note_fail "$key" "tarball download failed"; continue; }
|
||||
run_sh "${SUDO:+$SUDO }rm -rf /opt/nvim && ${SUDO:+$SUDO }mkdir -p /opt/nvim && ${SUDO:+$SUDO }tar -xzf /tmp/nvim.tgz -C /opt/nvim --strip-components=1" \
|
||||
<<<END
|
||||
@@ -0,0 +1,9 @@
|
||||
# what: the EXIT trap that removes the run's private download directory is gone
|
||||
# why: the directory holds whatever was fetched on the way through; leaving one behind per run turns a fix for a race into a slow leak of downloaded payloads under /tmp
|
||||
# kills: …and which does not outlive the run
|
||||
# run: unit
|
||||
<<<OLD
|
||||
trap dotup_cleanup EXIT INT TERM
|
||||
<<<NEW
|
||||
:
|
||||
<<<END
|
||||
@@ -0,0 +1,9 @@
|
||||
# what: ^t's dependency walk no longer stops at an invasive row (BUG-1, reintroduced)
|
||||
# why: filtering for `nvidia` and pressing ^t ticks the three docker rows off screen — a root-equivalent daemon group nobody looked at
|
||||
# kills: …and the invasive group it @needs stays off
|
||||
# run: unit
|
||||
<<<OLD
|
||||
go=$(printf '%s\n' "$shown" | expand_deps invasive-stop)
|
||||
<<<NEW
|
||||
go=$(printf '%s\n' "$shown" | expand_deps)
|
||||
<<<END
|
||||
@@ -0,0 +1,13 @@
|
||||
# what: ^t's second press goes back to the reverse @needs closure instead of the journal (BUG-2, reintroduced)
|
||||
# why: the reverse edges do not retract what the forward ones pulled in, so ^t ^t leaves the dependencies ticked and is not an undo
|
||||
# kills: …and ^t ^t hands that back too, node included
|
||||
# run: unit
|
||||
<<<OLD
|
||||
if [ -f "$TICK" ] && [ "$shown" = "$(sed '/^=$/,$d' "$TICK")" ]; then
|
||||
go=$(sed '1,/^=$/d' "$TICK")
|
||||
else
|
||||
go=$(printf '%s\n' "$shown" | expand_rdeps)
|
||||
fi
|
||||
<<<NEW
|
||||
go=$(printf '%s\n' "$shown" | expand_rdeps)
|
||||
<<<END
|
||||
Reference in New Issue
Block a user