fix(help): stop eight functions executing on --help

These eight ignore $argv entirely, so passing --help ran the command
instead of describing it. The new check shadows every external binary
they reach with a recording stub on PATH and fails if anything is
invoked. Before the fix it reported, verbatim:

    cleanup --help EXECUTED: pacman -Qtdq
    fzf-update --help EXECUTED: git clone --depth 1 https://github.com/junegunn/fzf.git /tmp/.../.fzf
    limine-edit --help EXECUTED: sudoedit /boot/limine.conf sudo limine-enroll-config sudo limine-mkinitcpio sudo sbctl sign-all
    lock --help EXECUTED: loginctl lock-session
    screensleep --help EXECUTED: busctl --user call org.kde.kglobalaccel ... invokeShortcut s Turn Off Screen
    sudo-toggle --help EXECUTED: sudo stat -c %s /etc/sudoers.d/nofail-toggle sudo tee /etc/sudoers.d/nofail-toggle
    tmux-clean --help EXECUTED: tmux list-sessions -F #{session_name} #{session_attached}
    upgrade --help EXECUTED: paru -Syu --noconfirm

cleanup's log line is the read that precedes `sudo pacman -Rns $orphans`,
which the stub suppressed by returning no orphans; on a real machine with
orphans present the removal ran.

Each now answers --help from its own comment header. The call site is the
first statement of the body, above the C4 guard, so help stays reachable
when the component is disabled and nothing side-effecting runs first.
This commit is contained in:
2026-09-07 20:04:02 -04:00
parent b424b26700
commit 037588ecf6
9 changed files with 68 additions and 0 deletions
+2
View File
@@ -14,6 +14,8 @@
# EXAMPLE
# cleanup
function cleanup --description 'Log orphans to ~/.removed_orphans and remove them'
__fish_help_header (status current-function) $argv; and return 0
set -l orphans (pacman -Qtdq)
if test -n "$orphans"
echo "📝 Logging orphans to ~/.removed_orphans..."
+2
View File
@@ -14,6 +14,8 @@
# EXAMPLE
# fzf-update
function fzf-update --description 'Install or upgrade fzf from git HEAD'
__fish_help_header (status current-function) $argv; and return 0
if test -d ~/.fzf
echo "Updating fzf..."
git -C ~/.fzf pull --ff-only
+2
View File
@@ -16,6 +16,8 @@
# EXAMPLE
# limine-edit
function limine-edit --description 'Safely edit and re-verify Limine configuration'
__fish_help_header (status current-function) $argv; and return 0
# 1. Open the config with sudoedit
sudoedit /boot/limine.conf
+2
View File
@@ -13,5 +13,7 @@
# EXAMPLE
# lock
function lock --wraps='loginctl' --description 'alias lock=loginctl'
__fish_help_header (status current-function) $argv; and return 0
loginctl lock-session
end
+2
View File
@@ -14,6 +14,8 @@
# EXAMPLE
# screensleep
function screensleep --description 'Turn off the display using KDE PowerDevil'
__fish_help_header (status current-function) $argv; and return 0
# Optional: 1-second delay to ensure no keystrokes wake it immediately
sleep 1
busctl --user call \
+2
View File
@@ -19,6 +19,8 @@
# EXAMPLE
# sudo-toggle
function sudo-toggle --description 'Toggle sudo password requirement on/off'
__fish_help_header (status current-function) $argv; and return 0
# Check the file size using sudo stat to see if our bypass rule is active
set -l file_size (sudo stat -c %s /etc/sudoers.d/nofail-toggle 2>/dev/null)
+2
View File
@@ -14,6 +14,8 @@
# EXAMPLE
# tmux-clean
function tmux-clean --description 'Kill all tmux sessions except the current one'
__fish_help_header (status current-function) $argv; and return 0
# Get a list of all session names that are NOT currently attached
set sessions (tmux list-sessions -F '#{session_name} #{session_attached}' | string match -rv ' 1$' | string split -f1 ' ')
+2
View File
@@ -21,6 +21,8 @@
# EXAMPLE
# upgrade
function upgrade --description 'Full system upgrade via paru or yay'
__fish_help_header (status current-function) $argv; and return 0
# Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled (status current-function)
set -l c_err (set_color red)
+52
View File
@@ -237,6 +237,58 @@ function test_help_renderer_degrades_safely
test $failed -eq 0
end
function test_help_never_executes_destructive_path
# These eight ignore $argv entirely, so before the header-driven help
# landed, `upgrade --help` ran `paru -Syu --noconfirm`. The check has
# to prove --help does NOT reach the destructive path *without* ever
# running it: every external binary the eight can reach is shadowed by
# a recording stub on PATH, and the recorder must stay empty.
#
# WARNING: a silent pass here means a MISSING STUB, not success. If a
# function shows neither an EXECUTED line nor its own help, its
# command is absent from the stub list below -- add it. A test that
# cannot fail proves nothing about a body that runs sudo pacman -Rns.
set -l root (realpath (dirname (status filename))/..)
set -l tmp (mktemp -d)
mkdir -p $tmp/bin
set -l log $tmp/invoked.log
touch $log
for b in sudo pacman paru yay loginctl busctl tmux systemd-inhibit \
sudoedit limine-enroll-config limine-mkinitcpio sbctl git fzf steam
printf '#!/bin/sh\necho "$(basename "$0") $*" >> %s\n' $log >$tmp/bin/$b
chmod +x $tmp/bin/$b
end
set -l failed 0
for fn in cleanup fzf-update limine-edit lock screensleep sudo-toggle \
tmux-clean upgrade
set -l out (env TERM=dumb PATH="$tmp/bin:$PATH" HOME=$tmp \
fish --no-config -c \
"set -g fish_function_path $root/functions $fish_function_path
$fn --help" 2>/dev/null)
set -l code $status
if test $code -ne 0
echo " $fn --help exited $code, expected 0"
set failed 1
end
if not contains -- $fn $out
echo " $fn --help did not print its own help"
set failed 1
end
set -l ran (string trim -- (command cat $log))
if test -n "$ran"
echo " $fn --help EXECUTED: $ran"
set failed 1
end
echo -n "" >$log
end
rm -rf $tmp
test $failed -eq 0
end
function functional_test_main
set -l names (functions -a | string match 'test_*' | sort)
set -l failed 0