blob: 0734dd544bd469b50c3145488fe75e825531df32 [file] [log] [blame]
Luigi Santivetti0fdd4702020-06-22 19:00:32 +01001#!/bin/bash
2#
3# shared.sh - multiple utils
4#
5# Copyright 2019 Luigi Santivetti <luigi.santivetti@gmail.com>
6
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13
14# The above copyright notice and this permission notice (including the next
15# paragraph) shall be included in all copies or substantial portions of the
16# Software.
17
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21# ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25function __call_module
26{
27 local -r this_module="$1"
28
29 [ -n "$this_module" ] || { lets -l -e "module not defined"; return $s_err; }
30
31 if is_opt "upins" "upall"; then
32 [ ! -d "$instance_d" ] && {
33 lets -l -e "trying to update an invalid instance"
34 return $s_err
35 }
36 fi
37
38 if is_opt "check" "watch" "upins" "upall" "doins" "doall"; then
39 local __envtable; local -i ret
40
41 __envtable="$(get_module_dependencies "envtable" $this_module)"; ret=$?
42 case "$ret" in
43 $s_ok )
44 [ -n "$__envtable" ] && {
45
46 # Export what's inside __envtable and check the actual table is
47 # imported as a variable.
48 eval "$__envtable" && declare -p -- "envtable" >/dev/null || {
49 lets -l -e "failed to export enviroment table"
50 return $s_err
51 }
52
53 # envtable is successfully on the stack, throw away its
54 # textual representation.
55 unset __envtable
56 } || {
57 lets -l -e "failed to get environment table"
58 return $s_err
59 } ;;
60 * ) return $s_err ;;
61 esac
62 fi
63
64 if is_opt "check"; then
65 (
66 # Export external variables found
67 set -eu; eval "${envtable[$this_module]}"; set +eu
68
69 case "${#deps[@]}" in
70 0 ) lets -l -i "$this_module doesn't have dependencies"
71 return $s_ok ;;
72 * ) lets -l -i "$this_module depends on: ${deps[@]}"
73 are_in_modules ${deps[@]} || {
74 lets -l -w "${deps[@]} not in MODULES"
75 } ;;
76 esac
77
78 # Check if this module correctly defines its own
79 # depmod. Return with an error if it doesn't since
80 # other options rely on this module depmod.
81
82 source "$module_d/$this_module/$module_sh"
83 if ! declare -p -- "depmod" &>/dev/null; then
84 lets -l -e "$this_module must define 'depmod'"
85 return $s_err
86 fi
87
88 for dep in ${deps[@]}; do
89 __is_in_array $dep ${depmod[@]} || {
90 lets -l -e "$dep not in $this_module depmod: ${depmod[@]}"
91 lets -l -e "add $dep to $this_module depmod"
92 return $s_err
93 }
94 done
95 )
96 return $?
97 fi
98
99 (
100 local -a files=( )
101 local callback
102
103 files+=( "$module_d/$this_module/$module_sh" )
104 files+=( "$module_d/$this_module/$holder_sh" )
Luigi Santivetti0fdd4702020-06-22 19:00:32 +0100105
106 if is_opt "doins" "upins" "upall" "doall" "watch"; then
107
Luigi Santivetti0b2f48a2020-10-25 21:23:27 +0000108 # Only upmod doesn't need scheme
109 files+=( "$module_d/$this_module/$scheme_sh" )
110
Luigi Santivetti0fdd4702020-06-22 19:00:32 +0100111 # Export external references
112 if test_source <(echo "${envtable[$this_module]}"); then
113 eval "${envtable[$this_module]}" || return $s_err2
114 else
115 return $s_err2
116 fi
117 fi
118
119 # Source needed files
120 if test_source "${files[@]}"; then
121 for f in ${files[@]}; do source "$f" || return $s_err3; done
122 else
123 return $s_err3
124 fi
125
126 callback="$(declare -F -- "tod_$2" 2>/dev/null)" || return $s_err6
127
128 if is_opt "doins" "doall"; then
129 create_instance_d $instance_d || return $s_err4
130 fi
131
132 # -- Here be dragons
133 eval "$callback \"${@:2}\"" || return $s_err5
134 )
135 case "$?" in
136 $s_err2 ) lets -l -e "$this_module: failed to export environment" ;;
137 $s_err3 ) lets -l -e "$this_module: failed to source $f" ;;
138 $s_err4 ) lets -l -e "$this_module: failed to create instance_d" ;;
139 $s_err5 ) lets -l -e "$this_module: $callback failed" ;;
140 $s_err6 ) lets -l -w "$this_module: $callback not available"
141 return $s_ok ;;
142 $s_ok ) return $s_ok ;;
143 esac
144
145 return $s_err
146}
147
148function __option_call
149{
150 local option="$1"; shift
151 local -a mods=( "${@}" )
152 local modname
153
154 is_valid_module "${mods[@]}"
155 case "$?" in
156 $s_err | $s_off_broken ) return $s_err ;;
157 $s_ok | $s_off_usable ) ;;
158 esac
159
160 # Actually call into module code
161 for modname in ${OPTARG[@]}; do
162 __call_module $modname $option
163 [ $? -eq $s_ok ] || return $s_err
164 done
165}
166
167function option_call
168{
169 local -a mods
170
171 mods=( $(get_modules_optarg "${@:2}") ) || return $s_err
172 # Filtered out list of requested modules
173 OPTARG=( "${mods[@]}" )
174
175 __option_call "$1" "${mods[@]}" >/dev/null
176}
177
178# @desc : process command line options only two options allowed per invocation
179# : at the moment. Keep it simple, keep it robust. For options details
180# : see help.sh.
181# :
182# : credits to https://stackoverflow.com/a/28466267
183function __option_process
184{
185 local opt; OPTIND=1
186
187 # Be quiet and disallow any single char option
188 local -r options=":-:"
189 local -a args
190
191 if getopts "$options" opt; then
192 if [ "$opt" = "-" ]; then
193 opt="${OPTARG%%=*}" # Get option name
194 OPTARG="${OPTARG#$opt}" # Get option argument(s)
195 OPTARG="${OPTARG#=}" # Drop `=` if any
196 OPTARG="${OPTARG//,/ }" # Drop `,` if any
197
198 # Early return for help
199 [ "$opt" = "help" ] && __help && return $s_ok
200
201 is_in_options "$opt" || return $s_err2
202 fi
203 fi
204
205 OPTIONS[$opt]=1; option_call $opt "${OPTARG[@]}"
206 case "$?" in
207 $s_err ) lets -l -e "$opt failed"; return $s_err ;;
208 $s_ok ) lets -l -i --phew "$opt success"; return $s_ok ;;
209 esac
210}
211
212function option_process
213{
214 __option_process ${@}
215 case "$?" in
216 $s_err2 ) lets -l -e "invalid option, --help" ;;
217 $s_err ) return $s_err ;;
218 $s_ok ) return $s_ok ;;
219 esac
220}