changeset 786:b78815b47d5e

fports: deptree has now an option to print a flattened tree. The flattened tree is the transitive closure of all dependencies.
author Franz Glasner <fzglas.hg@dom66.de>
date Tue, 29 Oct 2024 11:03:22 +0100
parents 43cebff4ea0d
children 004c676c3415
files docs/man/man8/fports.rst sbin/fports
diffstat 2 files changed, 134 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/docs/man/man8/fports.rst	Mon Oct 28 14:41:15 2024 +0100
+++ b/docs/man/man8/fports.rst	Tue Oct 29 11:03:22 2024 +0100
@@ -13,7 +13,7 @@
 
 **fports -V**
 
-**fports deptree** [**-l** `maxlevel`] [**-r**] `package` ...
+**fports deptree** [**-l** `maxlevel`] [**-r**] [**t**] `package` ...
 
 
 Description
@@ -52,6 +52,11 @@
 
   .. program:: fports deptree
 
+  .. option:: -t
+
+     Instead of printing the dependencies as tree print them as a sorted
+     list. This list is the transitive closure of all dependencies.
+
   .. option:: -l <maxlevel>
 
      Limit the output to sub-levels up to `maxlevel`. To print only
--- a/sbin/fports	Mon Oct 28 14:41:15 2024 +0100
+++ b/sbin/fports	Tue Oct 29 11:03:22 2024 +0100
@@ -64,17 +64,21 @@
 #: Implementation of the "deptree" command.
 #:
 command_deptree() {
-    local opt opt_reversed opt_maxlevel
+    local opt opt_reversed opt_maxlevel opt_flat
     # $@
 
     opt_maxlevel=0
     opt_reversed=no
-    while getopts "l:r" opt; do
+    opt_flat=no
+    while getopts "l:rt" opt; do
         case "${opt}" in
             l)
                 opt_maxlevel=$(($OPTARG + 0));;
             r)
+                # shellcheck disable=SC2034
                 opt_reversed=yes;;
+            t)
+                opt_flat=yes;;
             \?)
                 exit 2;;
             *)
@@ -85,9 +89,9 @@
     OPTIND=1
 
     if checkyesno opt_reversed; then
-        _command_deptree_reversed "${opt_maxlevel}" "$@"
+        _command_deptree_reversed "${opt_maxlevel}" "${opt_flat}" "$@"
     else
-        _command_deptree_normal "${opt_maxlevel}" "$@"
+        _command_deptree_normal "${opt_maxlevel}" "${opt_flat}" "$@"
     fi
 }
 
@@ -96,18 +100,19 @@
 #: Implementation of printing a "normal" dependency tree
 #:
 _command_deptree_normal() {
-    local maxlevel     # $@
-    
-    local pkgdeps pkgqueue curdeps pkg n v
+    local maxlevel flat     # $@
+
+    local pkgdeps pkgqueue curdeps pkg n v flatdeps
 
     maxlevel="${1}"
-    shift
-    
+    flat="${2}"
+    shift 2
+
     # shellcheck disable=SC2034    # pkgqueue seems unused
     pkgqueue=''
     farray_create pkgqueue  # queue (array) of packages that are queued for
                             # resolution
-    
+
     for pkg in "$@"; do
         if ! pkg query '%n' "${pkg}" 1>/dev/null 2>/dev/null ; then
             farray_release pkgqueue
@@ -126,7 +131,7 @@
                 farray_append curdeps "${n}=${v}"
                 farray_append pkgqueue "${n}"
             done <<EOF_01a8cebe-8659-4e32-87a4-bbce117e386b
-$(LC_ALL=C.UTF-8 pkg query '%dn %dv' "${pkg}")   
+$(LC_ALL=C.UTF-8 pkg query '%dn %dv' "${pkg}")
 EOF_01a8cebe-8659-4e32-87a4-bbce117e386b
             falist_set pkgdeps "${pkg}" "${curdeps}"
             farray_release curdeps
@@ -135,9 +140,17 @@
     done
     farray_release pkgqueue
     #    falist_debug pkgdeps
-    for pkg in "$@"; do
-        _print_dependency_tree 0 "${maxlevel}" '-->' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}"
-    done
+    if checkyesno flat; then
+        for pkg in "$@"; do
+            _flatten_pkgdeps flatdeps "${pkgdeps}" "${pkg}"
+            _print_flatdeps '-->' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${flatdeps}"
+            falist_release "${flatdeps}"
+        done
+    else
+        for pkg in "$@"; do
+            _print_dependency_tree 0 "${maxlevel}" '-->' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}"
+        done
+    fi
     falist_release pkgdeps
 }
 
@@ -146,18 +159,20 @@
 #: Implementation of printing a reversed dependency tree
 #:
 _command_deptree_reversed() {
-    local maxlevel   # $@
-    
-    local pkgdeps pkgqueue curdeps pkg n v
+    local maxlevel flat  # $@
+
+    local pkgdeps pkgqueue curdeps pkg n v flatdeps
 
     maxlevel="${1}"
-    shift
-    
+    # shellcheck disable=SC2034    # appears unused
+    flat="${2}"
+    shift 2
+
     # shellcheck disable=SC2034    # pkgqueue seems unused
     pkgqueue=''
     farray_create pkgqueue  # queue (array) of packages that are queued for
                             # resolution
-    
+
     for pkg in "$@"; do
         if ! pkg query '%n' "${pkg}" 1>/dev/null 2>/dev/null ; then
             farray_release pkgqueue
@@ -176,7 +191,7 @@
                 farray_append curdeps "${n}=${v}"
                 farray_append pkgqueue "${n}"
             done <<EOF_5079e996-c6d2-4e6d-825d-53183a64ab06
-$(LC_ALL=C.UTF-8 pkg query '%rn %rv' "${pkg}")   
+$(LC_ALL=C.UTF-8 pkg query '%rn %rv' "${pkg}")
 EOF_5079e996-c6d2-4e6d-825d-53183a64ab06
             falist_set pkgdeps "${pkg}" "${curdeps}"
             farray_release curdeps
@@ -185,9 +200,17 @@
     done
     farray_release pkgqueue
     #    falist_debug pkgdeps
-    for pkg in "$@"; do
-        _print_dependency_tree 0 "${maxlevel}" '<--' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}"
-    done
+    if checkyesno flat; then
+        for pkg in "$@"; do
+            _flatten_pkgdeps flatdeps "${pkgdeps}" "${pkg}"
+            _print_flatdeps '<--' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${flatdeps}"
+            falist_release "${flatdeps}"
+        done
+    else
+        for pkg in "$@"; do
+            _print_dependency_tree 0 "${maxlevel}" '<--' "${pkg}" "$(LC_ALL=C.UTF-8 pkg query '%v' "${pkg}")" "${pkgdeps}"
+        done
+    fi
     falist_release pkgdeps
 }
 
@@ -211,7 +234,7 @@
     if [ "${2}" -ge 1 ]; then
         [ "${1}" -gt "${2}" ] && return 0
     fi
-    
+
     i="${1}"
     while [ "${i}" -gt 1 ]; do
         printf '%s' '    '
@@ -231,6 +254,86 @@
 }
 
 
+#:
+#: Args:
+#:   $1 (str): The package tag to use
+#:   $2 (str): The root package name
+#:   $3 (str): The package version of the root package in `$3`
+#:   $4 (alist): The alist of the flattened dependencies
+#:
+_print_flatdeps() {
+    # $1 $2 $3 $4
+
+    local pkgnames i n v
+
+    printf '%s v%s\n' "${2}" "${3}"
+
+    pkgnames=''
+    farray_create pkgnames
+    falist_keys pkgnames "$4"
+    farray_sort pkgnames
+    i=1
+    while farray_tryget n pkgnames "${i}"; do
+        falist_get v "${4}" "${n}"
+        printf '%s %s v%s\n' "${1}" "${n}" "${v}"
+        i=$((i + 1))
+    done
+
+    farray_release pkgnames
+}
+
+
+#:
+#: Flatten a package dependency alist.
+#:
+#: Args:
+#:   $1 (str): The variable name where to store the flattened dependencies
+#:             into. This object (alist) must be released by the caller.
+#:   $2 (str): The alist with all packages and its dependencies
+#:   $3 (str): The package for which to flatten its dependencies
+#:
+_flatten_pkgdeps() {
+    local pkgdeps rootpkg     # and $1
+
+    local alldeps queue pkg curdeps i depname depver
+
+    pkgdeps="${2}"
+    rootpkg="${3}"
+
+    falist_contains pkgdeps "${rootpkg}" || fatal "${EX_SOFTWARE}" "given package \`${rootpkg}' not in the given package dependency map"
+
+    # shellcheck disable=SC2034    # appears unused
+    queue=''
+    farray_create queue     # array with package names to be flattened
+
+    farray_append queue "${rootpkg}"
+
+    alldeps=''
+    falist_create alldeps   # alist with pkgname -> version
+    while farray_pop pkg queue 1; do
+        if ! falist_contains alldeps "${pkg}"; then
+            curdeps=''
+            falist_get curdeps pkgdeps "${pkg}"
+            i=1
+            while farray_tryget depname curdeps "${i}"; do
+                depver="${depname#*=}"
+                depname="${depname%%=*}"
+                if ! falist_contains alldeps "${depname}"; then
+                    falist_set alldeps "${depname}" "${depver}"
+                fi
+                farray_append queue "${depname}"
+                i=$((i + 1))
+            done
+            farray_release curdeps
+        fi
+    done
+
+    farray_release queue
+
+    setvar "${1}" "${alldeps}"
+}
+
+
 #
 # Global option handling
 #