Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison sbin/fports @ 770:56ab5c012d5f
fports: Begin a new command "fports" and fully implemented its subcommand "fports deptree".
fports is supposed to be the successor to check-ports.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Wed, 23 Oct 2024 13:56:52 +0200 |
| parents | |
| children | 43cebff4ea0d |
comparison
equal
deleted
inserted
replaced
| 769:03350d2a2af6 | 770:56ab5c012d5f |
|---|---|
| 1 #!/bin/sh | |
| 2 # -*- indent-tabs-mode: nil; -*- | |
| 3 #: | |
| 4 #: Check the version status of installed ports and compare them to | |
| 5 #: version in remote repositories and the local ports index. | |
| 6 #: | |
| 7 #: :Author: Franz Glasner | |
| 8 #: :Copyright: (c) 2017-2024 Franz Glasner. | |
| 9 #: All rights reserved. | |
| 10 #: :License: BSD 3-Clause "New" or "Revised" License. | |
| 11 #: See LICENSE for details. | |
| 12 #: If you cannot find LICENSE see | |
| 13 #: <https://opensource.org/licenses/BSD-3-Clause> | |
| 14 #: :ID: @(#)@@SIMPLEVERSIONTAG@@ | |
| 15 #: | |
| 16 | |
| 17 : # separator for shellcheck: no module-level directives below | |
| 18 | |
| 19 # shellcheck disable=SC2034 # VERSION appears unused | |
| 20 VERSION='@@VERSION@@' | |
| 21 | |
| 22 # shellcheck disable=SC2016 # no expansion | |
| 23 USAGE=' | |
| 24 USAGE: fports [ GLOBAL-OPTIONS ] COMMAND [ COMMAND-OPTIONS ] | |
| 25 | |
| 26 GLOBAL OPTIONS: | |
| 27 | |
| 28 -V Print the program name and version number to stdout and exit | |
| 29 | |
| 30 -h Print this help message to stdout and exit | |
| 31 | |
| 32 ' | |
| 33 | |
| 34 | |
| 35 _p_datadir='@@DATADIR@@' | |
| 36 [ "${_p_datadir#@@DATADIR}" = '@@' ] && _p_datadir="$(dirname "$0")"/../share/local-bsdtools | |
| 37 . "${_p_datadir}/common.subr" | |
| 38 . "${_p_datadir}/farray.sh" | |
| 39 . "${_p_datadir}/ports.subr" | |
| 40 | |
| 41 | |
| 42 #: | |
| 43 #: Configuration directory. | |
| 44 #: | |
| 45 : "${CONFIGDIR:=@@ETCDIR@@}" | |
| 46 | |
| 47 #: | |
| 48 #: Mapping configuration: installed package name -> original package name. | |
| 49 #: | |
| 50 #: Note: | |
| 51 #: This is independent of any repo | |
| 52 # | |
| 53 : "${PACKAGE_MAPPING:=${CONFIGDIR}/package-mapping.conf}" | |
| 54 | |
| 55 # shellcheck disable=SC1091 # does not exist -- cannot read | |
| 56 [ -r "${CONFIGDIR}/pkgtools.conf" ] && . "${CONFIGDIR}/pkgtools.conf" | |
| 57 | |
| 58 | |
| 59 # no unset variables | |
| 60 set -u | |
| 61 | |
| 62 | |
| 63 #: | |
| 64 #: Implementation of the "deptree" command. | |
| 65 #: | |
| 66 command_deptree() { | |
| 67 local opt opt_reversed opt_maxlevel | |
| 68 # $@ | |
| 69 | |
| 70 opt_maxlevel=0 | |
| 71 opt_reversed=no | |
| 72 while getopts "l:r" opt; do | |
| 73 case "${opt}" in | |
| 74 l) | |
| 75 opt_maxlevel=$(($OPTARG + 0));; | |
| 76 r) | |
| 77 opt_reversed=yes;; | |
| 78 \?) | |
| 79 exit 2;; | |
| 80 *) | |
| 81 fatal 2 "option handling failed";; | |
| 82 esac | |
| 83 done | |
| 84 shift $((OPTIND-1)) | |
| 85 OPTIND=1 | |
| 86 | |
| 87 if checkyesno opt_reversed; then | |
| 88 _command_deptree_reversed "${opt_maxlevel}" "$@" | |
| 89 else | |
| 90 _command_deptree_normal "${opt_maxlevel}" "$@" | |
| 91 fi | |
| 92 } | |
| 93 | |
| 94 | |
| 95 #: | |
| 96 #: Implementation of printing a "normal" dependency tree | |
| 97 #: | |
| 98 _command_deptree_normal() { | |
| 99 local maxlevel # $@ | |
| 100 | |
| 101 local pkgdeps pkgqueue curdeps pkg n v | |
| 102 | |
| 103 maxlevel="${1}" | |
| 104 shift | |
| 105 | |
| 106 # shellcheck disable=SC2034 # pkgqueue seems unused | |
| 107 pkgqueue='' | |
| 108 farray_create pkgqueue # queue (array) of packages that are queued for | |
| 109 # resolution | |
| 110 | |
| 111 for pkg in "$@"; do | |
| 112 if ! pkg query '%n' "${pkg}" 1>/dev/null 2>/dev/null ; then | |
| 113 farray_release pkgqueue | |
| 114 fatal "${EX_DATAERR}" "Package not found: ${pkg}" | |
| 115 fi | |
| 116 farray_append pkgqueue "${pkg}" | |
| 117 done | |
| 118 pkgdeps='' | |
| 119 falist_create pkgdeps # alist of packagges with its direct dependencies | |
| 120 while farray_pop pkg pkgqueue 1; do | |
| 121 if ! falist_contains pkgdeps "${pkg}"; then | |
| 122 curdeps='' | |
| 123 farray_create curdeps | |
| 124 while IFS=$' \t\n' read -r n v; do | |
| 125 [ -z "${n}" ] || [ -z "${v}" ] && continue | |
| 126 farray_append curdeps "${n}=${v}" | |
| 127 farray_append pkgqueue "${n}" | |
| 128 done <<EOF_01a8cebe-8659-4e32-87a4-bbce117e386b | |
| 129 $(LC_ALL=C.UTF-8 pkg query '%dn %dv' "${pkg}") | |
| 130 EOF_01a8cebe-8659-4e32-87a4-bbce117e386b | |
| 131 falist_set pkgdeps "${pkg}" "${curdeps}" | |
| 132 farray_release curdeps | |
| 133 curdeps='' | |
| 134 fi | |
| 135 done | |
| 136 farray_release pkgqueue | |
| 137 # falist_debug pkgdeps | |
| 138 for pkg in "$@"; do | |
| 139 _print_dependency_tree 0 "${maxlevel}" '-->' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}" | |
| 140 done | |
| 141 falist_release pkgdeps | |
| 142 } | |
| 143 | |
| 144 | |
| 145 #: | |
| 146 #: Implementation of printing a reversed dependency tree | |
| 147 #: | |
| 148 _command_deptree_reversed() { | |
| 149 local maxlevel # $@ | |
| 150 | |
| 151 local pkgdeps pkgqueue curdeps pkg n v | |
| 152 | |
| 153 maxlevel="${1}" | |
| 154 shift | |
| 155 | |
| 156 # shellcheck disable=SC2034 # pkgqueue seems unused | |
| 157 pkgqueue='' | |
| 158 farray_create pkgqueue # queue (array) of packages that are queued for | |
| 159 # resolution | |
| 160 | |
| 161 for pkg in "$@"; do | |
| 162 if ! pkg query '%n' "${pkg}" 1>/dev/null 2>/dev/null ; then | |
| 163 farray_release pkgqueue | |
| 164 fatal "${EX_DATAERR}" "Package not found: ${pkg}" | |
| 165 fi | |
| 166 farray_append pkgqueue "${pkg}" | |
| 167 done | |
| 168 pkgdeps='' | |
| 169 falist_create pkgdeps # alist of packagges with its direct dependencies | |
| 170 while farray_pop pkg pkgqueue 1; do | |
| 171 if ! falist_contains pkgdeps "${pkg}"; then | |
| 172 curdeps='' | |
| 173 farray_create curdeps | |
| 174 while IFS=$' \t\n' read -r n v; do | |
| 175 [ -z "${n}" ] || [ -z "${v}" ] && continue | |
| 176 farray_append curdeps "${n}=${v}" | |
| 177 farray_append pkgqueue "${n}" | |
| 178 done <<EOF_5079e996-c6d2-4e6d-825d-53183a64ab06 | |
| 179 $(LC_ALL=C.UTF-8 pkg query '%rn %rv' "${pkg}") | |
| 180 EOF_5079e996-c6d2-4e6d-825d-53183a64ab06 | |
| 181 falist_set pkgdeps "${pkg}" "${curdeps}" | |
| 182 farray_release curdeps | |
| 183 curdeps='' | |
| 184 fi | |
| 185 done | |
| 186 farray_release pkgqueue | |
| 187 # falist_debug pkgdeps | |
| 188 for pkg in "$@"; do | |
| 189 _print_dependency_tree 0 "${maxlevel}" '<--' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}" | |
| 190 done | |
| 191 falist_release pkgdeps | |
| 192 } | |
| 193 | |
| 194 | |
| 195 #: | |
| 196 #: Internal helper to print an indented dependency list for a package. | |
| 197 #: | |
| 198 #: Args: | |
| 199 #: $1 (int): The (indentation) level where a level of `0` is the root level | |
| 200 #: $2 (int): The maximum level (`$1`) to print to | |
| 201 #: $3 (str): The package tag to use to for non-root-levels | |
| 202 #: $4 (str): The package name | |
| 203 #: $5 (str): The package version | |
| 204 #: $6 (alist): The llist of resolved packages and their dependencies | |
| 205 #: | |
| 206 _print_dependency_tree() { | |
| 207 # $1 $2 $3 $4 $5 $6 | |
| 208 | |
| 209 local i pkg ver curdeps | |
| 210 | |
| 211 if [ "${2}" -ge 1 ]; then | |
| 212 [ "${1}" -gt "${2}" ] && return 0 | |
| 213 fi | |
| 214 | |
| 215 i="${1}" | |
| 216 while [ "${i}" -gt 1 ]; do | |
| 217 printf '%s' ' ' | |
| 218 i=$((i - 1)) | |
| 219 done | |
| 220 [ "${1}" -ne 0 ] && printf '%s ' "${3}" | |
| 221 printf '%s v%s\n' "${4}" "${5}" | |
| 222 falist_get curdeps "${6}" "${pkg}" | |
| 223 i=1 | |
| 224 while farray_tryget pkg "${curdeps}" "${i}"; do | |
| 225 ver="${pkg#*=}" | |
| 226 pkg="${pkg%%=*}" | |
| 227 _print_dependency_tree $(($1 + 1)) "${2}" "${3}" "${pkg}" "${ver}" "${6}" | |
| 228 i=$((i + 1)) | |
| 229 done | |
| 230 farray_release curdeps | |
| 231 } | |
| 232 | |
| 233 | |
| 234 # | |
| 235 # Global option handling | |
| 236 # | |
| 237 while getopts "Vh" _opt ; do | |
| 238 case "${_opt}" in | |
| 239 V) | |
| 240 printf 'fports %s\n' '@@SIMPLEVERSIONSTR@@' | |
| 241 exit 0 | |
| 242 ;; | |
| 243 h) | |
| 244 echo "${USAGE}" | |
| 245 exit 0 | |
| 246 ;; | |
| 247 \?) | |
| 248 exit 2; | |
| 249 ;; | |
| 250 *) | |
| 251 fatal 2 "option handling failed" | |
| 252 ;; | |
| 253 esac | |
| 254 done | |
| 255 | |
| 256 # | |
| 257 # Reset the Shell's option handling system to prepare for handling | |
| 258 # command-local options. | |
| 259 # | |
| 260 shift $((OPTIND-1)) | |
| 261 OPTIND=1 | |
| 262 | |
| 263 command="${1-}" | |
| 264 shift | |
| 265 | |
| 266 case "${command}" in | |
| 267 '') fatal 2 "no command given";; | |
| 268 deptree) | |
| 269 command_deptree "$@";; | |
| 270 *) | |
| 271 fatal 2 "unknown command \`${command}'";; | |
| 272 esac |
