Introduce tod - Template Open Deploy
diff --git a/util/option.sh b/util/option.sh
new file mode 100644
index 0000000..5f13a4c
--- /dev/null
+++ b/util/option.sh
@@ -0,0 +1,218 @@
+#!/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
+}