From 03338d1f39777dba60f575a62cb698aef556a32e Mon Sep 17 00:00:00 2001 From: rain Date: Tue, 23 Jun 2026 16:55:16 -0400 Subject: [PATCH] Gentoo user-packages: skip package if binary exists but not in portage Some packages on tadbit have binaries installed OUTSIDE portage (bat was installed by cargo earlier; eza/fd from a previous run that the script didn't track). qlist -I correctly reports them as not-in-portage, but command -v finds them on PATH. Without this guard, every apply would re-emerge these packages, causing spurious failures (e.g. 'there are no ebuilds to satisfy app-text/bat' even though /usr/bin/bat works fine). The detection now does: 1. If qlist reports the package is in portage: skip 2. If the binary is on PATH: log + skip 3. Otherwise: add to MISSING_PKGS Same fix applied to the GURU_MISSING detection. --- ...ce_20-install-user-packages-gentoo.sh.tmpl | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/run_once_20-install-user-packages-gentoo.sh.tmpl b/run_once_20-install-user-packages-gentoo.sh.tmpl index 66dd265..e5c1a5b 100644 --- a/run_once_20-install-user-packages-gentoo.sh.tmpl +++ b/run_once_20-install-user-packages-gentoo.sh.tmpl @@ -94,21 +94,37 @@ GENTOO_PKGS=( # check for our purposes is `qlist -I ` — returns 0 if the # package is in the installed-db, 1 if not. But qlist is from # gentoolkit and may not be available. Fall back to `equery`. +# +# A package may also be installed OUTSIDE portage (e.g. cargo install +# or a tarball extract that landed a binary at /usr/bin/). In +# that case qlist reports missing but the binary exists. To avoid +# re-installing these, also check for the binary on PATH and skip +# the package if it's there. MISSING_PKGS=() for p in "${GENTOO_PKGS[@]}"; do + bin_name=$(basename "$p") + bin_on_path=0 + command -v "$bin_name" >/dev/null 2>&1 && bin_on_path=1 + if command -v qlist >/dev/null 2>&1; then - if ! qlist -I "$p" >/dev/null 2>&1; then + if qlist -I "$p" >/dev/null 2>&1; then + : # installed via portage + elif (( bin_on_path )); then + log "$p: not in portage, but $bin_name found on PATH (skipped)" + else MISSING_PKGS+=("$p") fi elif command -v equery >/dev/null 2>&1; then - if ! equery -q list "$p" 2>/dev/null | grep -q "^$p"; then + if equery -q list "$p" 2>/dev/null | grep -q "^$p"; then + : # installed via portage + elif (( bin_on_path )); then + log "$p: not in portage, but $bin_name found on PATH (skipped)" + else MISSING_PKGS+=("$p") fi else - # Last resort: try a few common binary names per package - # (most have one matching the basename) - bin_name=$(basename "$p") - if ! command -v "$bin_name" >/dev/null 2>&1; then + # Last resort: just check the binary on PATH + if ! (( bin_on_path )); then MISSING_PKGS+=("$p") fi fi @@ -143,8 +159,21 @@ GURU_PKGS=( GURU_MISSING=() for p in "${GURU_PKGS[@]}"; do bin_name=$(basename "$p") - if ! command -v "$bin_name" >/dev/null 2>&1; then - GURU_MISSING+=("$p") + bin_on_path=0 + command -v "$bin_name" >/dev/null 2>&1 && bin_on_path=1 + + if command -v qlist >/dev/null 2>&1; then + if qlist -I "$p" >/dev/null 2>&1; then + : # already in portage + elif (( bin_on_path )); then + log "$p: not in portage, but $bin_name found on PATH (skipped)" + else + GURU_MISSING+=("$p") + fi + else + if ! (( bin_on_path )); then + GURU_MISSING+=("$p") + fi fi done