[pacman-dev] [PATCH] Added the function parse_options to replace getopt
This will make makepkg work properly on systems like Mac OS X, where the default installed getopt does not handle long options. The new parse_options function tries to behave like the original getopt command as much as possible. see also: http://www.archlinux.org/pipermail/pacman-dev/2008-May/011830.html Signed-off-by: Yun Zheng Hu <yunzheng.hu@gmail.com> --- scripts/makepkg.sh.in | 81 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 79 insertions(+), 2 deletions(-) diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 6dc7db4..8e3ad25 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -1117,6 +1117,83 @@ devel_update() { fi } +## +# usage : match_long_opt( $needle, $options ) +# return : matched option +## +match_long_opt() { + local needle=$1; shift + local matches item + for item in "$@"; do + [[ "$item" =~ ^"$needle" ]] && matches="$matches $item" + done + matches=( $matches ) + [[ ${#matches[@]} == 1 ]] && echo ${matches[0]} +} + +# getopt like parser, returns 1 on error +parse_options() { + local short_options=$1; shift; + local long_options=$1; shift; + + local needs_args=0 consume_args=0 retcode=0 + local opt_args="" last_opt="" + until [ -z "$1" ]; do + local handle_opt=$((!$needs_args && !$consume_args)) + + if [[ ${1:0:2} = '--' && $handle_opt == 1 ]]; then + # handle long option + opt=${1:2} + if [ ! -z "$opt" ]; then + longopt_match=$(match_long_opt $opt ${long_options//,/ }) + longopt_real="${longopt_match/:/}" # strip possible ':' + [[ "${longopt_match}" == "${longopt_real}:" ]] && needs_args=1 + [[ ! -z "$longopt_match" ]] && printf ' --%s' "$longopt_real" || { + echo "makepkg: $(gettext "unrecognized option") '$1'" >&2 + retcode=1 + } + elif [ $consume_args == 0 ]; then + # option '--', stop parsing options + consume_args=1 + fi + elif [[ ${1:0:1} = '-' && $handle_opt == 1 ]]; then + # handle short option(s) + opts=${1:1} + local i=0 args="" + while [ $i -lt ${#opts} ]; do + opt=${opts:$((i++)):1} + [[ "$needs_args" == 1 ]] && args="${param}${opt}" && continue + [[ "$short_options" =~ "${opt}:" ]] && needs_args=1 + [[ "$short_options" =~ "${opt}" ]] && printf ' -%s' "${opt}" || { + echo "makepkg: $(gettext "invalid option") -- '$opt'" >&2 + retcode=1 + } + done + # check if the user supplied the argument directly after the option + [ ! -z "$args" ] && printf " '$param'" && needs_args=0 + else + # handle non option + [ "$needs_args" == 1 ] && printf " '$1'" && needs_args=0 + [ "$consume_args" == 1 ] && opt_args="$opt_args '$1'" + fi + last_opt="$1" + shift + done + + # check if the user forgot to supply a required argument + if [[ "$needs_args" == 1 ]]; then + if [[ ${last_opt:0:2} = '--' ]]; then + echo "makepkg: option '$last_opt' $(gettext "requires an argument")" >&2 + else + echo "makepkg: option $(gettext "requires an argument") -- '${last_opt:1}'" >&2 + fi + retcode=1 + fi + + printf " --$opt_args\n" + return $retcode +} + usage() { printf "makepkg (pacman) %s\n" "$myver" echo @@ -1182,8 +1259,8 @@ OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,source" OPT_LONG="$OPT_LONG,syncdeps,version,config:" # Pacman Options OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" -OPT_TEMP="$(getopt -o "$OPT_SHORT" -l "$OPT_LONG" -n "$(basename "$0")" -- "$@" || echo 'GETOPT GO BANG!')" -if echo "$OPT_TEMP" | grep -q 'GETOPT GO BANG!'; then +OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" +if echo "$OPT_TEMP" | grep -q 'PARSE_OPTIONS FAILED'; then # This is a small hack to stop the script bailing with 'set -e' echo; usage; exit 1 # E_INVALID_OPTION; fi -- 1.5.6.5
Yun Zheng Hu wrote:
This will make makepkg work properly on systems like Mac OS X, where the default installed getopt does not handle long options.
The new parse_options function tries to behave like the original getopt command as much as possible.
see also: http://www.archlinux.org/pipermail/pacman-dev/2008-May/011830.html
Signed-off-by: Yun Zheng Hu <yunzheng.hu@gmail.com>
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality. Allan
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality.
Do you think this can make it to the pacman 3.2.3 release?
On Mon, Dec 8, 2008 at 8:22 AM, Yun Zheng Hu <yunzheng.hu@gmail.com> wrote:
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality.
Do you think this can make it to the pacman 3.2.3 release?
We (Allan and I) talked about this last night a bit. I would like to get it in, but with a maint release especially, we don't want to have regressions. -Dan
Dan McGee wrote:
On Mon, Dec 8, 2008 at 8:22 AM, Yun Zheng Hu <yunzheng.hu@gmail.com> wrote:
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality.
Do you think this can make it to the pacman 3.2.3 release?
We (Allan and I) talked about this last night a bit. I would like to get it in, but with a maint release especially, we don't want to have regressions.
I will try and find time to give it a thorough review in the next couple of days and see if we can get it in. Allan
Allan McRae wrote:
Dan McGee wrote:
On Mon, Dec 8, 2008 at 8:22 AM, Yun Zheng Hu <yunzheng.hu@gmail.com> wrote:
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality.
Do you think this can make it to the pacman 3.2.3 release?
We (Allan and I) talked about this last night a bit. I would like to get it in, but with a maint release especially, we don't want to have regressions.
I will try and find time to give it a thorough review in the next couple of days and see if we can get it in.
I've given this a fairly thorough testing now. It even managed to deal properly with passing an argument with a space in it (which is where I thought it may fail...). It does not put unused stuff at the end, but makepkg actually does nothing about those so this does not really matter... e.g. outputting $OPT_TEMP Not patched ./makepkg --log -p "BUILD SCRIPT" foobar ==> --log -p 'BUILD SCRIPT' -- 'foobar' Patched ./makepkg2 --log -p "BUILD SCRIPT" foobar ==> --log -p 'BUILD SCRIPT' -- It would be nice to do something about adding the unused values at the end in case we ever do something with them but that should be a simple fix. I can probably add this tomorrow and pull the patch onto my working branch. Allan
Allan McRae wrote:
Allan McRae wrote:
Dan McGee wrote:
On Mon, Dec 8, 2008 at 8:22 AM, Yun Zheng Hu <yunzheng.hu@gmail.com> wrote:
Just letting the submitter know that this patch is being looked at. I have a getopt branch on my git repo where this will receive more testing before it gets pulled in. From my current testing, it looks good and we seem to have lost no functionality.
Do you think this can make it to the pacman 3.2.3 release?
We (Allan and I) talked about this last night a bit. I would like to get it in, but with a maint release especially, we don't want to have regressions.
I will try and find time to give it a thorough review in the next couple of days and see if we can get it in.
I've given this a fairly thorough testing now. It even managed to deal properly with passing an argument with a space in it (which is where I thought it may fail...). It does not put unused stuff at the end, but makepkg actually does nothing about those so this does not really matter...
e.g. outputting $OPT_TEMP
Not patched ./makepkg --log -p "BUILD SCRIPT" foobar ==> --log -p 'BUILD SCRIPT' -- 'foobar'
Patched ./makepkg2 --log -p "BUILD SCRIPT" foobar ==> --log -p 'BUILD SCRIPT' --
It would be nice to do something about adding the unused values at the end in case we ever do something with them but that should be a simple fix. I can probably add this tomorrow and pull the patch onto my working branch.
I found some other differences too. makepkg = original, makepkg2 = this patch
./makepkg -psr ==> -p 'sr' --
./makepkg2 -psr ==> -p '' --
./makepkg -sp makepkg: option requires an argument -- 'p' ==> -s -- GETOPT GO BANG!
./makepkg2 -sp makepkg: option requires an argument -- 'sp' ==> -s -p -- PARSE_OPTIONS FAILED
And just for completeness....
./makepkg fakeroot -- -s -r ==> -- 'fakeroot' '-s' '-r'
./makepkg2 fakeroot -- -s -r ==> -- '-s' '-r'
I have fixed/rewritten the patch and will send it here soon. Allan
participants (3)
-
Allan McRae
-
Dan McGee
-
Yun Zheng Hu