commit:     3194b89d3043b9c1581203c7e07301281357585b
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Mon Jun 24 23:43:41 2024 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Jun 25 01:17:09 2024 +0000
URL:        
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=3194b89d

Add the trueof_all() and trueof_any() functions

These functions allow for it to be determined whether an arbitrary
simple command yields true for either all of an arbitrary list of
parameters or at least one of them. The simple command shall be given
each parameter, one at a time. Some examples are shown below.

trueof_all test -d -- /          /var/empty # returns 0
trueof_all test -d -- /          /dev/null  # returns 1
trueof_any test -d -- /          /dev/null  # returns 0
trueof_any test -d -- /etc/fstab /dev/null  # returns 1

Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>

 functions.sh   | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 test-functions | 44 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/functions.sh b/functions.sh
index 9336174..afc170a 100644
--- a/functions.sh
+++ b/functions.sh
@@ -454,6 +454,70 @@ trim()
        sed -e 's/^[[:space:]]\{1,\}//' -e 's/[[:space:]]\{1,\}$//'
 }
 
+#
+# Considers the parameters up to - but not including - a sentinel value as the
+# words comprising a simple command then determines whether said command
+# succeeds for all of the remaining parameters, passing them one at a time. If
+# the SENTINEL variable is set, it shall be taken as the value of the sentinel.
+# Otherwise, the value of the sentinel shall be defined as <hyphen-dash>
+# <hyphen-dash>. If the composed command is empty, the sentinel value is not
+# encountered or there are no parameters following the sentinel, the return
+# value shall be greater than 0.
+#
+trueof_all()
+{
+       local arg arg_idx i j
+
+       arg_idx=0
+       i=0
+       j=0
+       for arg; do
+               if [ "$(( arg_idx += 1 ))" -eq 1 ]; then
+                       set --
+               fi
+               if [ "$i" -gt 1 ]; then
+                       "$@" "${arg}" || return
+                       j=${arg_idx}
+               elif [ "${arg}" = "${SENTINEL-"--"}" ]; then
+                       i=${arg_idx}
+               else
+                       set -- "$@" "${arg}"
+               fi
+       done
+       test "$i" -gt 1 && test "$j" -gt "$i"
+}
+
+#
+# Considers the parameters up to - but not including - a sentinel value as the
+# words comprising a simple command then determines whether said command
+# succeeds for at least one of the remaining parameters, passing them one at a
+# time. If the SENTINEL variable is set, it shall be taken as the value of the
+# sentinel. Otherwise, the value of the sentinel shall be defined as
+# <hyphen-dash> <hyphen-dash>. If the composed command is empty, the sentinel
+# value is not encountered or there are no parameters following the sentinel,
+# the return value shall be greater than 0.
+#
+trueof_any()
+{
+       local arg arg_idx i
+
+       arg_idx=0
+       i=0
+       for arg; do
+               if [ "$(( arg_idx += 1 ))" -eq 1 ]; then
+                       set --
+               fi
+               if [ "$i" -gt 1 ]; then
+                       "$@" "${arg}" && return
+               elif [ "${arg}" = "${SENTINEL-"--"}" ]; then
+                       i=${arg_idx}
+               else
+                       set -- "$@" "${arg}"
+               fi
+       done
+       false
+}
+
 #
 # Prints a diagnostic message prefixed with the basename of the running script.
 #

diff --git a/test-functions b/test-functions
index d086e16..13be61c 100755
--- a/test-functions
+++ b/test-functions
@@ -622,6 +622,48 @@ test_is_subset() {
        iterate_tests 7 "$@"
 }
 
+test_trueof_all() {
+       set -- \
+               ge  1  N/A   N/A  N/A  N/A        N/A        \
+               ge  1  test  -d   N/A  N/A        N/A        \
+               ge  1  test  -d   --   N/A        N/A        \
+               ge  1  test  -d   --   /dev/null  N/A        \
+               ge  1  test  -d   --   /dev/null  /dev/null  \
+               eq  0  test  -d   --   /          N/A        \
+               eq  0  test  -d   --   /          /          \
+               ge  1  test  -d   --   /          /dev/null  \
+               ge  1  test  -d   --   /dev/null  /
+
+       callback() {
+               shift
+               test_description="trueof_all $(quote_args "$@")"
+               trueof_all "$@"
+       }
+
+       iterate_tests 7 "$@"
+}
+
+test_trueof_any() {
+       set -- \
+               ge  1  N/A   N/A  N/A  N/A        N/A        \
+               ge  1  test  -d   N/A  N/A        N/A        \
+               ge  1  test  -d   --   N/A        N/A        \
+               ge  1  test  -d   --   /dev/null  N/A        \
+               ge  1  test  -d   --   /dev/null  /dev/null  \
+               eq  0  test  -d   --   /          N/A        \
+               eq  0  test  -d   --   /          /          \
+               eq  0  test  -d   --   /          /dev/null  \
+               eq  0  test  -d   --   /dev/null  /
+
+       callback() {
+               shift
+               test_description="trueof_any $(quote_args "$@")"
+               trueof_any "$@"
+       }
+
+       iterate_tests 7 "$@"
+}
+
 iterate_tests() {
        slice_width=$1
        shift
@@ -694,6 +736,8 @@ test_whenceforth || rc=1
 test_parallel_run || rc=1
 test_is_anyof || rc=1
 test_is_subset || rc=1
+test_trueof_all || rc=1
+test_trueof_any || rc=1
 
 cleanup_tmpdir
 

Reply via email to