diff options
author | Lyndon Brown <jnqnfe@gmail.com> | 2020-03-18 01:51:53 +0000 |
---|---|---|
committer | Raphaƫl Hertzog <hertzog@debian.org> | 2020-04-23 16:29:00 +0200 |
commit | 6b7c8ed4bf15175299729355f04d60dcbac1aded (patch) | |
tree | 41c5a7b3ea23cf5a601432d00850c03debb26b42 | |
parent | 89e965ccae38e46e0dda0eb5746a0960ca606589 (diff) | |
download | vyos-live-build-6b7c8ed4bf15175299729355f04d60dcbac1aded.tar.gz vyos-live-build-6b7c8ed4bf15175299729355f04d60dcbac1aded.zip |
frontend: properly handle option processing
this means that the usage goes from:
lb {-h|--help|-u|--usage|-v|--version}
lb COMMAND [OPTIONS]
to:
lb {-h|--help|-u|--usage|-v|--version}
lb [FRONTEND_OPTIONS] COMMAND [COMMAND_OPTIONS]
though it is probably not worth is to update the description in the
manpages...? hmm...
so for instance this matters for color control with --color|--no-color
(you already had full control via environment vars). previously you could
do `lb COMMAND --no-color` to turn off colour, only to find that output
at the frontend level was still coloured (the option is processed at the
command context level, not the frontend), so you might try to instead use
`lb --no-color COMMAND`, only to find that this was not supported. Well
now it is, and used at the frontend level will fully control colour output
(after the command is processed anyway).
the full set of common options are thus available (except --force) at the
frontend level, and thus for instance all Echo_*() helpers used in the
frontend will work correctly after args are processed.
furthermore usage like `lb --color --help` will actually work. (not that
color is used there, but this previously would have failed with the
frontend treating the `--color` argument as the command; that's the point!)
Gbp-Dch: Short
-rwxr-xr-x | frontend/lb | 25 | ||||
-rwxr-xr-x | functions/arguments.sh | 93 | ||||
-rwxr-xr-x | functions/init.sh | 7 | ||||
-rwxr-xr-x | functions/man.sh | 19 | ||||
-rwxr-xr-x | scripts/build/config | 2 |
5 files changed, 100 insertions, 46 deletions
diff --git a/frontend/lb b/frontend/lb index 137867be2..1d8b89ab6 100755 --- a/frontend/lb +++ b/frontend/lb @@ -19,25 +19,14 @@ DESCRIPTION="Utility to build live systems" HELP="" USAGE="lb {clean|config|build}" -case "${1}" in - -h|--help) - if [ $(which man) ]; then - man lb - else - Usage - fi - exit 0 - ;; +# Handle options up to any command +# We replace the arg set with any remaining args on return +Arguments frontend "${@}" +eval set -- "${REMAINING_ARGS}" - ""|-u|--usage) - Usage - ;; - - -v|--version) - echo "${VERSION}" - exit 0 - ;; -esac +if [ -z "${1}" ]; then + Usage +fi COMMAND="${1}" shift diff --git a/functions/arguments.sh b/functions/arguments.sh index 4f6105649..a8dd33251 100755 --- a/functions/arguments.sh +++ b/functions/arguments.sh @@ -11,23 +11,84 @@ Arguments () { + # This function is used for handling arguments both at the frontend (`lb`) + # level and at the command level, since both accept almost the same basic + # argument set, with little difference in response to them. + # + # We enlist the help of getopt here which takes care of some of the + # intricacies of parsing for us. Note that getopt does not itself + # understand the concept of "command" arguments, and the behaviour of it + # shuffling non-options (those arguments that are not options or option + # values) to the end of the argument list would present a difficulty, if it + # were not for the fact that you can control this behaviour with use of the + # `POSIXLY_CORRECT` environment variable; setting this variable causes + # getopt to stop parsing arguments once it encounters the first non-option, + # treating all remaining arguments as being non-options. Note also that + # getopt always outputs a `--` separator argument between option (including + # option value) arguments and non-option arguments. + # + # At the frontend we need getopt to only parse options up to the point of + # a command. A command as far as getopt is concerned is simply a + # "non-option" argument. Using the above mentioned `POSIXLY_CORRECT` + # environment variable when parsing for the frontend, we can thus have + # getopt process options up to the first non-option, if given, which should + # be our command. We can then pass back any remaining arguments including + # the command argument, for a second command-stage handling. If no command + # is given, this is trivial to handle. If an invalid option is used before + # a command, this is caught by getopt. + # + # When a command is run, it is passed all remaining arguments, with most + # scripts then passing them to this function, with argument parsing then + # occurring in command-context, which just so happens to use almost the same + # set of arguments for most scripts (the config command is a notable + # exception). + # + # It is true that many of the common options have no effect in the frontend + # currently, but some do, such as colour control, and others could do in + # future or during development. + # + # Note, do not worry about options unavailable in frontend mode being + # handled in the case statement, they will never reach there if used for the + # frontend (i.e. before a command), they will result in an invalid option + # error! + + local LONGOPTS="breakpoints,color,debug,help,no-color,quiet,usage,verbose,version" + local SHORTOPTS="huv" + + local IS_FRONTEND="false" + if [ "${1}" = "frontend" ]; then + shift + IS_FRONTEND="true" + else + LONGOPTS="${LONGOPTS},force" + fi + + local GETOPT_ARGS="--name=${PROGRAM} --shell sh --longoptions $LONGOPTS --options $SHORTOPTS" + local ARGUMENTS local ERR=0 - ARGUMENTS="$(getopt --longoptions breakpoints,color,debug,force,help,no-color,quiet,usage,verbose,version --name=${PROGRAM} --options huv --shell sh -- "${@}")" || ERR=$? + if [ "${IS_FRONTEND}" = "true" ]; then + ARGUMENTS="$(export POSIXLY_CORRECT=1; getopt $GETOPT_ARGS -- "${@}")" || ERR=$? + else + ARGUMENTS="$(getopt $GETOPT_ARGS -- "${@}")" || ERR=$? + fi if [ $ERR -eq 1 ]; then - Echo_error "invalid arguments" + Echo_error "Invalid argument(s)" exit 1 elif [ $ERR -ne 0 ]; then Echo_error "getopt failure" exit 1 fi + # Replace arguments with result of getopt processing (e.g. with non-options shuffled to end) + # Note that this only affects this function's parameter set, not the calling function's or + # calling script's argument set. eval set -- "${ARGUMENTS}" - while true - do - case "${1}" in + local ARG + for ARG in "$@"; do + case "${ARG}" in --breakpoints) _BREAKPOINTS="true" shift @@ -58,8 +119,16 @@ Arguments () ;; -h|--help) - Man - shift + if [ $(which man) ]; then + if [ "${IS_FRONTEND}" = "true" ]; then + man ${PROGRAM} + else + man ${PROGRAM} $(basename ${0}) + fi + exit 0 + elif [ "${IS_FRONTEND}" = "true" ]; then + Usage + fi ;; --quiet) @@ -88,9 +157,17 @@ Arguments () ;; *) - Echo_error "internal error %s" "${0}" + if [ "${IS_FRONTEND}" = "true" ]; then + # We have handled all frontend options up to what we assume to be a command + break + fi + Echo_error "Internal error, unhandled option: %s" "${ARG}" exit 1 ;; esac done + + # Return remaining args + # Much more simple than trying to deal with command substitution. + REMAINING_ARGS="$@" } diff --git a/functions/init.sh b/functions/init.sh index 1fbbd9308..c9927492e 100755 --- a/functions/init.sh +++ b/functions/init.sh @@ -25,7 +25,14 @@ Auto_build_config () Init_config_data () { + # Here we ignore the consumption of option arguments, we would have to return REMAINING_ARGS + # for use in a `set -- $REMAINING_ARGS` (or `eval set -- "$REMAINING_ARGS"`) if we wanted to + # remove them from the set of args for calling scripts to make use of, in which case we might + # as well just move use of the function out of here. Note that currently scripts taking args + # like `$_PASS` do so as the first arg to the script, thus then just ignore any following + # option args (and capture them before arg processing takes place). Arguments "${@}" + unset REMAINING_ARGS Read_conffiles $(Common_config_files) Prepare_config diff --git a/functions/man.sh b/functions/man.sh deleted file mode 100755 index 06b51a7d4..000000000 --- a/functions/man.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -## live-build(7) - System Build Scripts -## Copyright (C) 2016-2020 The Debian Live team -## Copyright (C) 2006-2015 Daniel Baumann <mail@daniel-baumann.ch> -## -## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING. -## This is free software, and you are welcome to redistribute it -## under certain conditions; see COPYING for details. - - -Man () -{ - if [ $(which man) ] - then - man ${PROGRAM} $(basename ${0}) - exit 0 - fi -} diff --git a/scripts/build/config b/scripts/build/config index 05239eae6..9805e2af0 100755 --- a/scripts/build/config +++ b/scripts/build/config @@ -179,7 +179,7 @@ Local_arguments () ARGUMENTS="$(getopt --longoptions ${LONG_OPTIONS} --name="${PROGRAM}" --options a:d:m:k:b:s:c:huv --shell sh -- "${@}")" || ERR=$? if [ $ERR -eq 1 ]; then - Echo_error "invalid arguments" + Echo_error "Invalid argument(s)" exit 1 elif [ $ERR -ne 0 ]; then Echo_error "getopt failure" |