Skip to content

Commit 88521a1

Browse files
committed
fix: remove jq dependency from optimize command (#588)
Replace jq with bash-native JSON parsing helpers (json_get_value, json_validate, parse_optimization_items) so that mo optimize no longer requires jq to be installed. Closes #588
1 parent 6e1048a commit 88521a1

File tree

1 file changed

+78
-28
lines changed

1 file changed

+78
-28
lines changed

bin/optimize.sh

Lines changed: 78 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,72 @@ print_header() {
2828
echo -e "${PURPLE_BOLD}Optimize and Check${NC}"
2929
}
3030

31+
# Bash-native JSON parsing helpers (no jq dependency).
32+
# Extract a simple numeric value from JSON by key.
33+
json_get_value() {
34+
local json="$1"
35+
local key="$2"
36+
local value
37+
value=$(echo "$json" | grep -o "\"${key}\"[[:space:]]*:[[:space:]]*[0-9.]*" | head -1 | sed 's/.*:[[:space:]]*//')
38+
echo "${value:-0}"
39+
}
40+
41+
# Validate JSON has expected structure (basic check).
42+
json_validate() {
43+
local json="$1"
44+
# Check for required keys
45+
[[ "$json" == *'"memory_used_gb"'* ]] &&
46+
[[ "$json" == *'"optimizations"'* ]] &&
47+
[[ "$json" == *'{'* ]] && [[ "$json" == *'}'* ]]
48+
}
49+
50+
# Parse optimization items from JSON array.
51+
# Outputs pipe-delimited records: action|name|description|safe
52+
parse_optimization_items() {
53+
local json="$1"
54+
# Extract the optimizations array content
55+
local in_array=false
56+
local brace_count=0
57+
local current_item=""
58+
59+
while IFS= read -r line; do
60+
# Detect start of optimizations array
61+
if [[ "$line" == *'"optimizations"'*'['* ]]; then
62+
in_array=true
63+
continue
64+
fi
65+
66+
[[ "$in_array" != "true" ]] && continue
67+
68+
# Count braces to track object boundaries
69+
if [[ "$line" == *'{'* ]]; then
70+
((brace_count++))
71+
fi
72+
73+
if ((brace_count > 0)); then
74+
current_item+="$line"
75+
fi
76+
77+
if [[ "$line" == *'}'* ]]; then
78+
((brace_count--))
79+
if ((brace_count == 0)) && [[ -n "$current_item" ]]; then
80+
# Extract fields from the collected item
81+
local action name desc safe
82+
action=$(echo "$current_item" | grep -o '"action"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"action"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
83+
name=$(echo "$current_item" | grep -o '"name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
84+
desc=$(echo "$current_item" | grep -o '"description"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"description"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
85+
safe=$(echo "$current_item" | grep -o '"safe"[[:space:]]*:[[:space:]]*[a-z]*' | sed 's/.*:[[:space:]]*//')
86+
87+
[[ -n "$action" ]] && echo "${action}|${name}|${desc}|${safe}"
88+
current_item=""
89+
fi
90+
fi
91+
92+
# End of array
93+
[[ "$line" == *']'* ]] && ((brace_count == 0)) && break
94+
done <<< "$json"
95+
}
96+
3197
run_system_checks() {
3298
# Skip checks in dry-run mode.
3399
if [[ "${MOLE_DRY_RUN:-0}" == "1" ]]; then
@@ -139,12 +205,12 @@ show_optimization_summary() {
139205
show_system_health() {
140206
local health_json="$1"
141207

142-
local mem_used=$(echo "$health_json" | jq -r '.memory_used_gb // 0' 2> /dev/null || echo "0")
143-
local mem_total=$(echo "$health_json" | jq -r '.memory_total_gb // 0' 2> /dev/null || echo "0")
144-
local disk_used=$(echo "$health_json" | jq -r '.disk_used_gb // 0' 2> /dev/null || echo "0")
145-
local disk_total=$(echo "$health_json" | jq -r '.disk_total_gb // 0' 2> /dev/null || echo "0")
146-
local disk_percent=$(echo "$health_json" | jq -r '.disk_used_percent // 0' 2> /dev/null || echo "0")
147-
local uptime=$(echo "$health_json" | jq -r '.uptime_days // 0' 2> /dev/null || echo "0")
208+
local mem_used=$(json_get_value "$health_json" "memory_used_gb")
209+
local mem_total=$(json_get_value "$health_json" "memory_total_gb")
210+
local disk_used=$(json_get_value "$health_json" "disk_used_gb")
211+
local disk_total=$(json_get_value "$health_json" "disk_total_gb")
212+
local disk_percent=$(json_get_value "$health_json" "disk_used_percent")
213+
local uptime=$(json_get_value "$health_json" "uptime_days")
148214

149215
mem_used=${mem_used:-0}
150216
mem_total=${mem_total:-0}
@@ -157,11 +223,6 @@ show_system_health() {
157223
"$mem_used" "$mem_total" "$disk_used" "$disk_total" "$uptime"
158224
}
159225

160-
parse_optimizations() {
161-
local health_json="$1"
162-
echo "$health_json" | jq -c '.optimizations[]' 2> /dev/null
163-
}
164-
165226
announce_action() {
166227
local name="$1"
167228
local desc="$2"
@@ -406,12 +467,6 @@ main() {
406467
echo -e "${YELLOW}${ICON_DRY_RUN} DRY RUN MODE${NC}, No files will be modified\n"
407468
fi
408469

409-
if ! command -v jq > /dev/null 2>&1; then
410-
echo -e "${YELLOW}${ICON_ERROR}${NC} Missing dependency: jq"
411-
echo -e "${GRAY}Install with: ${GREEN}brew install jq${NC}"
412-
exit 1
413-
fi
414-
415470
if ! command -v bc > /dev/null 2>&1; then
416471
echo -e "${YELLOW}${ICON_ERROR}${NC} Missing dependency: bc"
417472
echo -e "${GRAY}Install with: ${GREEN}brew install bc${NC}"
@@ -431,13 +486,13 @@ main() {
431486
exit 1
432487
fi
433488

434-
if ! echo "$health_json" | jq empty 2> /dev/null; then
489+
if ! json_validate "$health_json"; then
435490
if [[ -t 1 ]]; then
436491
stop_inline_spinner
437492
fi
438493
echo ""
439494
log_error "Invalid system health data format"
440-
echo -e "${GRAY}${ICON_REVIEW}${NC} Check if jq, awk, sysctl, and df commands are available"
495+
echo -e "${GRAY}${ICON_REVIEW}${NC} Check if awk, sysctl, and df commands are available"
441496
exit 1
442497
fi
443498

@@ -463,17 +518,12 @@ main() {
463518
local -a confirm_items=()
464519
local opts_file
465520
opts_file=$(mktemp_file)
466-
parse_optimizations "$health_json" > "$opts_file"
467-
468-
while IFS= read -r opt_json; do
469-
[[ -z "$opt_json" ]] && continue
521+
parse_optimization_items "$health_json" > "$opts_file"
470522

471-
local name=$(echo "$opt_json" | jq -r '.name')
472-
local desc=$(echo "$opt_json" | jq -r '.description')
473-
local action=$(echo "$opt_json" | jq -r '.action')
474-
local path=$(echo "$opt_json" | jq -r '.path // ""')
475-
local safe=$(echo "$opt_json" | jq -r '.safe')
523+
while IFS='|' read -r action name desc safe; do
524+
[[ -z "$action" ]] && continue
476525

526+
local path=""
477527
local item="${name}|${desc}|${action}|${path}"
478528

479529
if [[ "$safe" == "true" ]]; then

0 commit comments

Comments
 (0)