aidevops 3.1.139 → 3.1.142
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.
- package/VERSION +1 -1
- package/aidevops.sh +1 -1
- package/package.json +1 -1
- package/setup-modules/shell-env.sh +269 -134
- package/setup-modules/tool-install.sh +396 -330
- package/setup.sh +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.1.
|
|
1
|
+
3.1.142
|
package/aidevops.sh
CHANGED
package/package.json
CHANGED
|
@@ -161,27 +161,25 @@ setup_oh_my_zsh() {
|
|
|
161
161
|
return 0
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
local shared_profile="$
|
|
169
|
-
local zsh_rc="$
|
|
164
|
+
# Check that both zsh and bash are installed and collect existing bash config files.
|
|
165
|
+
# Prints the bash config file paths (one per line) on success.
|
|
166
|
+
# Returns 1 if prerequisites are not met (caller should return 0 early).
|
|
167
|
+
_shell_compat_check_prereqs() {
|
|
168
|
+
local shared_profile="$1"
|
|
169
|
+
local zsh_rc="$2"
|
|
170
170
|
|
|
171
|
-
# If shared profile already exists, we've already set this up
|
|
172
171
|
if [[ -f "$shared_profile" ]]; then
|
|
173
172
|
print_success "Cross-shell compatibility already configured ($shared_profile)"
|
|
174
|
-
return
|
|
173
|
+
return 1
|
|
175
174
|
fi
|
|
176
175
|
|
|
177
|
-
# Need both bash and zsh to be relevant
|
|
178
176
|
if ! command -v zsh >/dev/null 2>&1; then
|
|
179
177
|
print_info "zsh not installed - cross-shell setup not needed"
|
|
180
|
-
return
|
|
178
|
+
return 1
|
|
181
179
|
fi
|
|
182
180
|
if ! command -v bash >/dev/null 2>&1; then
|
|
183
181
|
print_info "bash not installed - cross-shell setup not needed"
|
|
184
|
-
return
|
|
182
|
+
return 1
|
|
185
183
|
fi
|
|
186
184
|
|
|
187
185
|
# Collect all bash config files that exist
|
|
@@ -195,20 +193,27 @@ setup_shell_compatibility() {
|
|
|
195
193
|
|
|
196
194
|
if [[ ${#bash_files[@]} -eq 0 ]]; then
|
|
197
195
|
print_info "No bash config files found - skipping cross-shell setup"
|
|
198
|
-
return
|
|
196
|
+
return 1
|
|
199
197
|
fi
|
|
200
198
|
|
|
201
199
|
if [[ ! -f "$zsh_rc" ]]; then
|
|
202
200
|
print_info "No .zshrc found - skipping cross-shell setup"
|
|
203
|
-
return
|
|
201
|
+
return 1
|
|
204
202
|
fi
|
|
205
203
|
|
|
206
|
-
|
|
204
|
+
printf '%s\n' "${bash_files[@]}"
|
|
205
|
+
return 0
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# Count portable customizations (exports, aliases, PATH entries) across bash config files.
|
|
209
|
+
# Prints "exports aliases paths" space-separated.
|
|
210
|
+
_shell_compat_count_customizations() {
|
|
207
211
|
local total_exports=0
|
|
208
212
|
local total_aliases=0
|
|
209
213
|
local total_paths=0
|
|
210
214
|
|
|
211
|
-
|
|
215
|
+
local src_file
|
|
216
|
+
for src_file in "$@"; do
|
|
212
217
|
local n
|
|
213
218
|
# grep -c exits 1 on no match; || : prevents ERR trap noise
|
|
214
219
|
# File existence already verified when building bash_files array
|
|
@@ -220,34 +225,16 @@ setup_shell_compatibility() {
|
|
|
220
225
|
total_paths=$((total_paths + ${n:-0}))
|
|
221
226
|
done
|
|
222
227
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
fi
|
|
227
|
-
|
|
228
|
-
print_info "Detected bash customizations across ${#bash_files[@]} file(s):"
|
|
229
|
-
echo " Exports: $total_exports, Aliases: $total_aliases, PATH entries: $total_paths"
|
|
230
|
-
echo ""
|
|
231
|
-
print_info "Best practice: create a shared profile (~/.shell_common) sourced by"
|
|
232
|
-
print_info "both bash and zsh, so your customizations work in either shell."
|
|
233
|
-
echo ""
|
|
234
|
-
|
|
235
|
-
local setup_compat="Y"
|
|
236
|
-
if [[ "$NON_INTERACTIVE" != "true" ]]; then
|
|
237
|
-
read -r -p "Create shared shell profile for cross-shell compatibility? [Y/n]: " setup_compat
|
|
238
|
-
fi
|
|
239
|
-
|
|
240
|
-
if [[ ! "$setup_compat" =~ ^[Yy]?$ ]]; then
|
|
241
|
-
print_info "Skipped cross-shell compatibility setup"
|
|
242
|
-
print_info "Set up later by creating ~/.shell_common and sourcing it from both shells"
|
|
243
|
-
return 0
|
|
244
|
-
fi
|
|
228
|
+
echo "$total_exports $total_aliases $total_paths"
|
|
229
|
+
return 0
|
|
230
|
+
}
|
|
245
231
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
232
|
+
# Extract portable customizations from bash config files into the shared profile.
|
|
233
|
+
# Returns the count of extracted lines.
|
|
234
|
+
_shell_compat_extract_to_shared_profile() {
|
|
235
|
+
local shared_profile="$1"
|
|
236
|
+
shift
|
|
237
|
+
# remaining args are bash_files
|
|
251
238
|
|
|
252
239
|
{
|
|
253
240
|
echo "# Shared shell profile - sourced by both bash and zsh"
|
|
@@ -262,7 +249,8 @@ setup_shell_compatibility() {
|
|
|
262
249
|
local -a seen_lines=()
|
|
263
250
|
local extracted=0
|
|
264
251
|
|
|
265
|
-
|
|
252
|
+
local src_file
|
|
253
|
+
for src_file in "$@"; do
|
|
266
254
|
local src_basename
|
|
267
255
|
src_basename=$(basename "$src_file")
|
|
268
256
|
local added_header=false
|
|
@@ -336,14 +324,15 @@ setup_shell_compatibility() {
|
|
|
336
324
|
done <"$src_file"
|
|
337
325
|
done
|
|
338
326
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
return 0
|
|
343
|
-
fi
|
|
327
|
+
echo "$extracted"
|
|
328
|
+
return 0
|
|
329
|
+
}
|
|
344
330
|
|
|
345
|
-
|
|
346
|
-
|
|
331
|
+
# Add sourcing of the shared profile to .zshrc and all bash config files.
|
|
332
|
+
_shell_compat_add_sourcing() {
|
|
333
|
+
local zsh_rc="$1"
|
|
334
|
+
shift
|
|
335
|
+
# remaining args are bash_files
|
|
347
336
|
|
|
348
337
|
# Add sourcing to .zshrc if not already present (existence verified above)
|
|
349
338
|
if ! grep -q 'shell_common' "$zsh_rc"; then
|
|
@@ -359,7 +348,8 @@ setup_shell_compatibility() {
|
|
|
359
348
|
|
|
360
349
|
# Add sourcing to bash config files if not already present
|
|
361
350
|
# File existence already verified when building bash_files array
|
|
362
|
-
|
|
351
|
+
local src_file
|
|
352
|
+
for src_file in "$@"; do
|
|
363
353
|
if ! grep -q 'shell_common' "$src_file"; then
|
|
364
354
|
{
|
|
365
355
|
echo ""
|
|
@@ -372,6 +362,73 @@ setup_shell_compatibility() {
|
|
|
372
362
|
fi
|
|
373
363
|
done
|
|
374
364
|
|
|
365
|
+
return 0
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
# Extract portable customizations from bash configs into a shared profile for cross-shell use
|
|
369
|
+
setup_shell_compatibility() {
|
|
370
|
+
print_info "Setting up cross-shell compatibility..."
|
|
371
|
+
|
|
372
|
+
local shared_profile="$HOME/.shell_common"
|
|
373
|
+
local zsh_rc="$HOME/.zshrc"
|
|
374
|
+
|
|
375
|
+
# Check prerequisites; collect bash config files
|
|
376
|
+
local -a bash_files=()
|
|
377
|
+
local prereq_out
|
|
378
|
+
prereq_out=$(_shell_compat_check_prereqs "$shared_profile" "$zsh_rc") || return 0
|
|
379
|
+
while IFS= read -r line; do
|
|
380
|
+
[[ -n "$line" ]] && bash_files+=("$line")
|
|
381
|
+
done <<<"$prereq_out"
|
|
382
|
+
|
|
383
|
+
# Count customizations across all bash config files
|
|
384
|
+
local counts
|
|
385
|
+
counts=$(_shell_compat_count_customizations "${bash_files[@]}")
|
|
386
|
+
local total_exports total_aliases total_paths
|
|
387
|
+
read -r total_exports total_aliases total_paths <<<"$counts"
|
|
388
|
+
|
|
389
|
+
if [[ $total_exports -eq 0 && $total_aliases -eq 0 && $total_paths -eq 0 ]]; then
|
|
390
|
+
print_info "No bash customizations detected - skipping cross-shell setup"
|
|
391
|
+
return 0
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
print_info "Detected bash customizations across ${#bash_files[@]} file(s):"
|
|
395
|
+
echo " Exports: $total_exports, Aliases: $total_aliases, PATH entries: $total_paths"
|
|
396
|
+
echo ""
|
|
397
|
+
print_info "Best practice: create a shared profile (~/.shell_common) sourced by"
|
|
398
|
+
print_info "both bash and zsh, so your customizations work in either shell."
|
|
399
|
+
echo ""
|
|
400
|
+
|
|
401
|
+
local setup_compat="Y"
|
|
402
|
+
if [[ "$NON_INTERACTIVE" != "true" ]]; then
|
|
403
|
+
read -r -p "Create shared shell profile for cross-shell compatibility? [Y/n]: " setup_compat
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
if [[ ! "$setup_compat" =~ ^[Yy]?$ ]]; then
|
|
407
|
+
print_info "Skipped cross-shell compatibility setup"
|
|
408
|
+
print_info "Set up later by creating ~/.shell_common and sourcing it from both shells"
|
|
409
|
+
return 0
|
|
410
|
+
fi
|
|
411
|
+
|
|
412
|
+
# Extract portable customizations from bash config into shared profile
|
|
413
|
+
# We extract: exports, PATH modifications, aliases, eval statements, source commands
|
|
414
|
+
# We skip: bash-specific syntax (shopt, PROMPT_COMMAND, PS1, completion, bind, etc.)
|
|
415
|
+
# We deduplicate lines that appear in multiple files (e.g. .bash_profile sources .bashrc)
|
|
416
|
+
print_info "Creating shared profile: $shared_profile"
|
|
417
|
+
|
|
418
|
+
local extracted
|
|
419
|
+
extracted=$(_shell_compat_extract_to_shared_profile "$shared_profile" "${bash_files[@]}")
|
|
420
|
+
|
|
421
|
+
if [[ $extracted -eq 0 ]]; then
|
|
422
|
+
rm -f "$shared_profile"
|
|
423
|
+
print_info "No portable customizations found to extract"
|
|
424
|
+
return 0
|
|
425
|
+
fi
|
|
426
|
+
|
|
427
|
+
chmod 644 "$shared_profile"
|
|
428
|
+
print_success "Extracted $extracted unique customization(s) to $shared_profile"
|
|
429
|
+
|
|
430
|
+
_shell_compat_add_sourcing "$zsh_rc" "${bash_files[@]}"
|
|
431
|
+
|
|
375
432
|
echo ""
|
|
376
433
|
print_success "Cross-shell compatibility configured"
|
|
377
434
|
print_info "Your customizations are now in: $shared_profile"
|
|
@@ -499,53 +556,42 @@ add_local_bin_to_path() {
|
|
|
499
556
|
# If it appears after /opt/homebrew/bin, the real shellcheck is found first
|
|
500
557
|
# and the wrapper is bypassed entirely. The launchctl setenv always prepends,
|
|
501
558
|
# and the case-guard in shell rc files ensures it stays first.
|
|
502
|
-
setup_shellcheck_wrapper() {
|
|
503
|
-
local wrapper_path="$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"
|
|
504
559
|
|
|
505
|
-
|
|
560
|
+
# Verify the shellcheck wrapper exists and is executable.
|
|
561
|
+
# Returns 1 if setup should be aborted (caller returns 0).
|
|
562
|
+
_shellcheck_wrapper_verify() {
|
|
563
|
+
local wrapper_path="$1"
|
|
564
|
+
|
|
506
565
|
if [[ ! -x "$wrapper_path" ]]; then
|
|
507
566
|
if [[ -f "$wrapper_path" ]]; then
|
|
508
567
|
chmod +x "$wrapper_path"
|
|
509
568
|
else
|
|
510
569
|
print_warning "ShellCheck wrapper not found at $wrapper_path (will be available after deploy)"
|
|
511
|
-
return
|
|
570
|
+
return 1
|
|
512
571
|
fi
|
|
513
572
|
fi
|
|
514
573
|
|
|
515
|
-
# Verify the wrapper actually works (can find real shellcheck)
|
|
516
574
|
if ! "$wrapper_path" --version >/dev/null 2>&1; then
|
|
517
575
|
print_warning "ShellCheck wrapper cannot find real shellcheck binary — skipping"
|
|
518
|
-
return
|
|
576
|
+
return 1
|
|
519
577
|
fi
|
|
520
578
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
env_line='export SHELLCHECK_PATH="$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"'
|
|
524
|
-
# shellcheck disable=SC2016 # path_line is written to rc files; must expand at shell startup
|
|
525
|
-
# Sanitize-and-prepend: strip any existing occurrence of the shim dir from PATH
|
|
526
|
-
# (it may be at the END from a previous setup run), then prepend it. This ensures
|
|
527
|
-
# the shim is always first, even on machines upgrading from the old append form.
|
|
528
|
-
# The ${PATH:+:$PATH} guard handles the empty-PATH edge case without a trailing colon.
|
|
529
|
-
local path_line='_aidevops_shim="$HOME/.aidevops/bin"; PATH="$(printf '\''%s'\'' "$PATH" | tr '\'':'\'' '\''\n'\'' | grep -Fxv -- "$_aidevops_shim" | paste -sd: -)"; export PATH="$_aidevops_shim${PATH:+:$PATH}"; unset _aidevops_shim'
|
|
530
|
-
# Fish shell uses different syntax (set -gx instead of export)
|
|
531
|
-
# shellcheck disable=SC2016 # fish lines are written to config.fish; must expand at shell startup
|
|
532
|
-
local env_line_fish='set -gx SHELLCHECK_PATH "$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"'
|
|
533
|
-
# shellcheck disable=SC2016 # fish path line: strip existing, then prepend
|
|
534
|
-
local path_line_fish='set -l _aidevops_shim "$HOME/.aidevops/bin"; set -l _aidevops_rest (string match -v -- "$_aidevops_shim" $PATH); set -gx PATH $_aidevops_shim $_aidevops_rest'
|
|
535
|
-
local added_to=""
|
|
536
|
-
local already_in=""
|
|
579
|
+
return 0
|
|
580
|
+
}
|
|
537
581
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
582
|
+
# Layer 0: Create the PATH shim (GH#2993).
|
|
583
|
+
# Places a symlink to the wrapper in ~/.aidevops/bin so bash-language-server
|
|
584
|
+
# finds the wrapper via PATH lookup before the real shellcheck binary.
|
|
585
|
+
_shellcheck_wrapper_setup_shim() {
|
|
586
|
+
local wrapper_path="$1"
|
|
542
587
|
local shim_dir="$HOME/.aidevops/bin"
|
|
543
588
|
local shim_path="$shim_dir/shellcheck"
|
|
589
|
+
|
|
544
590
|
mkdir -p "$shim_dir"
|
|
545
591
|
|
|
546
|
-
# Create or update the symlink
|
|
547
592
|
local wrapper_realpath
|
|
548
593
|
wrapper_realpath="$(realpath "$wrapper_path" 2>/dev/null || readlink -f "$wrapper_path" 2>/dev/null || echo "$wrapper_path")"
|
|
594
|
+
|
|
549
595
|
if [[ -L "$shim_path" ]]; then
|
|
550
596
|
local current_target
|
|
551
597
|
current_target="$(realpath "$shim_path" 2>/dev/null || readlink -f "$shim_path" 2>/dev/null || echo "")"
|
|
@@ -563,57 +609,64 @@ setup_shellcheck_wrapper() {
|
|
|
563
609
|
print_success "Created shellcheck shim: $shim_path → $wrapper_path"
|
|
564
610
|
fi
|
|
565
611
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
612
|
+
return 0
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
# Layer 1: Set SHELLCHECK_PATH and prepend shim dir via launchctl (macOS only).
|
|
616
|
+
# Affects all GUI-launched processes for the current boot session.
|
|
617
|
+
_shellcheck_wrapper_setup_launchctl() {
|
|
618
|
+
local wrapper_path="$1"
|
|
619
|
+
local shim_dir="$2"
|
|
620
|
+
|
|
569
621
|
# Note: 2>/dev/null on launchctl is intentional — launchctl may not be
|
|
570
622
|
# available in non-GUI contexts (SSH, containers). Unlike grep where we
|
|
571
623
|
# want errors visible, launchctl failure is a non-fatal fallback.
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
# be at the END (e.g., appended by a previous setup run), which means the
|
|
575
|
-
# real shellcheck at /opt/homebrew/bin is found first. We strip any existing
|
|
576
|
-
# occurrence and prepend to guarantee first position.
|
|
577
|
-
if [[ "$PLATFORM_MACOS" == "true" ]]; then
|
|
578
|
-
if launchctl setenv SHELLCHECK_PATH "$wrapper_path" 2>/dev/null; then
|
|
579
|
-
print_info "Set SHELLCHECK_PATH via launchctl (GUI processes)"
|
|
580
|
-
fi
|
|
581
|
-
# Build a clean PATH with shim_dir at the front, removing any existing
|
|
582
|
-
# occurrence to prevent duplicates while ensuring first position.
|
|
583
|
-
# Handle the empty-PATH edge case to avoid a trailing colon (which
|
|
584
|
-
# resolves to "." and is a PATH injection vector).
|
|
585
|
-
local clean_path
|
|
586
|
-
clean_path=$(printf '%s' "$PATH" | tr ':' '\n' | grep -Fxv "$shim_dir" | tr '\n' ':' | sed 's/:$//')
|
|
587
|
-
local new_path
|
|
588
|
-
if [[ -n "$clean_path" ]]; then
|
|
589
|
-
new_path="${shim_dir}:${clean_path}"
|
|
590
|
-
else
|
|
591
|
-
new_path="${shim_dir}"
|
|
592
|
-
fi
|
|
593
|
-
if launchctl setenv PATH "$new_path" 2>/dev/null; then
|
|
594
|
-
print_info "Prepended $shim_dir to PATH via launchctl (GUI processes)"
|
|
595
|
-
fi
|
|
624
|
+
if launchctl setenv SHELLCHECK_PATH "$wrapper_path" 2>/dev/null; then
|
|
625
|
+
print_info "Set SHELLCHECK_PATH via launchctl (GUI processes)"
|
|
596
626
|
fi
|
|
597
627
|
|
|
598
|
-
#
|
|
599
|
-
#
|
|
600
|
-
#
|
|
601
|
-
#
|
|
602
|
-
|
|
628
|
+
# Build a clean PATH with shim_dir at the front, removing any existing
|
|
629
|
+
# occurrence to prevent duplicates while ensuring first position.
|
|
630
|
+
# Handle the empty-PATH edge case to avoid a trailing colon (which
|
|
631
|
+
# resolves to "." and is a PATH injection vector).
|
|
632
|
+
local clean_path
|
|
633
|
+
clean_path=$(printf '%s' "$PATH" | tr ':' '\n' | grep -Fxv "$shim_dir" | tr '\n' ':' | sed 's/:$//')
|
|
634
|
+
local new_path
|
|
635
|
+
if [[ -n "$clean_path" ]]; then
|
|
636
|
+
new_path="${shim_dir}:${clean_path}"
|
|
637
|
+
else
|
|
638
|
+
new_path="${shim_dir}"
|
|
639
|
+
fi
|
|
640
|
+
if launchctl setenv PATH "$new_path" 2>/dev/null; then
|
|
641
|
+
print_info "Prepended $shim_dir to PATH via launchctl (GUI processes)"
|
|
642
|
+
fi
|
|
643
|
+
|
|
644
|
+
return 0
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
# Layer 2: Configure SHELLCHECK_PATH and PATH shim in .zshenv.
|
|
648
|
+
# Affects ALL zsh processes including non-interactive (e.g. bash-language-server).
|
|
649
|
+
_shellcheck_wrapper_setup_zshenv() {
|
|
650
|
+
local env_line="$1"
|
|
651
|
+
local path_line="$2"
|
|
652
|
+
local shim_dir="$3"
|
|
603
653
|
local zshenv="$HOME/.zshenv"
|
|
654
|
+
local added_to_out=""
|
|
655
|
+
local already_in_out=""
|
|
656
|
+
|
|
604
657
|
if [[ -f "$zshenv" ]] || command -v zsh >/dev/null 2>&1; then
|
|
605
658
|
touch "$zshenv"
|
|
606
659
|
|
|
607
660
|
# SHELLCHECK_PATH env var (for tools that honour it)
|
|
608
661
|
if grep -q 'SHELLCHECK_PATH' "$zshenv"; then
|
|
609
|
-
|
|
662
|
+
already_in_out="$zshenv"
|
|
610
663
|
else
|
|
611
664
|
{
|
|
612
665
|
echo ""
|
|
613
666
|
echo "# Added by aidevops setup (GH#2915: prevent ShellCheck memory explosion)"
|
|
614
667
|
echo "$env_line"
|
|
615
668
|
} >>"$zshenv"
|
|
616
|
-
|
|
669
|
+
added_to_out="$zshenv"
|
|
617
670
|
fi
|
|
618
671
|
|
|
619
672
|
# PATH prepend for ~/.aidevops/bin (GH#2993: shim must be on PATH)
|
|
@@ -639,7 +692,20 @@ setup_shellcheck_wrapper() {
|
|
|
639
692
|
fi
|
|
640
693
|
fi
|
|
641
694
|
|
|
642
|
-
#
|
|
695
|
+
# Return values via stdout (space-separated)
|
|
696
|
+
echo "$added_to_out $already_in_out"
|
|
697
|
+
return 0
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
# Layer 3: Configure SHELLCHECK_PATH and PATH shim in interactive shell rc files.
|
|
701
|
+
_shellcheck_wrapper_setup_rc_files() {
|
|
702
|
+
local env_line="$1"
|
|
703
|
+
local path_line="$2"
|
|
704
|
+
local env_line_fish="$3"
|
|
705
|
+
local path_line_fish="$4"
|
|
706
|
+
local added_to_out=""
|
|
707
|
+
local already_in_out=""
|
|
708
|
+
|
|
643
709
|
local rc_file
|
|
644
710
|
while IFS= read -r rc_file; do
|
|
645
711
|
[[ -z "$rc_file" ]] && continue
|
|
@@ -665,14 +731,14 @@ setup_shellcheck_wrapper() {
|
|
|
665
731
|
|
|
666
732
|
# SHELLCHECK_PATH env var
|
|
667
733
|
if grep -q 'SHELLCHECK_PATH' "$rc_file"; then
|
|
668
|
-
|
|
734
|
+
already_in_out="${already_in_out:+$already_in_out, }$rc_file"
|
|
669
735
|
else
|
|
670
736
|
{
|
|
671
737
|
echo ""
|
|
672
738
|
echo "# Added by aidevops setup (GH#2915: prevent ShellCheck memory explosion)"
|
|
673
739
|
echo "$rc_env_line"
|
|
674
740
|
} >>"$rc_file"
|
|
675
|
-
|
|
741
|
+
added_to_out="${added_to_out:+$added_to_out, }$rc_file"
|
|
676
742
|
fi
|
|
677
743
|
|
|
678
744
|
# PATH prepend for ~/.aidevops/bin (GH#2993)
|
|
@@ -699,6 +765,72 @@ setup_shellcheck_wrapper() {
|
|
|
699
765
|
fi
|
|
700
766
|
done < <(get_all_shell_rcs)
|
|
701
767
|
|
|
768
|
+
echo "$added_to_out|$already_in_out"
|
|
769
|
+
return 0
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
setup_shellcheck_wrapper() {
|
|
773
|
+
local wrapper_path="$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"
|
|
774
|
+
|
|
775
|
+
_shellcheck_wrapper_verify "$wrapper_path" || return 0
|
|
776
|
+
|
|
777
|
+
local env_line
|
|
778
|
+
# shellcheck disable=SC2016 # env_line is written to rc files; must expand at shell startup
|
|
779
|
+
env_line='export SHELLCHECK_PATH="$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"'
|
|
780
|
+
# shellcheck disable=SC2016 # path_line is written to rc files; must expand at shell startup
|
|
781
|
+
# Sanitize-and-prepend: strip any existing occurrence of the shim dir from PATH
|
|
782
|
+
# (it may be at the END from a previous setup run), then prepend it. This ensures
|
|
783
|
+
# the shim is always first, even on machines upgrading from the old append form.
|
|
784
|
+
# The ${PATH:+:$PATH} guard handles the empty-PATH edge case without a trailing colon.
|
|
785
|
+
local path_line='_aidevops_shim="$HOME/.aidevops/bin"; PATH="$(printf '\''%s'\'' "$PATH" | tr '\'':'\'' '\''\n'\'' | grep -Fxv -- "$_aidevops_shim" | paste -sd: -)"; export PATH="$_aidevops_shim${PATH:+:$PATH}"; unset _aidevops_shim'
|
|
786
|
+
# Fish shell uses different syntax (set -gx instead of export)
|
|
787
|
+
# shellcheck disable=SC2016 # fish lines are written to config.fish; must expand at shell startup
|
|
788
|
+
local env_line_fish='set -gx SHELLCHECK_PATH "$HOME/.aidevops/agents/scripts/shellcheck-wrapper.sh"'
|
|
789
|
+
# shellcheck disable=SC2016 # fish path line: strip existing, then prepend
|
|
790
|
+
local path_line_fish='set -l _aidevops_shim "$HOME/.aidevops/bin"; set -l _aidevops_rest (string match -v -- "$_aidevops_shim" $PATH); set -gx PATH $_aidevops_shim $_aidevops_rest'
|
|
791
|
+
|
|
792
|
+
local shim_dir="$HOME/.aidevops/bin"
|
|
793
|
+
|
|
794
|
+
# Layer 0: PATH shim (GH#2993)
|
|
795
|
+
_shellcheck_wrapper_setup_shim "$wrapper_path"
|
|
796
|
+
|
|
797
|
+
# Layer 1: launchctl setenv (macOS) — affects all GUI-launched processes
|
|
798
|
+
# Set both SHELLCHECK_PATH (for tools that honour it) and PATH (for tools
|
|
799
|
+
# that resolve shellcheck via PATH lookup, like bash-language-server).
|
|
800
|
+
# CRITICAL: Always prepend shim_dir even if it's already in PATH — it may
|
|
801
|
+
# be at the END (e.g., appended by a previous setup run), which means the
|
|
802
|
+
# real shellcheck at /opt/homebrew/bin is found first. We strip any existing
|
|
803
|
+
# occurrence and prepend to guarantee first position.
|
|
804
|
+
if [[ "$PLATFORM_MACOS" == "true" ]]; then
|
|
805
|
+
_shellcheck_wrapper_setup_launchctl "$wrapper_path" "$shim_dir"
|
|
806
|
+
fi
|
|
807
|
+
|
|
808
|
+
# Layer 2: .zshenv — affects ALL zsh processes (interactive AND non-interactive)
|
|
809
|
+
# This is critical because opencode spawns bash-language-server as a
|
|
810
|
+
# non-interactive child process. .zshrc is NOT sourced for non-interactive
|
|
811
|
+
# shells, so SHELLCHECK_PATH set only in .zshrc is invisible to the LSP.
|
|
812
|
+
# GH#2993: Also prepend ~/.aidevops/bin to PATH here so the shim is found.
|
|
813
|
+
local zshenv_result
|
|
814
|
+
zshenv_result=$(_shellcheck_wrapper_setup_zshenv "$env_line" "$path_line" "$shim_dir")
|
|
815
|
+
local zshenv_added zshenv_already
|
|
816
|
+
zshenv_added="${zshenv_result%% *}"
|
|
817
|
+
zshenv_already="${zshenv_result##* }"
|
|
818
|
+
|
|
819
|
+
# Layer 3: Shell rc files — affects interactive terminal sessions
|
|
820
|
+
local rc_result
|
|
821
|
+
rc_result=$(_shellcheck_wrapper_setup_rc_files "$env_line" "$path_line" "$env_line_fish" "$path_line_fish")
|
|
822
|
+
local rc_added rc_already
|
|
823
|
+
rc_added="${rc_result%%|*}"
|
|
824
|
+
rc_already="${rc_result##*|}"
|
|
825
|
+
|
|
826
|
+
# Merge results from layers 2 and 3
|
|
827
|
+
local added_to=""
|
|
828
|
+
local already_in=""
|
|
829
|
+
[[ -n "$zshenv_added" && "$zshenv_added" != " " ]] && added_to="${zshenv_added}"
|
|
830
|
+
[[ -n "$rc_added" ]] && added_to="${added_to:+$added_to, }${rc_added}"
|
|
831
|
+
[[ -n "$zshenv_already" && "$zshenv_already" != " " ]] && already_in="${zshenv_already}"
|
|
832
|
+
[[ -n "$rc_already" ]] && already_in="${already_in:+$already_in, }${rc_already}"
|
|
833
|
+
|
|
702
834
|
if [[ -n "$added_to" ]]; then
|
|
703
835
|
print_success "Configured SHELLCHECK_PATH wrapper in: $added_to"
|
|
704
836
|
fi
|
|
@@ -719,6 +851,26 @@ setup_shellcheck_wrapper() {
|
|
|
719
851
|
return 0
|
|
720
852
|
}
|
|
721
853
|
|
|
854
|
+
# Check whether server access aliases are already configured in any rc file.
|
|
855
|
+
# Returns 0 (true) if already configured, 1 (false) if not.
|
|
856
|
+
_aliases_check_configured() {
|
|
857
|
+
local rc_file
|
|
858
|
+
while IFS= read -r rc_file; do
|
|
859
|
+
[[ -z "$rc_file" ]] && continue
|
|
860
|
+
if [[ -f "$rc_file" ]] && grep -q "# AI Assistant Server Access" "$rc_file"; then
|
|
861
|
+
return 0
|
|
862
|
+
fi
|
|
863
|
+
done < <(get_all_shell_rcs)
|
|
864
|
+
|
|
865
|
+
# Also check fish config (not included in get_all_shell_rcs on macOS)
|
|
866
|
+
local fish_config="$HOME/.config/fish/config.fish"
|
|
867
|
+
if [[ -f "$fish_config" ]] && grep -q "# AI Assistant Server Access" "$fish_config"; then
|
|
868
|
+
return 0
|
|
869
|
+
fi
|
|
870
|
+
|
|
871
|
+
return 1
|
|
872
|
+
}
|
|
873
|
+
|
|
722
874
|
# Add server access aliases to shell rc files (bash/zsh/fish)
|
|
723
875
|
setup_aliases() {
|
|
724
876
|
print_info "Setting up shell aliases..."
|
|
@@ -758,25 +910,7 @@ alias aws-helper './.agents/scripts/aws-helper.sh'
|
|
|
758
910
|
ALIASES
|
|
759
911
|
)
|
|
760
912
|
|
|
761
|
-
|
|
762
|
-
local any_configured=false
|
|
763
|
-
local rc_file
|
|
764
|
-
while IFS= read -r rc_file; do
|
|
765
|
-
[[ -z "$rc_file" ]] && continue
|
|
766
|
-
if [[ -f "$rc_file" ]] && grep -q "# AI Assistant Server Access" "$rc_file"; then
|
|
767
|
-
any_configured=true
|
|
768
|
-
break
|
|
769
|
-
fi
|
|
770
|
-
done < <(get_all_shell_rcs)
|
|
771
|
-
# Also check fish config (not included in get_all_shell_rcs on macOS)
|
|
772
|
-
if [[ "$any_configured" == "false" ]]; then
|
|
773
|
-
local fish_config="$HOME/.config/fish/config.fish"
|
|
774
|
-
if [[ -f "$fish_config" ]] && grep -q "# AI Assistant Server Access" "$fish_config"; then
|
|
775
|
-
any_configured=true
|
|
776
|
-
fi
|
|
777
|
-
fi
|
|
778
|
-
|
|
779
|
-
if [[ "$any_configured" == "true" ]]; then
|
|
913
|
+
if _aliases_check_configured; then
|
|
780
914
|
print_info "Server Access aliases already configured - Skipping"
|
|
781
915
|
return 0
|
|
782
916
|
fi
|
|
@@ -795,6 +929,7 @@ ALIASES
|
|
|
795
929
|
added_to="$fish_rc"
|
|
796
930
|
else
|
|
797
931
|
# Add to all bash/zsh rc files
|
|
932
|
+
local rc_file
|
|
798
933
|
while IFS= read -r rc_file; do
|
|
799
934
|
[[ -z "$rc_file" ]] && continue
|
|
800
935
|
|