From 59d2579bdf52bcda736baff677311760c4e5943f Mon Sep 17 00:00:00 2001 From: Chris Vogel Date: Sun, 26 May 2024 19:47:35 +0200 Subject: [PATCH 1/3] =?UTF-8?q?changed=20order=20of=20`source=20=E2=80=A6`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit yunohost helpers get included first so that I can overwrite them from _common.sh --- scripts/install | 2 +- scripts/remove | 2 +- scripts/restore | 2 +- scripts/upgrade | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/install b/scripts/install index 5845dc1..878252d 100755 --- a/scripts/install +++ b/scripts/install @@ -1,8 +1,8 @@ #!/bin/bash # IMPORT GENERIC HELPERS -source _common.sh source /usr/share/yunohost/helpers +source _common.sh # https://codeberg.org/ChriChri/flohmarkt_ynh/issues/9 # check if couchdb is already installed diff --git a/scripts/remove b/scripts/remove index 9054234..1a8d7c2 100755 --- a/scripts/remove +++ b/scripts/remove @@ -6,8 +6,8 @@ # IMPORT GENERIC HELPERS #================================================= -source _common.sh source /usr/share/yunohost/helpers +source _common.sh #================================================= # STANDARD REMOVE diff --git a/scripts/restore b/scripts/restore index f1c5c5c..d337f34 100755 --- a/scripts/restore +++ b/scripts/restore @@ -1,7 +1,7 @@ #!/bin/bash -source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers +source ../settings/scripts/_common.sh # reinstall couchdb ynh_script_progression --message="Reinstalling couchdb..." --weight=40 diff --git a/scripts/upgrade b/scripts/upgrade index 76e394f..8b9c0bc 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,7 +1,7 @@ #!/bin/bash -source _common.sh source /usr/share/yunohost/helpers +source _common.sh # UPGRADE_PACKAGE if only the YunoHost package has changed # UPGRADE_APP if the upstream app version has changed From 560221861c4a0839276e8ac14bc33e1b362b7bd6 Mon Sep 17 00:00:00 2001 From: Chris Vogel Date: Mon, 27 May 2024 20:18:42 +0200 Subject: [PATCH 2/3] a corner case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` the following cases need to be taken care of '--arg=value' → works '--arg= value' → works '--arg=-value' → works '--arg= -v' or '--arg= --value' → works if not exists arg '[v]=value=' → $arg will be set to '-v' or '--value' but if exists '[v]=value=' this is not the expected behavior: → then $arg is expected to contain an empty value and '-v' or '--value' is expected to be interpreted as its own valid argument (found in use of ynh_replace_string called by ynh_add_config) solution: insert an empty arg into array arguments to be later interpreted by getopts as the missing value to --arg= ``` There's still missing to limit adding of an additional empty argument only once when the actual argument fits the actual option_flag --- scripts/_common.sh | 123 +++++++++++++++++++++++++++++++++------------ 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/scripts/_common.sh b/scripts/_common.sh index a80471a..289a90f 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -47,9 +47,9 @@ flohmarkt_old_service="flohmarkt" #================================================= # debug output -flohmarkt_debug=0 +flohmarkt_debug=1 flohmarkt_print_debug() { - if [[ $flohmarkt_debug -eq 1 ]]; then echo "$*"; fi + if [[ $flohmarkt_debug -eq 1 ]]; then echo "flohmarkt_debug: $*"; fi } # Redisgn of ynh_handle_getopts_args for flohmarkt to be tested as `flohmarkt_ynh_handle_getopts_args` @@ -114,9 +114,12 @@ flohmarkt_print_debug() { # deprecated before the last re-design of this sub) # # Requires YunoHost version 3.2.2 or higher. -flohmarkt_ynh_handle_getopts_args() { +# flohmarkt_ynh_handle_getopts_args() { +# TODO testing: +ynh_handle_getopts_args() { # Manage arguments only if there's some provided - set +o xtrace # set +x + # TODO set +o xtrace # set +x + set +x if [ $# -eq 0 ]; then ynh_print_warn --message="ynh_handle_getopts_args called without arguments" return @@ -132,12 +135,13 @@ flohmarkt_ynh_handle_getopts_args() { local option_flag="" ## go through all possible options and replace arguments with short versions flohmarkt_print_debug "arguments = '${arguments[@]}" - flohmarkt_print_debug "args_array = '${!args_array[@]}'" + flohmarkt_print_debug "args_array = (${!args_array[@]})" for option_flag in "${!args_array[@]}"; do flohmarkt_print_debug "option_flag = $option_flag" # Concatenate each option_flags of the array to build the string of arguments for getopts # Will looks like 'abcd' for -a -b -c -d - # If the value of an option_flag finish by =, it's an option with additionnal values. (e.g. --user bob or -u bob) + # If the value of an option_flag finish by =, it's an option with additionnal values. + # (e.g. --user bob or -u bob) # Check the last character of the value associate to the option_flag flohmarkt_print_debug "compare to '${args_array[$option_flag]: -1}'" if [ "${args_array[$option_flag]: -1}" = "=" ]; then @@ -153,13 +157,67 @@ flohmarkt_ynh_handle_getopts_args() { ## for one possible option: look at each argument supplied: for arg in $(seq 0 $((${#arguments[@]} - 1))); do flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" + # the following cases need to be taken care of + # '--arg=value' → works + # '--arg= value' → works + # '--arg=-value' → works + # '--arg= -v' or + # '--arg= --value' → works if not exists arg '[v]=value=' + # → $arg will be set to '-v' or '--value' + # but if exists '[v]=value=' this is not the expected behavior: + # → then $arg is expected to contain an empty value and '-v' or '--value' + # is expected to be interpreted as its own valid argument + # (found in use of ynh_replace_string called by ynh_add_config) + # solution: + # insert an empty arg into array arguments to be later interpreted by + # getopts as the missing value to --arg= +# TODO + flohmarkt_print_debug "TODO: {argument[arg]:-1}='${arguments[arg]: -1}'" + if [[ ${arguments[arg]: -1} == '=' ]] \ + && [[ "$option_flag" == 'r' ]] + # TODO && ${arguments[arg]} is actual option_flag + Dieser Teil läuft für jedes argument x Mal (jeweils 1x für jedes Element von @args_array. + Wir wollen aber nur einmal die Änderung vornehmen, und zwar genau dann, wenn das aktuelle + option_flag zum aktuellen argument[arg] passt. + then + # arg ends with a '=' + local this_argument=${arguments[arg]} + local next_argument=${arguments[arg+1]} + # for looking up next_argument in args_array remove optionally trailing '=' + next_argument=$( printf '%s' "$next_argument" | cut -d'=' -f1 ) + flohmarkt_print_debug "this_argument='$this_argument', next_argument='$next_argument'" + + # check if next_argument is a value in args_array + # → starts with '--' and the rest of the argument excluding optional trailing '=' + # of the string is a value in associative array args_array + # → or starts with '-' and the rest of the argument is a valid key in args_array + # (long argument could already have been replaced by short version before) + flohmarkt_print_debug "args_array values='${args_array[@]}'" + flohmarkt_print_debug "args_array keys='${!args_array[@]}'" + flohmarkt_print_debug "{next_argument:2}='${next_argument:2}'" + flohmarkt_print_debug "{next_argument:1:1}='${next_argument:1:1}'" + set -x + if [[ "${next_argument:0:2}" == '--' ]] \ + && [[ -n $( printf '%s ' "${args_array[@]}" | fgrep -w "${next_argument:2}" ) ]] \ + || [[ "${next_argument:0:1}" == '-' ]] \ + && [[ -n $( printf '%s ' "\"${!args_array[@]}\"" | fgrep -w "${next_argument:1:1}" ) ]] + then + # insert an empty value to array arguments to be interpreted as the value + # for argument[arg] + arguments=( ${arguments[@]:0:arg+1} '' ${arguments[@]:arg+1}) + flohmarkt_print_debug "now arguments='${arguments[@]}'" + elif [[ ${arguments[arg]} == '--replace_string=' ]] && [[ $option_flag == 'r' ]]; then + exit + fi + fi + # Replace long option with = (match the beginning of the argument) - arguments[arg]="$(printf '%s\n' "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]}/-${option_flag}/")" - flohmarkt_print_debug "sed - printf '%s\n' \"${arguments[arg]}\" | sed \"s/^--${args_array[$option_flag]}/-${option_flag} /\"" + arguments[arg]="$(printf '%s\n' "${arguments[arg]}" \ + | sed "s/^--${args_array[$option_flag]}/-${option_flag}/")" flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" # And long option without = (match the whole line) - arguments[arg]="$(printf '%s\n' "${arguments[arg]}" | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag}/")" - flohmarkt_print_debug "sed - printf '%s\n' \"${arguments[arg]}\" | sed \"s/^--${args_array[$option_flag]%=}$/-${option_flag} /\"" + arguments[arg]="$(printf '%s\n' "${arguments[arg]}" \ + | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag}/")" flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" done flohmarkt_print_debug "arguments = '${arguments[@]}'" @@ -170,9 +228,6 @@ flohmarkt_ynh_handle_getopts_args() { # The function call is necessary here to allow `getopts` to use $@ parse_arg() { flohmarkt_print_debug "========= parse_arg started ======== , arguments='$@', getopts_parameters: '$getopts_parameters'" - for ME in "$@"; do - flohmarkt_print_debug " '$ME'" - done # Initialize the index of getopts OPTIND=1 # getopts will fill $parameter with the letter of the option it has read. @@ -192,22 +247,22 @@ flohmarkt_ynh_handle_getopts_args() { # Use the long option, corresponding to the short option read by getopts, as a variable # (e.g. for [u]=user, 'user' will be used as a variable) # Also, remove '=' at the end of the long option - # The variable name will be stored in 'option_var' + # The variable name will be stored in 'option_var' as a nameref option_var="${args_array[$parameter]%=}" + flohmarkt_print_debug "option_var='$option_var'" # if there's a '=' at the end of the long option name, this option takes values if [ "${args_array[$parameter]: -1}" != "=" ]; then # no argument expected for option - set option variable to '1' - # 'eval ${option_var}' will use the content of 'option_var' - flohmarkt_print_debug "option_var='${option_var}', option_value='1'" option_value=1 - return 1 else # remove leading and trailing spaces from OPTARG OPTARG="$( printf '%s' "${OPTARG}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')" - flohmarkt_print_debug "option_var='${option_var}', OPTARG='${OPTARG}'" option_value="${OPTARG}" - return 2 fi + flohmarkt_print_debug "option_value='$option_value'" + # set shift_value according to the number of options interpreted by getopts + shift_value=$(( $OPTIND - 1 )) + flohmarkt_print_debug "shift_value='$shift_value'" fi } @@ -222,10 +277,10 @@ flohmarkt_ynh_handle_getopts_args() { # (But an associative arrays isn't always sorted in the correct order...) # Remove all ':' in getopts_parameters, if used. legacy_args=${legacy_args:-${getopts_parameters//:/}} - while [ ${#arguments} -ne 0 ]; do + while [[ -v 'arguments' ]] && [[ ${#arguments} -ne 0 ]]; do + flohmarkt_print_debug '======= start while loop =======' local shift_value=0 local option_value='' # the value to be filled into ${!option_var} - flohmarkt_print_debug '======= start while loop =======' argument=${arguments[0]} flohmarkt_print_debug "argument='$argument'" # if state once changed to positional parameter mode, all the rest of the arguments will @@ -237,7 +292,6 @@ flohmarkt_ynh_handle_getopts_args() { elif [ $positional_mode == 0 ] && [ "${argument:0:1}" == '-' ]; then flohmarkt_print_debug "getopts, arguments='${arguments[@]}', starting parse_arg" parse_arg "${arguments[@]}" - shift_value=$? else positional_mode=1 # set state to positional parameter mode flohmarkt_print_debug "positional parameter, argument='$argument'" @@ -278,22 +332,27 @@ flohmarkt_ynh_handle_getopts_args() { fi # fill option_var with value found - # if ${option_var} is an array, fill mutiple values as array cells + # if ${!option_var} is an array, fill mutiple values as array cells # otherwise concatenate them seperated by ';' - flohmarkt_print_debug "option_var '$option_var', option_value '$option_value'" + # TODO explain use of nameref + local -n option_ref=$option_var + flohmarkt_print_debug "option_ref declare: '$(declare -p option_ref)'" + flohmarkt_print_debug "'$option_var' declare: '$(declare -p $option_var)'" if declare -p $option_var | grep '^declare -a ' > /dev/null; then # hurray it's an array flohmarkt_print_debug "hurray! '$option_var' is an array." - eval ${option_var}+='("${option_value}")' - elif [[ -z ${!option_var} ]]; then - eval ${option_var}='"${option_value}"' + ${option_ref}+='("${option_value}")' + elif ! [[ -v "$option_var" ]] || [[ -z "$option_ref" ]]; then + flohmarkt_print_debug "'$option_var' is unset or empty" + option_ref=${option_value} else - eval ${option_var}+='";${option_value}"' + flohmarkt_print_debug "appending to string '$option_ref'" + option_ref+=";${option_value}" fi - flohmarkt_print_debug "option_var '$option_var', option_value '${!option_var}'" + flohmarkt_print_debug "now declared $option_var: '$(declare -p $option_var)'" # shift value off arguments array - flohmarkt_print_debug "shifting '$shift_value' off arguments" + flohmarkt_print_debug "shifting '$shift_value' off arguments='${arguments[@]}'" arguments=("${arguments[@]:${shift_value}}") done @@ -307,7 +366,7 @@ flohmarkt_ynh_handle_getopts_args() { # local copy of ynh_local_curl() to test some improvement # https://github.com/YunoHost/issues/issues/2396 # https://codeberg.org/flohmarkt/flohmarkt_ynh/issues/51 -flohmarkt_ynh_local_curl() { +ynh_local_curl() { # Curl abstraction to help with POST requests to local pages (such as installation forms) # # usage: ynh_local_curl "page" "key1=value1" "key2=value2" ... @@ -366,7 +425,7 @@ flohmarkt_ynh_local_curl() { local -a data local -a curl_opt_args # optional arguments to `curl` # Manage arguments with getopts - flohmarkt_ynh_handle_getopts_args "$@" + ynh_handle_getopts_args "$@" # Define url of page to curl # $location contains either an URL or just a page From c6a409682902b01b63120bdd4f487e91345887b0 Mon Sep 17 00:00:00 2001 From: Chris Vogel Date: Tue, 28 May 2024 10:54:23 +0200 Subject: [PATCH 3/3] 1st version that actually installed flohmarkt This version installed flohmarkt successfully. In _common.sh it overrides the yunohost core subroutines ynh_handle_getopts_args and ynh_local_curl in preperation of extending ynh_local_curl to support all the features I'd need in flohmarkt scripts (while hopefully maintaining backward compatibility). --- scripts/_common.sh | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/scripts/_common.sh b/scripts/_common.sh index 289a90f..f3da101 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -47,9 +47,11 @@ flohmarkt_old_service="flohmarkt" #================================================= # debug output -flohmarkt_debug=1 +flohmarkt_debug=0 flohmarkt_print_debug() { - if [[ $flohmarkt_debug -eq 1 ]]; then echo "flohmarkt_debug: $*"; fi + set +x + if [[ $flohmarkt_debug -eq 1 ]]; then echo "flohmarkt_debug: $*" >&2; fi + set -x } # Redisgn of ynh_handle_getopts_args for flohmarkt to be tested as `flohmarkt_ynh_handle_getopts_args` @@ -119,7 +121,6 @@ flohmarkt_print_debug() { ynh_handle_getopts_args() { # Manage arguments only if there's some provided # TODO set +o xtrace # set +x - set +x if [ $# -eq 0 ]; then ynh_print_warn --message="ynh_handle_getopts_args called without arguments" return @@ -137,6 +138,16 @@ ynh_handle_getopts_args() { flohmarkt_print_debug "arguments = '${arguments[@]}" flohmarkt_print_debug "args_array = (${!args_array[@]})" for option_flag in "${!args_array[@]}"; do + # TODO refactor: Now I'm not sure anymore this part belongs here. To make the + # this all less hard to read and understand I'm thinking at the moment that it + # would be good to split the different things done here into their own loops: + # + # 1. build the option string $getopts_parameters + # 2. go through the arguments and add empty arguments where needed to + # allow for cases like '--arg= --value' where 'value' is a valid option, too + # 3. replace long option names by short once + # 4. (possibly add empty parameters for '-a -v' in cases where -a expects a value + # and -v is a valid option, too - but I dearly hope this will not be necessary) flohmarkt_print_debug "option_flag = $option_flag" # Concatenate each option_flags of the array to build the string of arguments for getopts # Will looks like 'abcd' for -a -b -c -d @@ -156,7 +167,7 @@ ynh_handle_getopts_args() { # ${#arguments[@]} is the size of the array ## for one possible option: look at each argument supplied: for arg in $(seq 0 $((${#arguments[@]} - 1))); do - flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" + flohmarkt_print_debug "option_flag='$option_flag', arg = '$arg', argument = '${arguments[arg]}'" # the following cases need to be taken care of # '--arg=value' → works # '--arg= value' → works @@ -171,21 +182,13 @@ ynh_handle_getopts_args() { # solution: # insert an empty arg into array arguments to be later interpreted by # getopts as the missing value to --arg= -# TODO - flohmarkt_print_debug "TODO: {argument[arg]:-1}='${arguments[arg]: -1}'" - if [[ ${arguments[arg]: -1} == '=' ]] \ - && [[ "$option_flag" == 'r' ]] - # TODO && ${arguments[arg]} is actual option_flag - Dieser Teil läuft für jedes argument x Mal (jeweils 1x für jedes Element von @args_array. - Wir wollen aber nur einmal die Änderung vornehmen, und zwar genau dann, wenn das aktuelle - option_flag zum aktuellen argument[arg] passt. - then + if [[ -v arguments[arg+1] ]] && [[ ${arguments[arg]: -1} == '=' ]]; then # arg ends with a '=' local this_argument=${arguments[arg]} local next_argument=${arguments[arg+1]} # for looking up next_argument in args_array remove optionally trailing '=' next_argument=$( printf '%s' "$next_argument" | cut -d'=' -f1 ) - flohmarkt_print_debug "this_argument='$this_argument', next_argument='$next_argument'" + flohmarkt_print_debug "MISSING PARAMETER: this_argument='$this_argument', next_argument='$next_argument'" # check if next_argument is a value in args_array # → starts with '--' and the rest of the argument excluding optional trailing '=' @@ -195,32 +198,28 @@ ynh_handle_getopts_args() { flohmarkt_print_debug "args_array values='${args_array[@]}'" flohmarkt_print_debug "args_array keys='${!args_array[@]}'" flohmarkt_print_debug "{next_argument:2}='${next_argument:2}'" - flohmarkt_print_debug "{next_argument:1:1}='${next_argument:1:1}'" - set -x - if [[ "${next_argument:0:2}" == '--' ]] \ - && [[ -n $( printf '%s ' "${args_array[@]}" | fgrep -w "${next_argument:2}" ) ]] \ - || [[ "${next_argument:0:1}" == '-' ]] \ - && [[ -n $( printf '%s ' "\"${!args_array[@]}\"" | fgrep -w "${next_argument:1:1}" ) ]] + flohmarkt_print_debug "{next_argument:0:2}='${next_argument:0:2}'" + if ( [[ "${next_argument:0:2}" == '--' ]] \ + && printf '%s ' "${args_array[@]}" | fgrep -w "${next_argument:2}" > /dev/null ) \ + || ( [[ "${next_argument:0:1}" == '-' ]] \ + && printf '%s ' "${!args_array[@]}" | fgrep -w "${next_argument:1:1}" > /dev/null ) then # insert an empty value to array arguments to be interpreted as the value # for argument[arg] arguments=( ${arguments[@]:0:arg+1} '' ${arguments[@]:arg+1}) flohmarkt_print_debug "now arguments='${arguments[@]}'" - elif [[ ${arguments[arg]} == '--replace_string=' ]] && [[ $option_flag == 'r' ]]; then - exit fi fi # Replace long option with = (match the beginning of the argument) arguments[arg]="$(printf '%s\n' "${arguments[arg]}" \ | sed "s/^--${args_array[$option_flag]}/-${option_flag}/")" - flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" # And long option without = (match the whole line) arguments[arg]="$(printf '%s\n' "${arguments[arg]}" \ | sed "s/^--${args_array[$option_flag]%=}$/-${option_flag}/")" - flohmarkt_print_debug "arg = '$arg', argument = '${arguments[arg]}'" + flohmarkt_print_debug " arg = '$arg', argument = '${arguments[arg]}'" done - flohmarkt_print_debug "arguments = '${arguments[@]}'" + flohmarkt_print_debug "====> end loop: arguments = '${arguments[@]}'" done flohmarkt_print_debug '================= end first loop =================' @@ -233,7 +232,7 @@ ynh_handle_getopts_args() { # getopts will fill $parameter with the letter of the option it has read. local parameter="" getopts ":$getopts_parameters" parameter || true - flohmarkt_print_debug "after getopts - parameter='$parameter', OPTIND='$OPTIND', OPTARG='$OPTARG'" + flohmarkt_print_debug "after getopts - parameter='$parameter', OPTIND='${OPTIND:-none}', OPTARG='${OPTARG:-none}'" if [ "$parameter" = "?" ]; then ynh_die --message="Invalid argument: -${OPTARG:-}" @@ -378,6 +377,7 @@ ynh_local_curl() { # | arg: -L --location: either the PAGE part in 'https://$domain/$path/PAGE' or an URI # | arg: -u --user: login username (requires --password) # | arg: -p --password: login password +# TODO I might need a mode to GET and --line_match... # | arg: URL like 'http://doma.in/path/file.ext' # | arg: page - positional parameter legacy version of '--page' # | arg: key1=value1 - (Optional, POST only) legacy version of '--data' as positional parameter