diff options
author | bill-auger <mr.j.spam.me@gmail.com> | 2022-09-18 23:39:41 -0400 |
---|---|---|
committer | bill-auger <mr.j.spam.me@gmail.com> | 2023-12-14 17:13:11 -0500 |
commit | 40ce3d91e9d53c60f0eb0696b22b428d2e35bfcd (patch) | |
tree | adc7ae823de8301a97eb7a5cbe20a39ae8fe57a3 | |
parent | 794ecfb27dc50806f2f2410fdf925277c931e2b9 (diff) |
[parabola-dependents]: housekeeping
-rwxr-xr-x | parabola-dependents | 139 |
1 files changed, 89 insertions, 50 deletions
diff --git a/parabola-dependents b/parabola-dependents index baa66e5..8f44207 100755 --- a/parabola-dependents +++ b/parabola-dependents @@ -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,6 +72,8 @@ Makedependents=() # CollectResults() declare -A HiorderDependents # CollectResults() +## helpers ## + Log() # (log_fmt [fmt_args]*) { local log_fmt=$1 @@ -75,77 +82,97 @@ Log() # (log_fmt [fmt_args]*) printf "${CBLUE}${log_fmt}${CEND}\n" ${fmt_args} >&2 } -LogError() # (source_file func_name line_n) +LogError() # (log_fmt [fmt_args]*) +{ + local log_fmt=$1 + local fmt_args="${@:2}" + + printf "${CRED}ERROR: ${log_fmt}${CEND}\n" ${fmt_args} >&2 +} + +Exit() # (log_fmt [fmt_args]*) +{ + LogError "$@" ; exit 1 ; +} + +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})" - printf "${CRED}ERROR: in ${func_name}\n${line_n}: %s${CEND}\n" "${err_loc=}" >&2 + LogError "in ${func_name}\n${line_n}: ${err_loc=}\n" } +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="--dbpath=${DB_DIR} --config=${CFG_FILE}" + readonly PACMAN_OPTS="--dbpath=${DB_DIR} --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} 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} ]] + 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 - repo-add ${TEMP_DB_NAME}.db.tar ./${dummy_pkg} &> /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 n_results 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 ...." @@ -160,11 +187,13 @@ export PATH="/code/pacman-contrib/src:${PATH}" done # compile results - Log "compiling results for ($(( ${#Makedependents[*]} + ${#dep_chains[@]} ))) dependents ...." + n_results=$(( ${#Makedependents[*]} + ${#dep_chains[@]} )) + Log "compiling results for (${n_results}) dependents ...." 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} @@ -178,37 +207,47 @@ export PATH="/code/pacman-contrib/src:${PATH}" PrintReport() { - local log_msg="\ndirect $( ! (( BE_VERBOSE )) || echo "and transitive ")dependents:" + 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 + # 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 )) + 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}}" - else is_hiorder_dep=$( (( $(tr '<' '\n' <<<${dep_chain} | wc -l) > 2 )) && echo 1 || echo 0 ) - - # display only first-order dependents - 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 + 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 + # TODO: report parabola abslibre packages with some degree of run-time dependency if (( ${#Makedependents[*]} )) - then Log "\nmakedepends dependents:" + then Log "\nbuild dependents:" printf " %s\n" ${Makedependents[*]} fi + # report arch abs packages with direct run-time dependency + # on the input package or sodep + # TODO: report arch abs packages with some degree of build-time dependency if (( BE_VERBOSE && ${#Ignored[@]} )) then Log "\narch dependents:" printf " %s\n" "${Ignored[@]}" - else echo -e "\n(plus ${#Ignored[@]} arch dependents - pass \`-v\` to see them)" + else echo -e "\n(plus ${#Ignored[@]} arch dependents)" fi + + # TODO: report arch abs packages with some degree of build-time dependency + # on the input package or sodep } Cleanup() @@ -220,15 +259,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 (( ! EUID )) || ! echo -e "${UNPRIVILEGED_MSG}" || exit 1 (( $# )) || ! echo -e "${INVALID_ARG_MSG}" || exit 1 -LANG=C +export LC_ALL=C Init CollectResults PrintReport |