From 6da4312f5c0c4913611ef857a8df6df1951f20d2 Mon Sep 17 00:00:00 2001 From: Bryan Joshua Pedini Date: Mon, 2 Nov 2026 20:29:46 +0100 Subject: [PATCH] feat: show packages trusted during the session --- README.md | 1 + skeptical-updater | 26 +++++++++++++++++++++----- tests/unit/interactive.bats | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a0b88c8..644126d 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ other command suffixes. | `Nx` | purge now, with its now-unneeded dependencies: the purge is simulated first and the prompt lists everything it removes (`Purge su-dummy-a now? This also removes: su-dummy-b [y/N]`); the answer is read from the same stdin; the rows of every removed package leave the list. `x` refuses when other installed packages depend on the target, like `pacman -Rns`; purge the dependents first (`not purged: su-dummy-b is required by: su-dummy-a - purge the dependents first`). Rows with old version `-` (new dependencies, not installed) cannot be purged | | `N+` | trust forever: write it and its installed dependency closure to the statefile; the row leaves the list. Rows this hides are re-included if they were excluded (a trusted package is upgraded) | | `*+` / `*-` | `+` / `-` for every listed package (`*-` is an all-or-nothing toggle: when all are excluded it re-includes them) | +| `a` | show packages trusted during this session again, marked with `=`; packages already trusted before the session remain hidden | | `l` | redraw the list | | `q` | quit without upgrading (exit 0) | | `h`, `?` | help | diff --git a/skeptical-updater b/skeptical-updater index f176b95..6609ebe 100755 --- a/skeptical-updater +++ b/skeptical-updater @@ -6,7 +6,7 @@ # and zypper: list what would be upgraded, interrogate every package, remember the # ones you trust, then run the native upgrade (with per-run exclusions). # -# Version: 0.4.0 +# Version: 0.5.0 # # Specification: docs/DESIGN.md. Single file, bash >= 4.3, no runtime dependency # beyond the distro's package manager and coreutils/sed/grep (awk only on the apt @@ -23,7 +23,7 @@ export LC_ALL=C DEBIAN_FRONTEND=noninteractive # never read from or written to a file (no HISTFILE; `history -r`/`-w`/`-a` are never used). unset HISTFILE -readonly SU_VERSION=0.4.0 +readonly SU_VERSION=0.5.0 readonly SU_PROG=skeptical-updater readonly SU_STATE_HEADER='# skeptical-updater trusted packages. Columns: backend package reason added(UTC ISO-8601)' readonly SU_PROMPT_HELP=' upgrade | N? what is it | N?? full info | N- exclude this run | Nx purge now | N+ trust forever' @@ -121,6 +121,7 @@ interactive commands (one line, whitespace-separated tokens, N = number in brack consecutive Nx commands are purged together after one confirmation N+ trust it forever (with its installed dependency closure) *+ / *- apply + / - to every listed package + a show packages trusted during this session again l redraw the list q quit without upgrading (exit 0) h, ? this help @@ -148,6 +149,7 @@ session_help() { consecutive Nx commands are purged together after one confirmation N+ trust N (and its installed dependencies) forever *+ *- trust / exclude every listed package (*- again re-includes them) + a show packages trusted during this session again l redraw the list (a '*' after the number marks an AUR package) q quit without upgrading h ? this help @@ -2232,6 +2234,8 @@ maybe_refresh() { if ((opt_refresh)); then be refresh || true; fi; } R_NAME=() R_OLD=() R_NEW=() R_REPO=() R_FLAGS=() R_AUR=() R_NUM=() R_GONE=() R_EXCL=() R_NOTES=() N_IDX=() # number -> row index N_MAX=0 +SESSION_SHOW_TRUSTED=0 +declare -A SESSION_TRUSTED=() load_rows() { local out rc=0 line name old new repo flags i n=0 w aur shown @@ -2279,7 +2283,7 @@ rows_left() { # number of rows not purged row_visible() { # row_visible IDX local i=$1 ((R_GONE[i] == 0 && R_NUM[i] > 0)) || return 1 - ((opt_all)) || ! is_trusted "${R_NAME[i]}" + ((opt_all)) || ! is_trusted "${R_NAME[i]}" || { ((SESSION_SHOW_TRUSTED)) && [[ -n ${SESSION_TRUSTED[${R_NAME[i]}]+x} ]]; } } print_list() { @@ -2296,6 +2300,8 @@ print_list() { done if ((opt_all)); then say "$total upgradable, $trusted trusted (marked with =), $review to review:" + elif ((SESSION_SHOW_TRUSTED)); then + say "$total upgradable, $trusted trusted (session trusted marked with =), $review to review:" else say "$total upgradable, $trusted trusted (hidden, use --all to show), $review to review:" fi @@ -2779,9 +2785,12 @@ session_trust() { # session_trust IDX... trust_pkg "${R_NAME[i]}" "$now" R_EXCL[i]=0 done + for ((i = 0; i < ${#R_NAME[@]}; i++)); do + if ((R_NUM[i] > 0 && !R_GONE[i])) && is_trusted "${R_NAME[i]}"; then SESSION_TRUSTED[${R_NAME[i]}]=1; fi + done # a row this trust hides must not stay excluded behind the user's back for ((i = 0; i < ${#R_NAME[@]}; i++)); do - if ((R_EXCL[i] && !R_GONE[i] && !opt_all)) && is_trusted "${R_NAME[i]}"; then + if ((R_EXCL[i] && !R_GONE[i])) && is_trusted "${R_NAME[i]}" && ! row_visible "$i"; then R_EXCL[i]=0 say " (${R_NAME[i]} is trusted now: no longer excluded from this run)" fi @@ -2834,7 +2843,7 @@ session_line() { for tok in "${toks[@]}"; do if [[ ! $tok =~ $re && ! $tok =~ $name_re ]]; then case $tok in - '*+' | '*-' | l | q | h | '?') ;; + '*+' | '*-' | a | l | q | h | '?') ;; *) err "unknown command '$tok' (h for help)" return 0 @@ -2919,6 +2928,13 @@ session_line() { if ((${#idx[@]})); then session_trust "${idx[@]}"; else say "nothing to trust"; fi ;; '*-') session_toggle_all ;; + a) + SESSION_SHOW_TRUSTED=1 + for ((n = 1; n <= N_MAX; n++)); do + if num_row "$n"; then initial[$n]=$REPLY; named[${R_NAME[REPLY]}]=$REPLY; fi + done + print_list + ;; l) print_list ;; q) say "Quit: nothing was upgraded." diff --git a/tests/unit/interactive.bats b/tests/unit/interactive.bats index fb63b6c..8c13cb1 100644 --- a/tests/unit/interactive.bats +++ b/tests/unit/interactive.bats @@ -536,3 +536,22 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc assert_output --partial 'would also remove su-dummy-c' log_lacks '^apt-get -y purge' } + +@test "a shows session trusted rows without exposing previously trusted rows" { + write_state "$HEADER" "apt${T}su-dummy-c${T}user${T}2026-01-01T00:00:00Z" + run skup --no-refresh <<<$'1+\na\n2?\nq' + assert_success + assert_line '=[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo' + assert_line '=[2] su-dummy-b 1.0 -> 2.0 su-fixture:su-repo' + refute_output --partial '=[3] su-dummy-c' + assert_line 'su-dummy-b: dummy package su-dummy-b for skeptical-updater tests' +} + +@test "a works on the same line as trust and keeps removed rows hidden" { + run skup --no-refresh <<<$'3x\ny\n1+ a 2?\nq' + assert_success + assert_line 'purged: su-dummy-c' + assert_line '=[1] su-dummy-a 1.0 -> 2.0 su-fixture:su-repo' + assert_line 'su-dummy-b: dummy package su-dummy-b for skeptical-updater tests' + refute_output --partial '=[3] su-dummy-c' +}