[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 1/8] Add core.sh and wrapper function



On Thu, 9 Apr 2015, George Dunlap wrote:
> Add core functionality and an executable to run it
> 
> Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
> ---
> CC: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
> ---
>  lib/core.sh | 147 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  raise       |  16 +++++++
>  2 files changed, 163 insertions(+)
>  create mode 100644 lib/core.sh
>  create mode 100755 raise
>
> diff --git a/lib/core.sh b/lib/core.sh
> new file mode 100644
> index 0000000..46b02e0
> --- /dev/null
> +++ b/lib/core.sh
> @@ -0,0 +1,147 @@
> +#!/usr/bin/env bash
> +
> +RAISIN_HELP=()
> +
> +# Core calling convention functionality
> +# 
> +# $arg_parse
> +#
> +#   Parse $@.  Begin with every element that a '=' in it being treated
> +#   as a variable assignment: declare the LHS a local variable and set
> +#   it to the RHS.  Once you reach an element without a '=' in it, or
> +#   a '--', put all further elements into the array args.
> +# 
> +# $requireargs VARNAME1 [VARNAME2, ...]
> +#
> +#   Check to see that VARNAME1 is defined, and throw an error if not.
> +#
> +# default VARNAME "VALUE" ; $default_post
> +#
> +#   Check to see is VARNAME is defined; if not, declare it a local
> +#   variable and set it to VALUE.
> +#
> +# Example usage:
> +#
> +#   function log()
> +#   {
> +#       local i;
> +#
> +#       $arg_parse
> +#
> +#       default tmpdir "/tmp"; $default_post
> +#
> +#       $requireargs filename
> +#
> +#       for $i in ${args[@]} ; do
> +#           echo "$i" > $tmpdir/$filename
> +#       done
> +#
> +#       [[ -n "$flower" ] && echo $flower
> +#   }
> +
> +arg_parse_cmd=\
> +"local -a args;
> +local _a;
> +local _vn;
> +local _m;
> +
> +_m=true;
> +
> +for _a in \"\$@\" ; do
> +    false && echo \"Evaluating \${_a} [[ \"\${_a/=}\" = \"\${_a}\" ]]\";
> +    if \$_m && [[ \"\${_a/=}\" != \"\${_a}\" ]] ; then
> +        false && echo Parameter;
> +        _vn=\${_a%%=*};
> +        eval \"local \$_vn\";
> +        eval \"\$_a\";
> +    elif \$_m && [[ \"\${_a}\" == \"--\" ]] ; then
> +        false && echo Separator;
> +        _m=false;
> +    else
> +        false && echo Argument;
> +        _m=false;
> +        args+=(\"\$_a\");
> +    fi;
> +done"

I am sorry but I cannot bear myself to introduce so much complexity into
the world.  raisin is supposed to be easy to read.  If we end up
actually needing something so powerful and so complex in the future we
can import it then, but I think that at the moment we can do nicely
without it.

But I do like the idea of a single unified raise script executing
commands.


> +arg_parse="eval $arg_parse_cmd"
> +
> +# Pass in either the current function name, or the name of the script
> +requireargs="eval _func=\"\$FUNCNAME\" ; eval [[ -n \\\"\$_func\\\" ]] || 
> _func=\$0 ; eval _require-args \$_func"
> +
> +function _require-args()
> +{
> +    local _arg
> +    local _args
> +
> +    _args=($@)
> +
> +    for _arg in ${_args[@]:1} ; do
> +     eval "[[ -n \"\${$_arg}\" ]] || fail \"${_args[0]}: Missing $_arg\""
> +    done
> +}
> +
> +function default()
> +{
> +    # l0: eval i="5"
> +    # l1: default_post="eval $1=\"$2\""
> +    # l3: eval "if [[ -z \"\$$1\" ]] ; then default_post=\"eval 
> \$1=\\\"$2\\\"\" ; fi"
> +    eval "if [[ -z \"\$$1\" ]] ; then default_post=\"eval local 
> \$1=\\\"$2\\\"\" ; else unset default_post ; fi"
> +}
> +
> +function fail()
> +{
> +   echo FATAL "$@" 1>&2
> +   [[ -n "$fail_cleanup" ]] && $fail_cleanup
> +   exit 1
> +}
> +
> +function info()
> +{
> +   echo INFO "$@" 1>&2
> +}
> +
> +function error()
> +{
> +   echo ERROR "$@" 1>&2
> +}
> +
> +RAISIN_HELP+=("help            List available commands")
> +function help()
> +{
> +    echo "Usage: $0 command [arguments...]"
> +    echo "  Run '$0 help' for a list of commands, or '$0 command-help' for"
> +    echo "  help on a particular command."
> +    echo
> +
> +    for i in "${RAISIN_HELP[@]}" ; do
> +     echo "$i"
> +    done
> +
> +    echo
> +
> +    exit 0
> +}
> +
> +function cmdline()
> +{
> +    local cmd;
> +
> +    [[ "$#" -eq "0" ]] && help
> +
> +    $arg_parse
> +
> +    # If the command is not defined, then print help and exit
> +    if ! type "${args[0]}" 2>/dev/null | grep -q 'function' ; then
> +     echo "Unknown function: ${args[0]}"
> +     echo
> +     help
> +    fi
> +
> +    info Running "${args[0]}"
> +    "${args[0]}" "${args[@]:1}" || exit 1
> +
> +    if ! [[ -z "$RET" ]] ; then
> +     echo $RET
> +    fi
> +}
> diff --git a/raise b/raise
> new file mode 100755
> index 0000000..7f3faae
> --- /dev/null
> +++ b/raise
> @@ -0,0 +1,16 @@
> +#!/usr/bin/env bash

It is important to "set -e" immediately to catch all possible errors:

 "-e  Exit immediately if a command exits with a non-zero status."

Then you can drop set -e from raise.sh and unraise.sh when you turn them
into libraries.


> +# Include your defaults
> +if [[ -e "./config" ]] ; then
> +    . ./config
> +fi
> +
> +# To use this as a library, set RAISIN_PATH appropriately
> +[[ -z "$RAISIN_PATH" ]] && RAISIN_PATH="$PWD/lib"
> +
> +# Then as many as the sub-libraries as you need
> +. ${RAISIN_PATH}/core.sh
> +
> +# And do your own thing rather than running commands
> +# I suggest defining a "main" function of your own and running it like this.
> +cmdline "$@"
> -- 
> 1.9.1
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.