From 1f8f0bd9ac4c11cdc1b9506f9f64d8192ecad4ee Mon Sep 17 00:00:00 2001 From: Alad Wenter Date: Mon, 10 Oct 2016 10:47:38 +0200 Subject: makepkg: Move parseopts from library to libmakepkg parseopts is used in makepkg and other scripts such as pacman-key as a getopt replacement. Instead of including it in those scripts via a macro, move it to libmakepkg/util/parseopts.sh and have scripts source this file where appropriate. To keep the parseopts test, a new variable was introduced: PM_LIBMAKEPKG_DIR Signed-off-by: Alad Wenter Signed-off-by: Allan McRae --- Makefile.am | 3 +- scripts/.gitignore | 2 +- scripts/Makefile.am | 14 +-- scripts/libmakepkg/util/parseopts.sh.in | 173 ++++++++++++++++++++++++++++++++ scripts/library/README | 20 ---- scripts/library/parseopts.sh | 137 ------------------------- scripts/makepkg.sh.in | 2 - scripts/pacman-db-upgrade.sh.in | 5 +- scripts/pacman-key.sh.in | 7 +- scripts/pkgdelta.sh.in | 7 +- scripts/po/POTFILES.in | 2 +- test/scripts/parseopts_test.sh | 2 +- 12 files changed, 200 insertions(+), 174 deletions(-) create mode 100644 scripts/libmakepkg/util/parseopts.sh.in delete mode 100644 scripts/library/parseopts.sh diff --git a/Makefile.am b/Makefile.am index f4ff187b..9fe3367a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,7 +39,8 @@ TEST_EXTENSIONS = .py AM_TESTS_ENVIRONMENT = \ PMTEST_UTIL_DIR=$(top_builddir)/src/util/; export PMTEST_UTIL_DIR; \ PMTEST_SCRIPT_DIR=$(top_builddir)/scripts/; export PMTEST_SCRIPT_DIR; \ - PMTEST_SCRIPTLIB_DIR=$(top_srcdir)/scripts/library/; export PMTEST_SCRIPTLIB_DIR; + PMTEST_SCRIPTLIB_DIR=$(top_srcdir)/scripts/library/; export PMTEST_SCRIPTLIB_DIR; \ + PMTEST_LIBMAKEPKG_DIR=$(top_builddir)/scripts/libmakepkg/; export PMTEST_LIBMAKEPKG_DIR; LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ $(top_srcdir)/build-aux/tap-driver.sh PY_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ diff --git a/scripts/.gitignore b/scripts/.gitignore index b0cb23fb..3a5ac8a7 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,9 +1,9 @@ makepkg makepkg-template -makepkg-wrapper pacman-db-upgrade pacman-key pkgdelta repo-add repo-elephant repo-remove +*-wrapper diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 3863a2c1..448057dc 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -36,7 +36,6 @@ EXTRA_DIST = \ LIBRARY = \ library/output_format.sh \ - library/parseopts.sh \ library/human_to_size.sh \ library/size_to_human.sh \ library/term_colors.sh @@ -97,6 +96,7 @@ LIBMAKEPKG_IN = \ libmakepkg/util.sh \ libmakepkg/util/message.sh \ libmakepkg/util/option.sh \ + libmakepkg/util/parseopts.sh \ libmakepkg/util/pkgbuild.sh \ libmakepkg/util/source.sh \ libmakepkg/util/util.sh @@ -105,7 +105,10 @@ LIBMAKEPKG_DIST = \ $(addsuffix .in, $(LIBMAKEPKG_IN)) WRAPPER = \ - makepkg-wrapper + makepkg-wrapper \ + pacman-db-upgrade-wrapper \ + pacman-key-wrapper \ + pkgdelta-wrapper COMPLETION_IN = \ completion/bash_completion \ @@ -180,7 +183,6 @@ all-am: $(COMPLETION_IN) makepkg: \ $(srcdir)/makepkg.sh.in \ $(srcdir)/wrapper.sh.in \ - $(srcdir)/library/parseopts.sh \ $(LIBMAKEPKG_IN) makepkg-template: \ @@ -197,13 +199,11 @@ pacman-db-upgrade: \ pacman-key: \ $(srcdir)/pacman-key.sh.in \ - $(srcdir)/library/output_format.sh \ - $(srcdir)/library/parseopts.sh + $(srcdir)/library/output_format.sh pkgdelta: \ $(srcdir)/pkgdelta.sh.in \ - $(srcdir)/library/output_format.sh \ - $(srcdir)/library/parseopts.sh + $(srcdir)/library/output_format.sh repo-add: \ $(srcdir)/repo-add.sh.in \ diff --git a/scripts/libmakepkg/util/parseopts.sh.in b/scripts/libmakepkg/util/parseopts.sh.in new file mode 100644 index 00000000..802275e5 --- /dev/null +++ b/scripts/libmakepkg/util/parseopts.sh.in @@ -0,0 +1,173 @@ +#!/bin/bash +# +# parseopts.sh - getopt_long-like parser +# +# Copyright (c) 2012-2016 Pacman Development Team +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# A getopt_long-like parser which portably supports longopts and +# shortopts with some GNU extensions. It does not allow for options +# with optional arguments. For both short and long opts, options +# requiring an argument should be suffixed with a colon. After the +# first argument containing the short opts, any number of valid long +# opts may be be passed. The end of the options delimiter must then be +# added, followed by the user arguments to the calling program. +# +# Recommended Usage: +# OPT_SHORT='fb:z' +# OPT_LONG=('foo' 'bar:' 'baz') +# if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then +# exit 1 +# fi +# set -- "${OPTRET[@]}" +# Returns: +# 0: parse success +# 1: parse failure (error message supplied) +parseopts() { + local opt= optarg= i= shortopts=$1 + local -a longopts=() unused_argv=() + + shift + while [[ $1 && $1 != '--' ]]; do + longopts+=("$1") + shift + done + shift + + longoptmatch() { + local o longmatch=() + for o in "${longopts[@]}"; do + if [[ ${o%:} = "$1" ]]; then + longmatch=("$o") + break + fi + [[ ${o%:} = "$1"* ]] && longmatch+=("$o") + done + + case ${#longmatch[*]} in + 1) + # success, override with opt and return arg req (0 == none, 1 == required) + opt=${longmatch%:} + if [[ $longmatch = *: ]]; then + return 1 + else + return 0 + fi ;; + 0) + # fail, no match found + return 255 ;; + *) + # fail, ambiguous match + printf "${0##*/}: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1" + printf " '%s'" "${longmatch[@]%:}" + printf '\n' + return 254 ;; + esac >&2 + } + + while (( $# )); do + case $1 in + --) # explicit end of options + shift + break + ;; + -[!-]*) # short option + for (( i = 1; i < ${#1}; i++ )); do + opt=${1:i:1} + + # option doesn't exist + if [[ $shortopts != *$opt* ]]; then + printf "${0##*/}: $(gettext "invalid option") -- '%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + fi + + OPTRET+=("-$opt") + # option requires optarg + if [[ $shortopts = *$opt:* ]]; then + # if we're not at the end of the option chunk, the rest is the optarg + if (( i < ${#1} - 1 )); then + OPTRET+=("${1:i+1}") + break + # if we're at the end, grab the the next positional, if it exists + elif (( i == ${#1} - 1 )) && [[ $2 ]]; then + OPTRET+=("$2") + shift + break + # parse failure + else + printf "${0##*/}: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + fi + fi + done + ;; + --?*=*|--?*) # long option + IFS='=' read -r opt optarg <<< "${1#--}" + longoptmatch "$opt" + case $? in + 0) + # parse failure + if [[ $optarg ]]; then + printf "${0##*/}: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2 + OPTRET=(--) + return 1 + # --longopt + else + OPTRET+=("--$opt") + fi + ;; + 1) + # --longopt=optarg + if [[ $optarg ]]; then + OPTRET+=("--$opt" "$optarg") + # --longopt optarg + elif [[ $2 ]]; then + OPTRET+=("--$opt" "$2" ) + shift + # parse failure + else + printf "${0##*/}: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2 + OPTRET=(--) + return 1 + fi + ;; + 254) + # ambiguous option -- error was reported for us by longoptmatch() + OPTRET=(--) + return 1 + ;; + 255) + # parse failure + printf "${0##*/}: $(gettext "invalid option") '--%s'\n" "$opt" >&2 + OPTRET=(--) + return 1 + ;; + esac + ;; + *) # non-option arg encountered, add it as a parameter + unused_argv+=("$1") + ;; + esac + shift + done + + # add end-of-opt terminator and any leftover positional parameters + OPTRET+=('--' "${unused_argv[@]}" "$@") + unset longoptmatch + + return 0 +} diff --git a/scripts/library/README b/scripts/library/README index e9615a2e..a9d15f1e 100644 --- a/scripts/library/README +++ b/scripts/library/README @@ -8,26 +8,6 @@ stdout and can be silenced by defining 'QUIET'. The 'warning' and 'error' functions print to stderr with the appropriate prefix added to the message. -parseopts.sh: -A getopt_long-like parser which portably supports longopts and shortopts -with some GNU extensions. It does not allow for options with optional -arguments. For both short and long opts, options requiring an argument -should be suffixed with a colon. After the first argument containing -the short opts, any number of valid long opts may be be passed. The end -of the options delimiter must then be added, followed by the user arguments -to the calling program. - -Recommended Usage: - OPT_SHORT='fb:z' - OPT_LONG=('foo' 'bar:' 'baz') - if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then - exit 1 - fi - set -- "${OPTRET[@]}" -Returns: - 0: parse success - 1: parse failure (error message supplied) - human_to_size.sh: A function to convert human readable sizes (such as "5.3 GiB") to raw byte equivalents. base10 and base2 suffixes are supported, case sensitively. If diff --git a/scripts/library/parseopts.sh b/scripts/library/parseopts.sh deleted file mode 100644 index cf6aa6c6..00000000 --- a/scripts/library/parseopts.sh +++ /dev/null @@ -1,137 +0,0 @@ -# getopt-like parser -parseopts() { - local opt= optarg= i= shortopts=$1 - local -a longopts=() unused_argv=() - - shift - while [[ $1 && $1 != '--' ]]; do - longopts+=("$1") - shift - done - shift - - longoptmatch() { - local o longmatch=() - for o in "${longopts[@]}"; do - if [[ ${o%:} = "$1" ]]; then - longmatch=("$o") - break - fi - [[ ${o%:} = "$1"* ]] && longmatch+=("$o") - done - - case ${#longmatch[*]} in - 1) - # success, override with opt and return arg req (0 == none, 1 == required) - opt=${longmatch%:} - if [[ $longmatch = *: ]]; then - return 1 - else - return 0 - fi ;; - 0) - # fail, no match found - return 255 ;; - *) - # fail, ambiguous match - printf "@SCRIPTNAME@: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1" - printf " '%s'" "${longmatch[@]%:}" - printf '\n' - return 254 ;; - esac >&2 - } - - while (( $# )); do - case $1 in - --) # explicit end of options - shift - break - ;; - -[!-]*) # short option - for (( i = 1; i < ${#1}; i++ )); do - opt=${1:i:1} - - # option doesn't exist - if [[ $shortopts != *$opt* ]]; then - printf "@SCRIPTNAME@: $(gettext "invalid option") -- '%s'\n" "$opt" >&2 - OPTRET=(--) - return 1 - fi - - OPTRET+=("-$opt") - # option requires optarg - if [[ $shortopts = *$opt:* ]]; then - # if we're not at the end of the option chunk, the rest is the optarg - if (( i < ${#1} - 1 )); then - OPTRET+=("${1:i+1}") - break - # if we're at the end, grab the the next positional, if it exists - elif (( i == ${#1} - 1 )) && [[ $2 ]]; then - OPTRET+=("$2") - shift - break - # parse failure - else - printf "@SCRIPTNAME@: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2 - OPTRET=(--) - return 1 - fi - fi - done - ;; - --?*=*|--?*) # long option - IFS='=' read -r opt optarg <<< "${1#--}" - longoptmatch "$opt" - case $? in - 0) - # parse failure - if [[ $optarg ]]; then - printf "@SCRIPTNAME@: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2 - OPTRET=(--) - return 1 - # --longopt - else - OPTRET+=("--$opt") - fi - ;; - 1) - # --longopt=optarg - if [[ $optarg ]]; then - OPTRET+=("--$opt" "$optarg") - # --longopt optarg - elif [[ $2 ]]; then - OPTRET+=("--$opt" "$2" ) - shift - # parse failure - else - printf "@SCRIPTNAME@: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2 - OPTRET=(--) - return 1 - fi - ;; - 254) - # ambiguous option -- error was reported for us by longoptmatch() - OPTRET=(--) - return 1 - ;; - 255) - # parse failure - printf "@SCRIPTNAME@: $(gettext "invalid option") '--%s'\n" "$opt" >&2 - OPTRET=(--) - return 1 - ;; - esac - ;; - *) # non-option arg encountered, add it as a parameter - unused_argv+=("$1") - ;; - esac - shift - done - - # add end-of-opt terminator and any leftover positional parameters - OPTRET+=('--' "${unused_argv[@]}" "$@") - unset longoptmatch - - return 0 -} diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 82c9367b..fd5c2f5b 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -1153,8 +1153,6 @@ run_split_packaging() { pkgname=("${pkgname_backup[@]}") } -m4_include(library/parseopts.sh) - usage() { printf "makepkg (pacman) %s\n" "$makepkg_version" echo diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in index 79e1c590..2bf444e1 100644 --- a/scripts/pacman-db-upgrade.sh.in +++ b/scripts/pacman-db-upgrade.sh.in @@ -30,7 +30,10 @@ declare -r myver='@PACKAGE_VERSION@' m4_include(library/output_format.sh) -m4_include(library/parseopts.sh) +LIBRARY=${LIBRARY:-'@libmakepkgdir@'} + +# Import parseopts.sh +source "$LIBRARY"/util/parseopts.sh usage() { printf "pacman-db-upgrade (pacman) %s\n" "${myver}" diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index ffefc68c..81bea0be 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -26,6 +26,11 @@ export TEXTDOMAINDIR='@localedir@' declare -r myver="@PACKAGE_VERSION@" +LIBRARY=${LIBRARY:-'@libmakepkgdir@'} + +# Import parseopts.sh +source "$LIBRARY"/util/parseopts.sh + # Options ADD=0 DELETE=0 @@ -50,8 +55,6 @@ DEFAULT_KEYSERVER='hkp://pool.sks-keyservers.net' m4_include(library/output_format.sh) -m4_include(library/parseopts.sh) - usage() { printf "pacman-key (pacman) %s\n" ${myver} echo diff --git a/scripts/pkgdelta.sh.in b/scripts/pkgdelta.sh.in index fe63974d..9f87185b 100644 --- a/scripts/pkgdelta.sh.in +++ b/scripts/pkgdelta.sh.in @@ -28,6 +28,12 @@ export TEXTDOMAINDIR='@localedir@' declare -r myver='@PACKAGE_VERSION@' +LIBRARY=${LIBRARY:-'@libmakepkgdir@'} + +# Import parseopts.sh +source "$LIBRARY"/util/parseopts.sh + +# Options QUIET=0 USE_COLOR='y' @@ -41,7 +47,6 @@ max_delta_size=70 # ensure we have a sane umask set umask 0022 -m4_include(library/parseopts.sh) m4_include(library/output_format.sh) # print usage instructions diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in index 4792bdfa..aa9e6764 100644 --- a/scripts/po/POTFILES.in +++ b/scripts/po/POTFILES.in @@ -49,6 +49,6 @@ scripts/libmakepkg/tidy/staticlibs.sh.in scripts/libmakepkg/tidy/strip.sh.in scripts/libmakepkg/tidy/zipman.sh.in scripts/libmakepkg/util/message.sh.in +scripts/libmakepkg/util/parseopts.sh.in scripts/libmakepkg/util/source.sh.in scripts/library/output_format.sh -scripts/library/parseopts.sh diff --git a/test/scripts/parseopts_test.sh b/test/scripts/parseopts_test.sh index a8738a4c..a5821986 100755 --- a/test/scripts/parseopts_test.sh +++ b/test/scripts/parseopts_test.sh @@ -3,7 +3,7 @@ source "$(dirname "$0")"/../tap.sh || exit 1 # source the library function -lib=${1:-${PMTEST_SCRIPTLIB_DIR}parseopts.sh} +lib=${1:-${PMTEST_LIBMAKEPKG_DIR}util/parseopts.sh} if [[ -z $lib || ! -f $lib ]]; then tap_bail "parseopts library ($lib) could not be located" exit 1 -- cgit v1.2.3-24-g4f1b