aboutsummaryrefslogtreecommitdiffstats
path: root/is_required
diff options
context:
space:
mode:
Diffstat (limited to 'is_required')
-rwxr-xr-xis_required139
1 files changed, 139 insertions, 0 deletions
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