| #!/bin/bash |
| # |
| # shared.sh - multiple utils |
| # |
| # Copyright 2019 Luigi Santivetti <luigi.santivetti@gmail.com> |
| |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the "Software"), |
| # to deal in the Software without restriction, including without limitation |
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| # and/or sell copies of the Software, and to permit persons to whom the |
| # Software is furnished to do so, subject to the following conditions: |
| |
| # The above copyright notice and this permission notice (including the next |
| # paragraph) shall be included in all copies or substantial portions of the |
| # Software. |
| |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| # ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| function __call_module |
| { |
| local -r this_module="$1" |
| |
| [ -n "$this_module" ] || { lets -l -e "module not defined"; return $s_err; } |
| |
| if is_opt "upins" "upall"; then |
| [ ! -d "$instance_d" ] && { |
| lets -l -e "trying to update an invalid instance" |
| return $s_err |
| } |
| fi |
| |
| if is_opt "check" "watch" "upins" "upall" "doins" "doall"; then |
| local __envtable; local -i ret |
| |
| __envtable="$(get_module_dependencies "envtable" $this_module)"; ret=$? |
| case "$ret" in |
| $s_ok ) |
| [ -n "$__envtable" ] && { |
| |
| # Export what's inside __envtable and check the actual table is |
| # imported as a variable. |
| eval "$__envtable" && declare -p -- "envtable" >/dev/null || { |
| lets -l -e "failed to export enviroment table" |
| return $s_err |
| } |
| |
| # envtable is successfully on the stack, throw away its |
| # textual representation. |
| unset __envtable |
| } || { |
| lets -l -e "failed to get environment table" |
| return $s_err |
| } ;; |
| * ) return $s_err ;; |
| esac |
| fi |
| |
| if is_opt "check"; then |
| ( |
| # Export external variables found |
| set -eu; eval "${envtable[$this_module]}"; set +eu |
| |
| case "${#deps[@]}" in |
| 0 ) lets -l -i "$this_module doesn't have dependencies" |
| return $s_ok ;; |
| * ) lets -l -i "$this_module depends on: ${deps[@]}" |
| are_in_modules ${deps[@]} || { |
| lets -l -w "${deps[@]} not in MODULES" |
| } ;; |
| esac |
| |
| # Check if this module correctly defines its own |
| # depmod. Return with an error if it doesn't since |
| # other options rely on this module depmod. |
| |
| source "$module_d/$this_module/$module_sh" |
| if ! declare -p -- "depmod" &>/dev/null; then |
| lets -l -e "$this_module must define 'depmod'" |
| return $s_err |
| fi |
| |
| for dep in ${deps[@]}; do |
| __is_in_array $dep ${depmod[@]} || { |
| lets -l -e "$dep not in $this_module depmod: ${depmod[@]}" |
| lets -l -e "add $dep to $this_module depmod" |
| return $s_err |
| } |
| done |
| ) |
| return $? |
| fi |
| |
| ( |
| local -a files=( ) |
| local callback |
| |
| files+=( "$module_d/$this_module/$module_sh" ) |
| files+=( "$module_d/$this_module/$holder_sh" ) |
| files+=( "$module_d/$this_module/$scheme_sh" ) |
| |
| if is_opt "doins" "upins" "upall" "doall" "watch"; then |
| |
| # Export external references |
| if test_source <(echo "${envtable[$this_module]}"); then |
| eval "${envtable[$this_module]}" || return $s_err2 |
| else |
| return $s_err2 |
| fi |
| fi |
| |
| # Source needed files |
| if test_source "${files[@]}"; then |
| for f in ${files[@]}; do source "$f" || return $s_err3; done |
| else |
| return $s_err3 |
| fi |
| |
| callback="$(declare -F -- "tod_$2" 2>/dev/null)" || return $s_err6 |
| |
| if is_opt "doins" "doall"; then |
| create_instance_d $instance_d || return $s_err4 |
| fi |
| |
| # -- Here be dragons |
| eval "$callback \"${@:2}\"" || return $s_err5 |
| ) |
| case "$?" in |
| $s_err2 ) lets -l -e "$this_module: failed to export environment" ;; |
| $s_err3 ) lets -l -e "$this_module: failed to source $f" ;; |
| $s_err4 ) lets -l -e "$this_module: failed to create instance_d" ;; |
| $s_err5 ) lets -l -e "$this_module: $callback failed" ;; |
| $s_err6 ) lets -l -w "$this_module: $callback not available" |
| return $s_ok ;; |
| $s_ok ) return $s_ok ;; |
| esac |
| |
| return $s_err |
| } |
| |
| function __option_call |
| { |
| local option="$1"; shift |
| local -a mods=( "${@}" ) |
| local modname |
| |
| is_valid_module "${mods[@]}" |
| case "$?" in |
| $s_err | $s_off_broken ) return $s_err ;; |
| $s_ok | $s_off_usable ) ;; |
| esac |
| |
| # Actually call into module code |
| for modname in ${OPTARG[@]}; do |
| __call_module $modname $option |
| [ $? -eq $s_ok ] || return $s_err |
| done |
| } |
| |
| function option_call |
| { |
| local -a mods |
| |
| mods=( $(get_modules_optarg "${@:2}") ) || return $s_err |
| # Filtered out list of requested modules |
| OPTARG=( "${mods[@]}" ) |
| |
| __option_call "$1" "${mods[@]}" >/dev/null |
| } |
| |
| # @desc : process command line options only two options allowed per invocation |
| # : at the moment. Keep it simple, keep it robust. For options details |
| # : see help.sh. |
| # : |
| # : credits to https://stackoverflow.com/a/28466267 |
| function __option_process |
| { |
| local opt; OPTIND=1 |
| |
| # Be quiet and disallow any single char option |
| local -r options=":-:" |
| local -a args |
| |
| if getopts "$options" opt; then |
| if [ "$opt" = "-" ]; then |
| opt="${OPTARG%%=*}" # Get option name |
| OPTARG="${OPTARG#$opt}" # Get option argument(s) |
| OPTARG="${OPTARG#=}" # Drop `=` if any |
| OPTARG="${OPTARG//,/ }" # Drop `,` if any |
| |
| # Early return for help |
| [ "$opt" = "help" ] && __help && return $s_ok |
| |
| is_in_options "$opt" || return $s_err2 |
| fi |
| fi |
| |
| OPTIONS[$opt]=1; option_call $opt "${OPTARG[@]}" |
| case "$?" in |
| $s_err ) lets -l -e "$opt failed"; return $s_err ;; |
| $s_ok ) lets -l -i --phew "$opt success"; return $s_ok ;; |
| esac |
| } |
| |
| function option_process |
| { |
| __option_process ${@} |
| case "$?" in |
| $s_err2 ) lets -l -e "invalid option, --help" ;; |
| $s_err ) return $s_err ;; |
| $s_ok ) return $s_ok ;; |
| esac |
| } |