aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md27
-rwxr-xr-xis_required139
-rw-r--r--is_required.bash30
3 files changed, 196 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..cb115fe
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,27 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## What this is
+
+Two files:
+- `is_required` — bash script: given a package name, searches `/var/lib/sbopkg/SBo-git/**/*.info` for entries whose `REQUIRES=` field contains that package (whole-word match), then marks each result as installed or not by checking `/var/log/packages/`
+- `is_required.bash` — bash-completion script for the above
+
+## Key design facts
+
+**`/var/log/packages` is a symlink** → `/var/lib/pkgtools/packages`. All `find` calls must use `-follow` or they return nothing.
+
+**Package name extraction** strips the last three dash-delimited fields from filenames in `/var/log/packages` (version, arch, build tag), e.g. `ffmpeg-7.1.4-x86_64-1` → `ffmpeg`.
+
+**SBo repo path** defaults to `/var/lib/sbopkg/SBo-git`; overridable via `$SBO_REPO`. Package log defaults to `/var/log/packages`; overridable via `$PKG_LOG`.
+
+**Color output** is gated on `[[ -t 1 ]]` — auto-disabled when piped/redirected.
+
+## Installing the completion
+
+```bash
+sudo cp is_required.bash /etc/bash_completion.d/is_required
+# or for the current user (requires ~/.bash_completion.d/ sourced in ~/.bashrc):
+cp is_required.bash ~/.bash_completion.d/is_required
+```
diff --git a/is_required b/is_required
new file mode 100755
index 0000000..f64c95f
--- /dev/null
+++ b/is_required
@@ -0,0 +1,139 @@
+#!/bin/bash
+# Show which SBo packages require a given package, marking installed ones.
+
+SBO_REPO="${SBO_REPO:-/var/lib/sbopkg/SBo-git}"
+PKG_LOG="${PKG_LOG:-/var/log/packages}"
+
+# Colors (disabled when stdout is not a terminal)
+if [[ -t 1 ]]; then
+ C_RESET='\033[0m'
+ C_INSTALLED='\033[1;32m' # bold green — installed
+ C_MISSING='\033[0;33m' # yellow — not installed
+ C_TARGET='\033[1;36m' # bold cyan — the queried package
+ C_CATEGORY='\033[2;37m' # dim white — category label
+ C_HEADER='\033[1;37m' # bold white — section headers
+ C_ERROR='\033[1;31m' # bold red — errors
+ C_SEP='\033[0;90m' # dark grey — separators
+else
+ C_RESET='' C_INSTALLED='' C_MISSING=''
+ C_TARGET='' C_CATEGORY='' C_HEADER='' C_ERROR='' C_SEP=''
+fi
+
+usage() {
+ cat <<EOF
+Usage: $(basename "$0") [OPTIONS] <package>
+
+Show SBo packages that list <package> in their REQUIRES field.
+
+Options:
+ -i show only installed dependents
+ -u show only uninstalled dependents
+ -r recursive: also find what requires those packages (one level)
+ -h this help
+
+Symbols:
+ [I] installed on this system
+ [ ] not installed
+EOF
+ exit 0
+}
+
+die() { printf "${C_ERROR}error:${C_RESET} %s\n" "$*" >&2; exit 1; }
+
+OPT_INSTALLED=0
+OPT_UNINSTALLED=0
+OPT_RECURSIVE=0
+
+while getopts "iurh" opt; do
+ case "$opt" in
+ i) OPT_INSTALLED=1 ;;
+ u) OPT_UNINSTALLED=1 ;;
+ r) OPT_RECURSIVE=1 ;;
+ h) usage ;;
+ *) usage ;;
+ esac
+done
+shift $((OPTIND - 1))
+
+[[ $# -lt 1 ]] && usage
+TARGET="$1"
+
+[[ -d "$SBO_REPO" ]] || die "SBo repo not found at $SBO_REPO (set \$SBO_REPO)"
+[[ -d "$PKG_LOG" ]] || die "package log not found at $PKG_LOG (set \$PKG_LOG)"
+
+# Build installed-package name set (strip version-arch-build suffix)
+declare -A INSTALLED
+while IFS= read -r entry; do
+ name="${entry##*/}" # basename
+ name="${name%-*-*-*}" # strip last three dash-fields
+ INSTALLED["$name"]=1
+done < <(find "$PKG_LOG" -maxdepth 1 -follow -type f)
+
+is_installed() { [[ -n "${INSTALLED[$1]+set}" ]]; }
+
+# Search .info files for packages that require TARGET (whole-word match)
+find_dependents() {
+ local pkg="$1"
+ grep -rl "REQUIRES=.*\b${pkg}\b" "$SBO_REPO" --include="*.info" 2>/dev/null
+}
+
+print_result() {
+ local info_file="$1"
+ local prgnam
+ prgnam=$(grep -m1 '^PRGNAM=' "$info_file" | cut -d'"' -f2)
+ local category
+ category=$(awk -F'/' '{print $(NF-2)}' <<< "$info_file")
+
+ if is_installed "$prgnam"; then
+ [[ $OPT_UNINSTALLED -eq 1 ]] && return
+ printf "${C_INSTALLED}[I] %-40s${C_RESET} ${C_CATEGORY}(%s)${C_RESET}\n" \
+ "$prgnam" "$category"
+ else
+ [[ $OPT_INSTALLED -eq 1 ]] && return
+ printf "${C_MISSING}[ ] %-40s${C_RESET} ${C_CATEGORY}(%s)${C_RESET}\n" \
+ "$prgnam" "$category"
+ fi
+}
+
+printf "${C_HEADER}Packages requiring ${C_TARGET}'%s'${C_RESET}${C_HEADER}:${C_RESET}\n" "$TARGET"
+printf "${C_SEP}%s${C_RESET}\n" "────────────────────────────────────────────────────"
+
+mapfile -t DIRECT < <(find_dependents "$TARGET")
+
+if [[ ${#DIRECT[@]} -eq 0 ]]; then
+ printf "${C_SEP}(none found)${C_RESET}\n"
+ exit 0
+fi
+
+for f in "${DIRECT[@]}"; do
+ print_result "$f"
+done | sort
+
+if [[ $OPT_RECURSIVE -eq 1 ]]; then
+ declare -A SEEN
+ for f in "${DIRECT[@]}"; do
+ prgnam=$(grep -m1 '^PRGNAM=' "$f" | cut -d'"' -f2)
+ SEEN["$prgnam"]=1
+ done
+
+ printf "\n${C_HEADER}Packages requiring those (one level up):${C_RESET}\n"
+ printf "${C_SEP}%s${C_RESET}\n" "────────────────────────────────────────────────────"
+
+ declare -A SECOND_LEVEL
+ for f in "${DIRECT[@]}"; do
+ prgnam=$(grep -m1 '^PRGNAM=' "$f" | cut -d'"' -f2)
+ while IFS= read -r f2; do
+ p2=$(grep -m1 '^PRGNAM=' "$f2" | cut -d'"' -f2)
+ [[ -z "${SEEN[$p2]+set}" && -z "${SECOND_LEVEL[$p2]+set}" ]] || continue
+ SECOND_LEVEL["$p2"]="$f2"
+ done < <(find_dependents "$prgnam")
+ done
+
+ if [[ ${#SECOND_LEVEL[@]} -eq 0 ]]; then
+ printf "${C_SEP}(none found)${C_RESET}\n"
+ else
+ for p2 in "${!SECOND_LEVEL[@]}"; do
+ print_result "${SECOND_LEVEL[$p2]}"
+ done | sort
+ fi
+fi
diff --git a/is_required.bash b/is_required.bash
new file mode 100644
index 0000000..bf90930
--- /dev/null
+++ b/is_required.bash
@@ -0,0 +1,30 @@
+# is_required(1) completion -*- shell-script -*-
+
+_is_required()
+{
+ local cur prev words cword
+ _init_completion || return
+
+ case $prev in
+ is_required)
+ ;;
+ -*)
+ ;;
+ esac
+
+ if [[ $cur == -* ]]; then
+ COMPREPLY=( $(compgen -W '-i -u -r -h' -- "$cur") )
+ return
+ fi
+
+ # Complete package names from /var/log/packages (strip version-arch-build)
+ local pkglog="${PKG_LOG:-/var/log/packages}"
+ local packages
+ packages=$(find "$pkglog" -maxdepth 1 -follow -type f 2>/dev/null \
+ | sed 's|.*/||; s/-[^-]*-[^-]*-[^-]*$//')
+
+ COMPREPLY=( $(compgen -W "$packages" -- "$cur") )
+} &&
+complete -F _is_required is_required
+
+# ex: filetype=sh