diff options
author | bill-auger <mr.j.spam.me@gmail.com> | 2022-09-10 18:17:55 -0400 |
---|---|---|
committer | bill-auger <mr.j.spam.me@gmail.com> | 2022-09-21 06:58:47 -0400 |
commit | 97e192d6081e7e0c43ea147959323633c1c57de9 (patch) | |
tree | 85ea3ad624fdee3c4a5594518bda5513b5a959b1 | |
parent | ea94c344e8f7e42da439bde0a062fb775388c988 (diff) |
[maintenance-tools/parabola-dependents]: housekeeping
-rwxr-xr-x | src/maintenance-tools/parabola-dependents | 157 |
1 files changed, 96 insertions, 61 deletions
diff --git a/src/maintenance-tools/parabola-dependents b/src/maintenance-tools/parabola-dependents index 4b6b675..86504cb 100755 --- a/src/maintenance-tools/parabola-dependents +++ b/src/maintenance-tools/parabola-dependents @@ -3,7 +3,7 @@ readonly ABS_DIR=/packages/abslibre readonly DEBUG=0 -readonly BE_VERBOSE=$( [[ "$1" == '-v' ]] && echo 1 || echo 0 ) +readonly BE_VERBOSE=$( [[ "${1}" == '-v' ]] && echo 1 || echo 0 ) ; (( $BE_VERBOSE )) && shift ; readonly PKGBUILD_SED_RX='s|/PKGBUILD$|| ; s|([^/]*/)?([^/]+)/([^/]+)$|\2 \3|' readonly DEP=$( sed -E "${PKGBUILD_SED_RX}" <<<${1} | cut -d ' ' -f 2 ) @@ -46,7 +46,11 @@ readonly USAGE="USAGE: By default, only first-order dependents are listed, with counts of higher-order dependents. - Note: this script can take several minutes to complete, if the dependency-tree is large. + Note: This script makes no assumption regarding the state of the ABS trees. + You will need to manage them manually (eg: \`git pull && git checkout master\`). + It will however, ignore any PKGBUILDs which are not checked-in to the master branch. + + Note: This script can take several minutes to complete, if the dependency-graph is large. Options: -v @@ -57,9 +61,10 @@ readonly CBLUE='\033[0;36m' readonly CRED='\033[0;31m' readonly CEND='\033[0m' readonly SEP_CHAR='=' -DB_DIR='' # Init() -CFG_FILE='' # Init() -OPTS='' # Init() +DB_DIR='' # Init() +CFG_FILE='' # Init() +PACMAN_OPTS='' # Init() +PACTREE_OPTS='' # Init() Ignored=() # CollectResults() Dependents=() # CollectResults() @@ -67,33 +72,62 @@ Makedependents=() # CollectResults() declare -A HiorderDependents # CollectResults() -Log() # (log_fmt [args]*) +## helpers ## + +Log() # (log_fmt [fmt_args]*) +{ + local log_fmt=$1 + local fmt_args="${@:2}" + + printf "${CBLUE}${log_fmt}${CEND}\n" ${fmt_args} >&2 +} + +LogError() # (log_fmt [fmt_args]*) { - local log_fmt=$1 ; shift ; - local args="$@" + local log_fmt=$1 + local fmt_args="${@:2}" - printf "${CBLUE}${log_fmt}${CEND}\n" ${args} >&2 + printf "${CRED}ERROR: ${log_fmt}${CEND}\n" ${fmt_args} >&2 } -LogError() # (source_file func_name line_n) +LogScriptError() # (source_file func_name line_n) { local source_file="$1" local func_name=$2 local line_n=$3 + local err_loc="$(awk "(( NR == ${line_n} )) { print }" ${source_file})" + + LogError "in ${func_name}\n${line_n}: %s\n" "${err_loc}" +} - printf "${CRED}ERROR: in ${func_name}\n${line_n}: %s${CEND}\n" \ - "$(awk "(( NR == ${line_n} )) { print }" ${source_file})" >&2 +Exit() # (log_fmt [fmt_args]*) +{ + LogError "$@" ; exit 1 ; +} + +IsArchRepo() # (repo) +{ + local repo=$1 ; [[ "${repo}" =~ ^(community|core|extra|multilib|testing)$ ]] } + +## business ## + Init() { + # find or create the temporary workspace readonly DB_DIR="$( db_dir=$(ls -1 -d /tmp/${TEMP_DB_NAME}.??? 2> /dev/null | head -n 1) [[ -d "${db_dir}" ]] && echo "${db_dir}" || su $(logname) -c "mktemp -d -p /tmp -t ${TEMP_DB_NAME}.XXX" )" readonly CFG_FILE=${DB_DIR}/pacman-all.conf - readonly OPTS="--config=${CFG_FILE}" + readonly PACMAN_OPTS="--config=${CFG_FILE}" + readonly PACTREE_OPTS="${PACMAN_OPTS} --sync --reverse --unique --chain" +# TODO: `pactree --chain` is an unpublished custom feature +export PATH="/code/pacman-contrib/src:${PATH}" + + # populate or update the temporary package database if ! (( DEBUG )) || ! (( $(ls -1 /tmp/${TEMP_DB_NAME}.??? | wc -l) )) then Log "updating database ...." printf "[options]\nArchitecture = auto\n" > ${CFG_FILE} @@ -101,52 +135,45 @@ Init() for repo in ${REPOS[@]} do printf "[${repo}]\nInclude = /etc/pacman.d/mirrorlist\n" >> ${CFG_FILE} done - pacman ${OPTS} -Sy &> /dev/null - else Log "not updating database in DEBUG mode - delete ${DB_DIR} to sync" + pacman ${PACMAN_OPTS} -Sy &> /dev/null + else Log "skipping database update in DEBUG mode - delete ${DB_DIR} to sync" fi # create dummy for missing dependency package or sodep - local dep pkgbase dummy_pkg - if ! pacman ${OPTS} -Ss ^${DEP}$ &> /dev/null + local log_msg dep pkgbase dummy_pkg + if ! pacman ${PACMAN_OPTS} -Ss ^${DEP}$ &> /dev/null then if [[ "${DEP}" =~ (.*)\.so=? ]] - then Log "creating dummy package for sodep: '${DEP}'" + then log_msg="creating dummy package for sodep: '${DEP}'" dep=${DEP} ; pkgbase=$(sed 's|^\([0-9a-z@._+-]*\)|\1|' <<<${BASH_REMATCH[1]}) ; - else Log "pkgbase: '${DEP}' not found - creating dummy package" + else log_msg="pkgbase: '${DEP}' not found - creating dummy package" dep='' ; pkgbase=${DEP} ; fi + dummy_pkg=${pkgbase}-0.0.0-42-$(uname -m).pkg.tar.xz + + [[ ! -f ${DB_DIR}/${dummy_pkg} ]] && Log "${log_msg}" || break cd ${DB_DIR} printf "${DUMMY_PKGBUILD}\n" "${pkgbase}" "${dep}" > ./PKGBUILD su $(logname) -c 'makepkg --force &> /dev/null' - dummy_pkg=${pkgbase}-0.0.0-42-$(uname -m).pkg.tar.xz - [[ -f ./${dummy_pkg} ]] - - repo-add ${TEMP_DB_NAME}.db.tar ./${dummy_pkg} &> /dev/null + if [[ -f ./${dummy_pkg} ]] + then repo-add ${TEMP_DB_NAME}.db.tar ./${dummy_pkg} &> /dev/null + printf "[${TEMP_DB_NAME}]\nServer = file://${DB_DIR}\n" >> ${CFG_FILE} + pacman ${PACMAN_OPTS} -Sy &> /dev/null - Log "dummy package '${pkgbase}' created" - printf "[${TEMP_DB_NAME}]\nServer = file://${DB_DIR}\n" >> ${CFG_FILE} - - pacman ${OPTS} -Sy &> /dev/null + Log "dummy package '${pkgbase}' created" + else Exit "makepkg failed" + fi fi } -IsArchRepo() # (repo) -{ - local repo=$1 ; [[ "${repo}" =~ ^(community|core|extra|multilib|testing)$ ]] -} - CollectResults() { - local dep_chains dep_chain dep_pkg via_pkg repos repo pkgbase - -# TODO: --chain is a custom pactree feature -export PATH="/code/pacman-contrib/src:${PATH}" + local dep_chains pkgbuild repo pkgbase dep_chain dep_pkg via_pkg repos # query database for dependents Log "querying database ...." - mapfile -t dep_chains < <(pactree ${OPTS} --sync --reverse --unique --chain \ - ${DEP} | sort ) + mapfile -t dep_chains < <(pactree ${PACTREE_OPTS} ${DEP} | sort) # parse PKGBUILDs for makedepends Log "searching abslibre ...." @@ -161,11 +188,12 @@ export PATH="/code/pacman-contrib/src:${PATH}" done # compile results - Log "compiling results for ($(( ${#Makedependents[*]} + ${#dep_chains[@]} ))) dependents ...." + Log "compiling results ...." for dep_chain in "${dep_chains[@]}" do dep_pkg=$(sed 's|.*<- ||' <<<${dep_chain}) via_pkg=$(sed 's|.*\] <- \([^ ]*\).*|\1|' <<<${dep_chain}) - repos=$(pacman ${OPTS} -Si ${dep_pkg} | grep Repository | cut -d ':' -f 2 | tr -d ' ') + repos="$(pacman ${PACMAN_OPTS} -Si ${dep_pkg} | grep Repository | \ + cut -d ':' -f 2 | tr -d ' ' )" for repo in ${repos} do if IsArchRepo ${repo} @@ -179,33 +207,41 @@ export PATH="/code/pacman-contrib/src:${PATH}" PrintReport() { + local log_msg="\ndirect$( ! (( BE_VERBOSE )) || echo " and transitive") parabola dependents:" local dep_chain is_hiorder_dep via_pkg repo_pkg declare -i n_hiorder_deps - (( ${#Dependents[*]} )) && echo "direct and transitive dependents" + # report parabola abslibre packages with some degree of run-time dependency + # on the input package or sodep + (( ${#Dependents[*]} )) && Log "${log_msg}" for dep_chain in "${Dependents[@]}" - do if (( BE_VERBOSE )) - then echo "${dep_chain/ /${SEP_CHAR}}" - else is_hiorder_dep=$( (( $(tr '<' '\n' <<<${dep_chain} | wc -l) > 2 )) && echo 1 || echo 0 ) - - if ! (( is_hiorder_dep )) - then via_pkg=$(sed 's|.*\] <- \([^ ]*\).*|\1|' <<<${dep_chain}) - repo_pkg=${dep_chain/ *} - n_hiorder_deps=$(( ${HiorderDependents[${via_pkg}]} - 1 )) - echo " ${repo_pkg}${SEP_CHAR}(${n_hiorder_deps} higher-order deps)" - fi + do is_hiorder_dep=$( (( $(tr '<' '\n' <<<${dep_chain} | wc -l) > 2 )) && echo 1 || echo 0 ) + + if (( BE_VERBOSE )) + then # display all transitive dependents + echo " ${dep_chain/ /${SEP_CHAR}}" + elif ! (( is_hiorder_dep )) + then # display only first-order dependents + via_pkg=$(sed 's|.*\] <- \([^ ]*\).*|\1|' <<<${dep_chain}) + repo_pkg=${dep_chain/ *} + n_hiorder_deps=$(( ${HiorderDependents[${via_pkg}]} - 1 )) + echo " ${repo_pkg}${SEP_CHAR}(${n_hiorder_deps} higher-order deps)" fi done | column --table --separator="${SEP_CHAR}" --table-wrap=2 + # report parabola abslibre packages with direct build-time dependency + # on the input package or sodep if (( ${#Makedependents[*]} )) - then Log "\nmakedepends dependents:" + then Log "\nbuild dependents:" printf " %s\n" ${Makedependents[*]} fi - echo + # report arch abs packages with direct run-time dependency + # on the input package or sodep if (( BE_VERBOSE && ${#Ignored[@]} )) - then printf "%s${SEP_CHAR}(ignored)\n" "${Ignored[@]}" | column --table --separator="${SEP_CHAR}" - else echo "(${#Ignored[@]} ignored)" + then Log "\narch dependents:" + printf " %s\n" "${Ignored[@]}" + else echo -e "\n(plus ${#Ignored[@]} arch dependents)" fi } @@ -218,16 +254,15 @@ Cleanup() set -o errexit -o errtrace -trap 'Cleanup' EXIT INT TERM -trap 'LogError "${BASH_SOURCE[0]}" "${FUNCNAME[0]}" "${LINENO}"' ERR +trap 'Cleanup' EXIT INT TERM +trap 'LogScriptError "${BASH_SOURCE[0]}" "${FUNCNAME[0]}" "${LINENO}"' ERR -(( $BE_VERBOSE )) && shift || true -(( ! EUID )) || ! echo -e "${UNPRIVILEGED_MSG}" || exit 1 -(( $# )) || ! echo -e "${INVALID_ARG_MSG}" || exit 1 +(( ! EUID )) || ! echo -e "${UNPRIVILEGED_MSG}" || exit 1 +(( $# )) || ! echo -e "${INVALID_ARG_MSG}" || exit 1 -LANG=C +export LC_ALL=C Init CollectResults PrintReport |