Repository navigation
Expand file tree
/
Copy pathshellform.sh
More file actions
204 lines (170 loc) · 5.93 KB
/
Copy pathshellform.sh
File metadata and controls
204 lines (170 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#!/usr/bin/env bash
# shellform.sh
if [[ -n "${SHELLFORM_LOADED:-}" ]]; then
shellform_init
return
fi
SHELLFORM_LOADED=1
##########################################################################
# Public DSL API
##########################################################################
configure() { shellform_configure "$@"; }
end() { shellform_end; }
##########################################################################
# Internal State and Config
##########################################################################
shellform_configuring=0
shellform_current_service=""
shellform_service_options=()
shellform_command_count=0
shellform_error_count=0
shellform_start_time=$(date +%s)
shellform_max_args=10
##########################################################################
# Logging & Error Reporting
##########################################################################
shellform_log_dir="./logs"
mkdir -p "$shellform_log_dir"
shellform_log_file="$shellform_log_dir/shellform_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$shellform_log_file") 2>&1
shellform_fatal() {
echo -e "\n❌ Fatal error: $*" >&2
local i=0
while caller $i; do ((i++)); done
exit 1
}
shellform_exec() {
if [[ "${shellform_dryrun:-0}" -eq 1 ]]; then
return 0
fi
"$@"
}
shellform_cmd() {
"$@"
}
shellform_run() {
local cmd="$1"
shift
local args=("$@")
local visible_args=("${args[@]:0:$shellform_max_args}")
[ "${#args[@]}" -gt "$shellform_max_args" ] && visible_args+=("...")
shellform_command_count=$((shellform_command_count + 1))
echo -e "▶️ $cmd ${visible_args[*]}"
if shellform_exec "$cmd" "${args[@]}"; then
echo -e "✅ Success: $cmd ${visible_args[*]}"
else
echo -e "❌ Failed: $cmd ${visible_args[*]}"
shellform_error_count=$((shellform_error_count + 1))
return 1
fi
}
shellform_dump_call_trace() {
local ERROR_CMD=$(eval echo "$BASH_COMMAND")
echo "🚨 ERROR: Command \"$ERROR_CMD\" failed."
echo "🚨 Call trace:"
local i=1
while caller $i; do
((i++))
done
}
##########################################################################
# Core DSL Implementation
##########################################################################
shellform_configure() {
if [[ "$shellform_configuring" -eq 1 ]]; then
shellform_fatal "Nested configure blocks not allowed"
fi
shellform_current_service="$1"
shellform_service_options=()
shellform_configuring=1
local spec_func="${shellform_current_service}_spec"
if ! declare -f "$spec_func" >/dev/null; then
shellform_fatal "Missing required function: $spec_func"
fi
shellform_service_options=($($spec_func))
# 🔹 One-time init per service
local init_fn="${shellform_current_service}_init"
local inited_var="shellform_service_${shellform_current_service}_inited"
if declare -f "$init_fn" >/dev/null && [[ -z "${!inited_var:-}" ]]; then
local init_rc=0
"$init_fn" || init_rc=$?
if [[ $init_rc -ne 0 ]]; then
echo ""
echo "════════════════════════════════════════════════════════════"
echo "❌ PROVIDER INIT FAILED: $shellform_current_service (exit $init_rc)"
echo "════════════════════════════════════════════════════════════"
echo "The 'configure $shellform_current_service ... end' block cannot run."
echo "Fix the provider's prerequisites and re-run the script."
echo "════════════════════════════════════════════════════════════"
echo ""
shellform_error_count=$((shellform_error_count + 1))
exit $init_rc
fi
printf -v "$inited_var" 1
fi
for option in "${shellform_service_options[@]}"; do
shellform_define_option_function "$option"
done
}
shellform_define_option_function() {
local option="$1"
local var="shellform__${shellform_current_service}_${option}_items"
eval "$var=()"
eval "
$option() {
shellform_handle_option \"$option\" \"\$@\"
}"
}
shellform_handle_option() {
local option="$1"
shift
local var="shellform__${shellform_current_service}_${option}_items"
local item_fn="${shellform_current_service}_${option}_item"
eval "$var+=(\"\$@\")"
if declare -f "$item_fn" >/dev/null; then
"$item_fn" "$@"
fi
}
shellform_end() {
if [[ "$shellform_configuring" -ne 1 ]]; then
shellform_fatal "'end' called outside of a configure block"
fi
for option in "${shellform_service_options[@]}"; do
local var="shellform__${shellform_current_service}_${option}_items"
local group_fn="${shellform_current_service}_${option}_group"
if declare -f "$group_fn" >/dev/null && [[ "$(declare -p "$var" 2>/dev/null)" =~ "declare -a" ]]; then
local args
eval "args=(\"\${$var[@]:-}\")"
# Skip the group call when no items were registered for this option
if [[ ${#args[@]} -eq 0 || ( ${#args[@]} -eq 1 && -z "${args[0]}" ) ]]; then
:
else
"$group_fn" "${args[@]}"
fi
fi
unset -f "$option"
unset "$var"
done
shellform_configuring=0
shellform_current_service=""
shellform_service_options=()
}
##########################################################################
# Final Summary
##########################################################################
shellform_summary() {
local end_time=$(date +%s)
local elapsed=$((end_time - shellform_start_time))
echo "\nSummary:"
echo " Time Elapsed: ${elapsed}s"
echo " Commands Run: $shellform_command_count"
echo " Errors: $shellform_error_count"
echo " Log File: $shellform_log_file"
}
shellform_init() {
trap shellform_dump_call_trace ERR
trap shellform_summary EXIT
set -euo pipefail
set -o errtrace
}
shellform_init