blob: 857290f5c95ec7165838036384005378c79d749c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
#!/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() {
printf "Usage: %s [OPTIONS] <package>\n" "$(basename "$0")"
printf "\nShow SBo packages that list <package> in their REQUIRES field.\n"
printf "\nOptions:\n"
printf " -i show only installed dependents\n"
printf " -u show only uninstalled dependents\n"
printf " -r recursive: also find what requires those packages (one level)\n"
printf " -h this help\n"
printf "\nSymbols and colors:\n"
printf " ${C_INSTALLED}[I] installed${C_RESET} package is present in %s\n" "$PKG_LOG"
printf " ${C_MISSING}[ ] missing${C_RESET} package is not installed\n"
printf " ${C_TARGET}<package>${C_RESET} queried package name (in header)\n"
printf " ${C_CATEGORY}(category)${C_RESET} SBo category of the dependent\n"
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
|