auto-toolkit 0.1.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/libs/args.sh +366 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/libs/common.sh +122 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/libs/download.sh +102 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/libs/gpg.sh +122 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/libs/pkg.sh +104 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/scripts/docker/docker-cleanup.sh +69 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/scripts/files/find-large-files.sh +120 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/scripts/security/hash-check.sh +177 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/scripts/setup/setup-dev-env.sh +104 -0
- auto_toolkit-0.1.0b1.data/data/share/auto-toolkit/scripts/system/install-program.sh +90 -0
- auto_toolkit-0.1.0b1.dist-info/METADATA +409 -0
- auto_toolkit-0.1.0b1.dist-info/RECORD +28 -0
- auto_toolkit-0.1.0b1.dist-info/WHEEL +4 -0
- auto_toolkit-0.1.0b1.dist-info/entry_points.txt +2 -0
- src/__init__.py +5 -0
- src/__main__.py +10 -0
- src/cli.py +687 -0
- src/colors.py +49 -0
- src/config.py +116 -0
- src/constants.py +67 -0
- src/discovery.py +357 -0
- src/enums.py +34 -0
- src/executor.py +103 -0
- src/installer.py +138 -0
- src/metadata.py +128 -0
- src/search.py +122 -0
- src/trust.py +211 -0
- src/validator.py +158 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Declarative argument parsing and usage generator for automation scripts.
|
|
3
|
+
#
|
|
4
|
+
# Example Usage:
|
|
5
|
+
# source "$LIB_DIR/common.sh"
|
|
6
|
+
# source "$LIB_DIR/args.sh"
|
|
7
|
+
#
|
|
8
|
+
# cli_init "auto install auto-toolkit [OPTIONS]" \
|
|
9
|
+
# "Install and symlink auto CLI binary into your PATH."
|
|
10
|
+
#
|
|
11
|
+
# cli_opt "--path" "-p" "Specify target installation directory" TARGET_DIR "$HOME/.local/bin"
|
|
12
|
+
# cli_flag "--dry-run" "-d" "Simulate installation steps" DRY_RUN
|
|
13
|
+
# cli_flag "--force" "-f" "Force overwrite of existing files" FORCE
|
|
14
|
+
#
|
|
15
|
+
# cli_example "auto install auto-toolkit"
|
|
16
|
+
# cli_example "auto install auto-toolkit --dry-run"
|
|
17
|
+
#
|
|
18
|
+
# cli_parse "$@"
|
|
19
|
+
|
|
20
|
+
# Global CLI definitions
|
|
21
|
+
CLI_USAGE=""
|
|
22
|
+
CLI_DESCRIPTION=""
|
|
23
|
+
CLI_OPTS=()
|
|
24
|
+
CLI_EXAMPLES=()
|
|
25
|
+
CLI_POSITIONAL=()
|
|
26
|
+
|
|
27
|
+
# Initialize CLI metadata
|
|
28
|
+
cli_init() {
|
|
29
|
+
CLI_USAGE="$1"
|
|
30
|
+
CLI_DESCRIPTION="${2:-}"
|
|
31
|
+
CLI_OPTS=()
|
|
32
|
+
CLI_EXAMPLES=()
|
|
33
|
+
CLI_POSITIONAL=()
|
|
34
|
+
|
|
35
|
+
# Automatically add built-in help flag
|
|
36
|
+
cli_flag "--help" "-h" "Show this help message and exit" CLI_SHOW_HELP false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Register a boolean flag
|
|
40
|
+
# Syntax: cli_flag <long> <short> <description> <var_name> [default_val=false]
|
|
41
|
+
cli_flag() {
|
|
42
|
+
local long="${1#--}"
|
|
43
|
+
local short="${2#-}"
|
|
44
|
+
local desc="$3"
|
|
45
|
+
local var_name="$4"
|
|
46
|
+
local default_val="${5:-false}"
|
|
47
|
+
|
|
48
|
+
# Set default value in caller's environment
|
|
49
|
+
printf -v "$var_name" "%s" "$default_val"
|
|
50
|
+
|
|
51
|
+
CLI_OPTS+=("flag|${long}|${short}|${var_name}|${default_val}|${desc}")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Register an option taking a value
|
|
55
|
+
# Syntax: cli_opt <long> <short> <description> <var_name> [default_val=""] [required=false]
|
|
56
|
+
cli_opt() {
|
|
57
|
+
local long="${1#--}"
|
|
58
|
+
local short="${2#-}"
|
|
59
|
+
local desc="$3"
|
|
60
|
+
local var_name="$4"
|
|
61
|
+
local default_val="${5:-}"
|
|
62
|
+
local required="${6:-false}"
|
|
63
|
+
|
|
64
|
+
# Set default value in caller's environment
|
|
65
|
+
printf -v "$var_name" "%s" "$default_val"
|
|
66
|
+
|
|
67
|
+
CLI_OPTS+=("val|${long}|${short}|${var_name}|${default_val}|${desc}|${required}")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Add a usage example
|
|
71
|
+
cli_example() {
|
|
72
|
+
CLI_EXAMPLES+=("$1")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# Print formatted help text
|
|
76
|
+
cli_help() {
|
|
77
|
+
local c_bold="${COLOR_BOLD:-\033[1m}"
|
|
78
|
+
local c_cyan="${COLOR_CYAN:-\033[36m}"
|
|
79
|
+
local c_dim="${COLOR_DIM:-\033[90m}"
|
|
80
|
+
local c_reset="${COLOR_RESET:-\033[0m}"
|
|
81
|
+
|
|
82
|
+
echo -e "${c_bold}Usage:${c_reset} ${CLI_USAGE}"
|
|
83
|
+
|
|
84
|
+
if [[ -n "$CLI_DESCRIPTION" ]]; then
|
|
85
|
+
echo ""
|
|
86
|
+
echo -e " ${CLI_DESCRIPTION}"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [[ ${#CLI_OPTS[@]} -gt 0 ]]; then
|
|
90
|
+
echo ""
|
|
91
|
+
echo -e "${c_bold}Options:${c_reset}"
|
|
92
|
+
|
|
93
|
+
# Calculate max flag width for clean alignment
|
|
94
|
+
local max_flag_len=0
|
|
95
|
+
local entry
|
|
96
|
+
|
|
97
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
98
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
99
|
+
local flag_display=""
|
|
100
|
+
|
|
101
|
+
if [[ -n "$opt_short" ]]; then
|
|
102
|
+
flag_display="-${opt_short}, --${opt_long}"
|
|
103
|
+
else
|
|
104
|
+
flag_display=" --${opt_long}"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
if [[ "$opt_type" == "val" ]]; then
|
|
108
|
+
flag_display="${flag_display} <val>"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [[ ${#flag_display} -gt $max_flag_len ]]; then
|
|
112
|
+
max_flag_len=${#flag_display}
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
|
|
116
|
+
local col_width=$((max_flag_len + 4))
|
|
117
|
+
|
|
118
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
119
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
120
|
+
local flag_display=""
|
|
121
|
+
|
|
122
|
+
if [[ -n "$opt_short" ]]; then
|
|
123
|
+
flag_display="-${opt_short}, --${opt_long}"
|
|
124
|
+
else
|
|
125
|
+
flag_display=" --${opt_long}"
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
if [[ "$opt_type" == "val" ]]; then
|
|
129
|
+
flag_display="${flag_display} <val>"
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
local default_info=""
|
|
133
|
+
|
|
134
|
+
if [[ -n "$opt_default" && "$opt_default" != "false" ]]; then
|
|
135
|
+
default_info=" ${c_dim}(default: ${opt_default})${c_reset}"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
if [[ "$opt_req" == "true" ]]; then
|
|
139
|
+
default_info=" ${c_cyan}(required)${c_reset}"
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
printf " %-*s %s%b\n" "$col_width" "$flag_display" "$opt_desc" "$default_info"
|
|
143
|
+
done
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
if [[ ${#CLI_EXAMPLES[@]} -gt 0 ]]; then
|
|
147
|
+
echo ""
|
|
148
|
+
echo -e "${c_bold}Examples:${c_reset}"
|
|
149
|
+
|
|
150
|
+
local ex
|
|
151
|
+
|
|
152
|
+
for ex in "${CLI_EXAMPLES[@]}"; do
|
|
153
|
+
echo -e " $ex"
|
|
154
|
+
done
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
echo ""
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# Parse command-line arguments according to registered options
|
|
161
|
+
cli_parse() {
|
|
162
|
+
local args=("$@")
|
|
163
|
+
CLI_POSITIONAL=()
|
|
164
|
+
|
|
165
|
+
while [[ ${#args[@]} -gt 0 ]]; do
|
|
166
|
+
local key="${args[0]}"
|
|
167
|
+
|
|
168
|
+
case "$key" in
|
|
169
|
+
-h|--help)
|
|
170
|
+
cli_help
|
|
171
|
+
exit 0
|
|
172
|
+
;;
|
|
173
|
+
|
|
174
|
+
--)
|
|
175
|
+
shift
|
|
176
|
+
CLI_POSITIONAL+=("${args[@]}")
|
|
177
|
+
break
|
|
178
|
+
;;
|
|
179
|
+
|
|
180
|
+
--*=*)
|
|
181
|
+
# Handle --option=value syntax
|
|
182
|
+
local opt_name="${key%%=*}"
|
|
183
|
+
opt_name="${opt_name#--}"
|
|
184
|
+
local opt_val="${key#*=}"
|
|
185
|
+
local matched=false
|
|
186
|
+
local entry
|
|
187
|
+
|
|
188
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
189
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
190
|
+
|
|
191
|
+
if [[ "$opt_long" == "$opt_name" && "$opt_type" == "val" ]]; then
|
|
192
|
+
printf -v "$opt_var" "%s" "$opt_val"
|
|
193
|
+
matched=true
|
|
194
|
+
break
|
|
195
|
+
fi
|
|
196
|
+
done
|
|
197
|
+
|
|
198
|
+
if [[ "$matched" == false ]]; then
|
|
199
|
+
if command -v log_error &>/dev/null; then
|
|
200
|
+
log_error "Unknown option: $key"
|
|
201
|
+
else
|
|
202
|
+
echo -e "Error: Unknown option: $key" >&2
|
|
203
|
+
fi
|
|
204
|
+
cli_help >&2
|
|
205
|
+
exit 1
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
args=("${args[@]:1}")
|
|
209
|
+
;;
|
|
210
|
+
|
|
211
|
+
--*)
|
|
212
|
+
local opt_name="${key#--}"
|
|
213
|
+
local matched=false
|
|
214
|
+
local entry
|
|
215
|
+
|
|
216
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
217
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
218
|
+
|
|
219
|
+
if [[ "$opt_long" == "$opt_name" ]]; then
|
|
220
|
+
if [[ "$opt_type" == "flag" ]]; then
|
|
221
|
+
printf -v "$opt_var" "%s" "true"
|
|
222
|
+
matched=true
|
|
223
|
+
args=("${args[@]:1}")
|
|
224
|
+
break
|
|
225
|
+
elif [[ "$opt_type" == "val" ]]; then
|
|
226
|
+
if [[ ${#args[@]} -lt 2 || "${args[1]}" =~ ^- ]]; then
|
|
227
|
+
if command -v log_error &>/dev/null; then
|
|
228
|
+
log_error "Option '--$opt_long' requires a value."
|
|
229
|
+
else
|
|
230
|
+
echo -e "Error: Option '--$opt_long' requires a value." >&2
|
|
231
|
+
fi
|
|
232
|
+
cli_help >&2
|
|
233
|
+
exit 1
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
printf -v "$opt_var" "%s" "${args[1]}"
|
|
237
|
+
matched=true
|
|
238
|
+
args=("${args[@]:2}")
|
|
239
|
+
break
|
|
240
|
+
fi
|
|
241
|
+
fi
|
|
242
|
+
done
|
|
243
|
+
|
|
244
|
+
if [[ "$matched" == false ]]; then
|
|
245
|
+
if command -v log_error &>/dev/null; then
|
|
246
|
+
log_error "Unknown option: $key"
|
|
247
|
+
else
|
|
248
|
+
echo -e "Error: Unknown option: $key" >&2
|
|
249
|
+
fi
|
|
250
|
+
cli_help >&2
|
|
251
|
+
exit 1
|
|
252
|
+
fi
|
|
253
|
+
;;
|
|
254
|
+
|
|
255
|
+
-[a-zA-Z0-9]*)
|
|
256
|
+
local opt_name="${key#-}"
|
|
257
|
+
local matched=false
|
|
258
|
+
|
|
259
|
+
# 1. Check for combined single-character short flags (e.g. -fd, -xzf)
|
|
260
|
+
if [[ ${#opt_name} -gt 1 ]]; then
|
|
261
|
+
local all_flags=true
|
|
262
|
+
local matched_vars=()
|
|
263
|
+
local i
|
|
264
|
+
|
|
265
|
+
for (( i=0; i<${#opt_name}; i++ )); do
|
|
266
|
+
local ch="${opt_name:i:1}"
|
|
267
|
+
local ch_found=false
|
|
268
|
+
local entry
|
|
269
|
+
|
|
270
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
271
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
272
|
+
|
|
273
|
+
if [[ "$opt_short" == "$ch" && "$opt_type" == "flag" ]]; then
|
|
274
|
+
matched_vars+=("$opt_var")
|
|
275
|
+
ch_found=true
|
|
276
|
+
break
|
|
277
|
+
fi
|
|
278
|
+
done
|
|
279
|
+
|
|
280
|
+
if [[ "$ch_found" == false ]]; then
|
|
281
|
+
all_flags=false
|
|
282
|
+
break
|
|
283
|
+
fi
|
|
284
|
+
done
|
|
285
|
+
|
|
286
|
+
if [[ "$all_flags" == true && ${#matched_vars[@]} -gt 0 ]]; then
|
|
287
|
+
for v in "${matched_vars[@]}"; do
|
|
288
|
+
printf -v "$v" "%s" "true"
|
|
289
|
+
done
|
|
290
|
+
|
|
291
|
+
args=("${args[@]:1}")
|
|
292
|
+
continue
|
|
293
|
+
fi
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
# 2. Check if it matches a registered short option or flag
|
|
297
|
+
local entry
|
|
298
|
+
|
|
299
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
300
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
301
|
+
|
|
302
|
+
if [[ "$opt_short" == "$opt_name" ]]; then
|
|
303
|
+
if [[ "$opt_type" == "flag" ]]; then
|
|
304
|
+
printf -v "$opt_var" "%s" "true"
|
|
305
|
+
matched=true
|
|
306
|
+
args=("${args[@]:1}")
|
|
307
|
+
break
|
|
308
|
+
elif [[ "$opt_type" == "val" ]]; then
|
|
309
|
+
if [[ ${#args[@]} -lt 2 || "${args[1]}" =~ ^- ]]; then
|
|
310
|
+
if command -v log_error &>/dev/null; then
|
|
311
|
+
log_error "Option '-$opt_short' requires a value."
|
|
312
|
+
else
|
|
313
|
+
echo -e "Error: Option '-$opt_short' requires a value." >&2
|
|
314
|
+
fi
|
|
315
|
+
cli_help >&2
|
|
316
|
+
exit 1
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
printf -v "$opt_var" "%s" "${args[1]}"
|
|
320
|
+
matched=true
|
|
321
|
+
args=("${args[@]:2}")
|
|
322
|
+
break
|
|
323
|
+
fi
|
|
324
|
+
fi
|
|
325
|
+
done
|
|
326
|
+
|
|
327
|
+
if [[ "$matched" == false ]]; then
|
|
328
|
+
if command -v log_error &>/dev/null; then
|
|
329
|
+
log_error "Unknown option: $key"
|
|
330
|
+
else
|
|
331
|
+
echo -e "Error: Unknown option: $key" >&2
|
|
332
|
+
fi
|
|
333
|
+
cli_help >&2
|
|
334
|
+
exit 1
|
|
335
|
+
fi
|
|
336
|
+
;;
|
|
337
|
+
|
|
338
|
+
*)
|
|
339
|
+
CLI_POSITIONAL+=("$key")
|
|
340
|
+
args=("${args[@]:1}")
|
|
341
|
+
;;
|
|
342
|
+
esac
|
|
343
|
+
done
|
|
344
|
+
|
|
345
|
+
# Validate required options
|
|
346
|
+
local entry
|
|
347
|
+
|
|
348
|
+
for entry in "${CLI_OPTS[@]}"; do
|
|
349
|
+
IFS='|' read -r opt_type opt_long opt_short opt_var opt_default opt_desc opt_req <<< "$entry"
|
|
350
|
+
|
|
351
|
+
if [[ "$opt_req" == "true" ]]; then
|
|
352
|
+
local current_val="${!opt_var}"
|
|
353
|
+
|
|
354
|
+
if [[ -z "$current_val" ]]; then
|
|
355
|
+
if command -v log_error &>/dev/null; then
|
|
356
|
+
log_error "Missing required option: --${opt_long}"
|
|
357
|
+
else
|
|
358
|
+
echo -e "Error: Missing required option: --${opt_long}" >&2
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
cli_help >&2
|
|
362
|
+
exit 1
|
|
363
|
+
fi
|
|
364
|
+
fi
|
|
365
|
+
done
|
|
366
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Common helper functions for logging, terminal colors, and temporary directory lifecycle
|
|
3
|
+
|
|
4
|
+
# Color initialization (respects NO_COLOR, non-interactive terminals, and dumb terminal)
|
|
5
|
+
init_colors() {
|
|
6
|
+
if [[ -z "${NO_COLOR:-}" && -t 1 && "${TERM:-}" != "dumb" ]]; then
|
|
7
|
+
COLOR_RESET="\033[0m"
|
|
8
|
+
COLOR_BOLD="\033[1m"
|
|
9
|
+
COLOR_RED="\033[31m"
|
|
10
|
+
COLOR_GREEN="\033[32m"
|
|
11
|
+
COLOR_YELLOW="\033[33m"
|
|
12
|
+
COLOR_BLUE="\033[34m"
|
|
13
|
+
COLOR_MAGENTA="\033[35m"
|
|
14
|
+
COLOR_CYAN="\033[36m"
|
|
15
|
+
COLOR_DIM="\033[90m"
|
|
16
|
+
else
|
|
17
|
+
COLOR_RESET=""
|
|
18
|
+
COLOR_BOLD=""
|
|
19
|
+
COLOR_RED=""
|
|
20
|
+
COLOR_GREEN=""
|
|
21
|
+
COLOR_YELLOW=""
|
|
22
|
+
COLOR_BLUE=""
|
|
23
|
+
COLOR_MAGENTA=""
|
|
24
|
+
COLOR_CYAN=""
|
|
25
|
+
COLOR_DIM=""
|
|
26
|
+
fi
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
init_colors
|
|
30
|
+
|
|
31
|
+
log_info() {
|
|
32
|
+
echo -e "${COLOR_CYAN}==>${COLOR_RESET} ${COLOR_BOLD}$*${COLOR_RESET}"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
log_step() {
|
|
36
|
+
echo -e " ${COLOR_BLUE}->${COLOR_RESET} $*"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
log_success() {
|
|
40
|
+
echo -e " ${COLOR_GREEN}[✓]${COLOR_RESET} $*"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
log_warn() {
|
|
44
|
+
echo -e " ${COLOR_YELLOW}[!] Warning:${COLOR_RESET} $*" >&2
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
log_error() {
|
|
48
|
+
echo -e " ${COLOR_RED}[✗] Error:${COLOR_RESET} $*" >&2
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Temporary directory tracking & cleanup
|
|
52
|
+
declare -a _AUTO_TEMP_DIRS=()
|
|
53
|
+
|
|
54
|
+
_cleanup_temp_dirs() {
|
|
55
|
+
local dir
|
|
56
|
+
|
|
57
|
+
for dir in "${_AUTO_TEMP_DIRS[@]}"; do
|
|
58
|
+
if [[ -d "$dir" ]]; then
|
|
59
|
+
rm -rf "$dir" 2>/dev/null || true
|
|
60
|
+
fi
|
|
61
|
+
done
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
trap '_cleanup_temp_dirs' EXIT INT TERM
|
|
65
|
+
|
|
66
|
+
create_temp_dir() {
|
|
67
|
+
local prefix="${1:-auto-toolkit}"
|
|
68
|
+
local tmp_dir
|
|
69
|
+
|
|
70
|
+
tmp_dir="$(mktemp -d "/tmp/${prefix}.XXXXXX")"
|
|
71
|
+
_AUTO_TEMP_DIRS+=("$tmp_dir")
|
|
72
|
+
|
|
73
|
+
echo "$tmp_dir"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
setup_temp_dir() {
|
|
77
|
+
local prefix="${1:-auto-toolkit}"
|
|
78
|
+
|
|
79
|
+
create_temp_dir "$prefix"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Verify required binaries exist on host PATH
|
|
83
|
+
require_commands() {
|
|
84
|
+
local missing=()
|
|
85
|
+
local cmd
|
|
86
|
+
|
|
87
|
+
for cmd in "$@"; do
|
|
88
|
+
if ! command -v "$cmd" &>/dev/null; then
|
|
89
|
+
missing+=("$cmd")
|
|
90
|
+
fi
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
94
|
+
log_error "Missing required commands: ${missing[*]}"
|
|
95
|
+
log_error "Please install the missing tools and try again."
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
return 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Interactive confirmation prompt with default handling
|
|
103
|
+
confirm_action() {
|
|
104
|
+
local prompt="${1:-Are you sure?}"
|
|
105
|
+
local default_ans="${2:-N}"
|
|
106
|
+
|
|
107
|
+
if [[ "${FORCE:-false}" == "true" ]]; then
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [[ ! -t 0 ]]; then
|
|
112
|
+
[[ "${default_ans^^}" == "Y" ]] && return 0 || return 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
local prompt_suffix="[y/N]"
|
|
116
|
+
[[ "${default_ans^^}" == "Y" ]] && prompt_suffix="[Y/n]"
|
|
117
|
+
|
|
118
|
+
read -r -p "$prompt $prompt_suffix " answer
|
|
119
|
+
answer="${answer:-$default_ans}"
|
|
120
|
+
|
|
121
|
+
[[ "${answer,,}" =~ ^y(es)?$ ]]
|
|
122
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Robust downloading utilities with retry logic, timeout, and progress feedback
|
|
3
|
+
|
|
4
|
+
# Download a file from URL to output destination using curl or wget
|
|
5
|
+
# Arguments:
|
|
6
|
+
# $1: Source URL (http://, https://, file://)
|
|
7
|
+
# $2: Destination file path
|
|
8
|
+
# $3: Retry attempts (default: 3)
|
|
9
|
+
# $4: Connection timeout in seconds (default: 15)
|
|
10
|
+
fetch_file() {
|
|
11
|
+
local url="$1"
|
|
12
|
+
local dest="$2"
|
|
13
|
+
local retries="${3:-3}"
|
|
14
|
+
local timeout="${4:-15}"
|
|
15
|
+
|
|
16
|
+
if [[ -z "$url" || -z "$dest" ]]; then
|
|
17
|
+
echo "Usage: fetch_file <url> <dest> [retries] [timeout]" >&2
|
|
18
|
+
return 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
local dest_dir
|
|
22
|
+
dest_dir="$(dirname "$dest")"
|
|
23
|
+
mkdir -p "$dest_dir"
|
|
24
|
+
|
|
25
|
+
# Handle local file:// protocol
|
|
26
|
+
if [[ "$url" =~ ^file:// ]]; then
|
|
27
|
+
local local_path="${url#file://}"
|
|
28
|
+
|
|
29
|
+
if [[ -f "$local_path" ]]; then
|
|
30
|
+
cp -f "$local_path" "$dest"
|
|
31
|
+
return 0
|
|
32
|
+
else
|
|
33
|
+
echo "Error: Local source file not found: $local_path" >&2
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if command -v curl &>/dev/null; then
|
|
39
|
+
curl --fail \
|
|
40
|
+
--location \
|
|
41
|
+
--connect-timeout "$timeout" \
|
|
42
|
+
--retry "$retries" \
|
|
43
|
+
--retry-connrefused \
|
|
44
|
+
--silent \
|
|
45
|
+
--show-error \
|
|
46
|
+
-o "$dest" \
|
|
47
|
+
"$url"
|
|
48
|
+
elif command -v wget &>/dev/null; then
|
|
49
|
+
wget --tries="$retries" \
|
|
50
|
+
--timeout="$timeout" \
|
|
51
|
+
--quiet \
|
|
52
|
+
--show-progress \
|
|
53
|
+
-O "$dest" \
|
|
54
|
+
"$url"
|
|
55
|
+
else
|
|
56
|
+
echo "Error: Neither 'curl' nor 'wget' is available on this system." >&2
|
|
57
|
+
return 1
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Fetch text content (e.g. version file, signature, key) to standard output
|
|
62
|
+
# Arguments:
|
|
63
|
+
# $1: Source URL
|
|
64
|
+
# $2: Connection timeout in seconds (default: 10)
|
|
65
|
+
fetch_text() {
|
|
66
|
+
local url="$1"
|
|
67
|
+
local timeout="${2:-10}"
|
|
68
|
+
|
|
69
|
+
if [[ -z "$url" ]]; then
|
|
70
|
+
echo "Usage: fetch_text <url> [timeout]" >&2
|
|
71
|
+
return 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Handle local file:// protocol
|
|
75
|
+
if [[ "$url" =~ ^file:// ]]; then
|
|
76
|
+
local local_path="${url#file://}"
|
|
77
|
+
|
|
78
|
+
if [[ -f "$local_path" ]]; then
|
|
79
|
+
cat "$local_path"
|
|
80
|
+
return 0
|
|
81
|
+
else
|
|
82
|
+
echo "Error: Local source file not found: $local_path" >&2
|
|
83
|
+
return 1
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
if command -v curl &>/dev/null; then
|
|
88
|
+
curl --fail \
|
|
89
|
+
--location \
|
|
90
|
+
--connect-timeout "$timeout" \
|
|
91
|
+
--silent \
|
|
92
|
+
"$url"
|
|
93
|
+
elif command -v wget &>/dev/null; then
|
|
94
|
+
wget --timeout="$timeout" \
|
|
95
|
+
--quiet \
|
|
96
|
+
-O - \
|
|
97
|
+
"$url"
|
|
98
|
+
else
|
|
99
|
+
echo "Error: Neither 'curl' nor 'wget' is available on this system." >&2
|
|
100
|
+
return 1
|
|
101
|
+
fi
|
|
102
|
+
}
|