From 208bf7b187bb61987a128c3a91b1324dc99f2cdb Mon Sep 17 00:00:00 2001 From: bill-auger Date: Wed, 21 Sep 2022 05:39:48 -0400 Subject: [maintenance-tools/parabola-dependents]: account for duplicate packages with different deps --- src/maintenance-tools/parabola-dependents | 63 +++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/maintenance-tools/parabola-dependents b/src/maintenance-tools/parabola-dependents index 4e6b7dc..0125f86 100755 --- a/src/maintenance-tools/parabola-dependents +++ b/src/maintenance-tools/parabola-dependents @@ -8,6 +8,9 @@ readonly DEBUG=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 ) +readonly TRANSITIVE_DEP_RX='( <- [^ ]*)' +readonly DEP_RX='([a-z]*)/([^ ]*)' +readonly DEP_CHAIN_RX="\[${DEP}\]${TRANSITIVE_DEP_RX}?${TRANSITIVE_DEP_RX}* <- ${DEP_RX}$" # readonly REPOS=( nonprism nonsystemd{-testing,} libre{-testing,} readonly REPOS=( nonprism{-testing,} nonsystemd{-testing,} libre{-testing,} @@ -233,24 +236,62 @@ export PATH="/code/pacman-contrib/src:${PATH}" CollectResults() { - local dep_chains dep_chain dep_pkg via_pkg repos repo + local dep_chains dep_chain + local via_pkg transitive_pkg found_repo dep_pkg + local repos_deps=() repo_deps dep_repo dep_deps # query database for dependents Log "querying database ...." - mapfile -t dep_chains < <(pactree ${PACTREE_OPTS} ${DEP} | sort) + mapfile -t dep_chains < <(pactree ${PACTREE_OPTS} ${DEP}) # compile results Log "compiling results ...." for dep_chain in "${dep_chains[@]}" - do # example dep_chains: - # first-order dep: '[$DEP] <- $dep_pkg' - # high-order dep: '[$DEP] <- $via_pkg <- transitive_dep <- $dep_pkg' - dep_pkg=$(sed 's|.*<- ||' <<<${dep_chain}) - via_pkg=$(sed 's|.*\] <- \([^ ]*\).*|\1|' <<<${dep_chain}) - repos="$(pacman ${PACMAN_OPTS} -Si ${dep_pkg} | grep Repository | \ - cut -d ':' -f 2 | tr -d ' ' )" - for repo in ${repos} - do if IsArchRepo ${repo} + do # `pactree` will only report one dependent package, + # even if packages with duplicate names exist in different repos. + # Presumably, it selects the first repo in pacman.conf order, as does `pacman`. + # This is problematic for the purpose of this script; + # because those duplicates do not necessarily have the same dependencies. + # In fact, that is a primary motivation for having duplicate packages. + # So, in order to ignore packages with duplicate names, + # which are not actually in the dependency chain of the input package, + # and to report packages with duplicate names + # which are actually in the dependency chain of the input package, + # we need to capture the first-order dependent ($via_pkg), + # the highest-order dependent ($dep_pkg), + # and the highest-order transitive dependent ($transitive_pkg). + # $via_pkg is the chain root node, and may be empty, + # if $dep_pkg is a direct dependent of the input package (example #1). + # $transitive_pkg is the direct dependency of the leaf node, and may be empty, + # if $dep_pkg is a direct dependent of the input package (example #1), + # or if $via_pkg is a direct dependent of $dep_pkg (example #2). + # $dep_repo is the repo containing the leaf node package under present scrutiny. + # $dep_pkg is the leaf node package under present scrutiny. + # + # Example dep_chains: + # 1. first-order dep: '[$DEP] <- $found_repo/$dep_pkg' + # 2. second-order dep: '[$DEP] <- $via_pkg <- $found_repo/$dep_pkg' + # 3. high-order dep: '[$DEP] <- $via_pkg <- $transitive_pkg <- $found_repo/$dep_pkg' + [[ "${dep_chain}" =~ ${DEP_CHAIN_RX} ]] || Exit "script regex error" + + via_pkg=${BASH_REMATCH[1]/ <- /} + transitive_pkg=${BASH_REMATCH[2]/ <- /} + found_repo=${BASH_REMATCH[3]} + dep_pkg=${BASH_REMATCH[4]} + mapfile -t repos_deps < <( ( expac ${PACMAN_OPTS} -Ss '%r/%n %D' -l ' ' ${dep_pkg} | \ + grep ^[^/]*/${dep_pkg}\ [^/]*$ || : ) | \ + sed "s|/${dep_pkg} | |" ) + + for repo_deps in "${repos_deps[@]}" + do dep_repo=$( cut -d ' ' -f 1 <<<${repo_deps}) + dep_deps="$(cut -d ' ' -f 2- <<<${repo_deps})" + + if [[ " ${dep_deps} " =~ ' '(${DEP}|${via_pkg}|${transitive_pkg})' ' ]] + then dep_chain="$(sed "s| ${found_repo}/${dep_pkg}$| ${dep_repo}/${dep_pkg}|" <<<${dep_chain})" + else continue + fi + + if IsArchRepo ${dep_repo} then ArchDependents+=( "${dep_chain}" ) else ParabolaDependents+=( "${dep_chain}" ) fi -- cgit v1.2.2