Stop conf_upgrade losing every key that follows a single-line array

This commit is contained in:
Gmer4Lfe
2026-08-10 18:42:25 -04:00
parent 74b579e281
commit 6054f68754
+50 -20
View File
@@ -249,6 +249,21 @@ elif grep -q 'HOSTN' "$TEMPLATE" 2>/dev/null; then
fi
fi
# ── Block-parsing patterns ───────────────────────────────────────────────────────────────────
# All three walkers below share these. A single-line array — KEY=(a b c) — both opens and
# closes on one line. Matching only the opener leaves the walker inside a block it never
# leaves, so every key until the next standalone ")" becomes invisible: skipped by
# _collect_stats, dropped from HOST_MAP by _parse_target, and emitted from the template
# instead of the user's conf by _write_merged. _ARR_ONELINE_RE is what stops that.
_ARR_DECL_RE='^[[:space:]]*declare[[:space:]]+-[a-zA-Z]+[[:space:]]+([A-Z0-9_]+)[[:space:]]*=\('
_ARR_OPEN_RE='^[[:space:]]*([A-Z0-9_]+)[[:space:]]*=\('
_ARR_CLOSE_RE='^[[:space:]]*\)[[:space:]]*(#.*)?$'
# The [^#]* is deliberate: it forces the closing ")" to appear before any comment, so an
# opener like FOO=( # see note (here) is not mistaken for a complete single-line array.
_ARR_ONELINE_RE='=\([^#]*\)[[:space:]]*(#.*)?$'
_SCALAR_RE='^[[:space:]]*([A-Z0-9_]+)[[:space:]]*='
# ── Parse target → KEY → full definition block ───────────────────────────────────────────────
declare -A HOST_MAP # KEY → complete definition line(s) from user's conf
@@ -260,19 +275,23 @@ _parse_target() {
if [[ "$in_block" == true ]]; then
cur_block+="$line"$'\n'
# Closing ) — optional trailing whitespace and comment
if [[ "$line" =~ ^[[:space:]]*\)[[:space:]]*(#.*)?$ ]]; then
if [[ "$line" =~ $_ARR_CLOSE_RE ]]; then
HOST_MAP["$cur_key"]="$cur_block"
in_block=false; cur_key=""; cur_block=""
fi
else
# declare -A KEY=(
if [[ "$line" =~ ^[[:space:]]*declare[[:space:]]+-[a-zA-Z]+[[:space:]]+([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true; cur_block="$line"$'\n'
# KEY=(
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true; cur_block="$line"$'\n'
# declare -A KEY=( / KEY=(
if [[ "$line" =~ $_ARR_DECL_RE ]] || [[ "$line" =~ $_ARR_OPEN_RE ]]; then
cur_key="${BASH_REMATCH[1]}"
# KEY=(a b c) — opens and closes on one line, never enter block mode
if [[ "$line" =~ $_ARR_ONELINE_RE ]]; then
HOST_MAP["$cur_key"]="$line"$'\n'
cur_key=""
else
in_block=true; cur_block="$line"$'\n'
fi
# KEY=value (simple scalar)
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*= ]]; then
elif [[ "$line" =~ $_SCALAR_RE ]]; then
HOST_MAP["${BASH_REMATCH[1]}"]="$line"$'\n'
fi
fi
@@ -289,7 +308,7 @@ _collect_stats() {
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ "$in_block" == true ]]; then
if [[ "$line" =~ ^[[:space:]]*\)[[:space:]]*(#.*)?$ ]]; then
if [[ "$line" =~ $_ARR_CLOSE_RE ]]; then
in_block=false
TMPL_SEEN["$cur_key"]=1
if [[ -n "${HOST_MAP[$cur_key]+_}" ]]; then KEPT+=("$cur_key")
@@ -297,11 +316,17 @@ _collect_stats() {
cur_key=""
fi
else
if [[ "$line" =~ ^[[:space:]]*declare[[:space:]]+-[a-zA-Z]+[[:space:]]+([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*= ]]; then
if [[ "$line" =~ $_ARR_DECL_RE ]] || [[ "$line" =~ $_ARR_OPEN_RE ]]; then
cur_key="${BASH_REMATCH[1]}"
if [[ "$line" =~ $_ARR_ONELINE_RE ]]; then
TMPL_SEEN["$cur_key"]=1
if [[ -n "${HOST_MAP[$cur_key]+_}" ]]; then KEPT+=("$cur_key")
else ADDED+=("$cur_key"); fi
cur_key=""
else
in_block=true
fi
elif [[ "$line" =~ $_SCALAR_RE ]]; then
local k="${BASH_REMATCH[1]}"
TMPL_SEEN["$k"]=1
if [[ -n "${HOST_MAP[$k]+_}" ]]; then KEPT+=("$k")
@@ -324,18 +349,23 @@ _write_merged() {
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ "$in_block" == true ]]; then
cur_block+="$line"$'\n'
if [[ "$line" =~ ^[[:space:]]*\)[[:space:]]*(#.*)?$ ]]; then
if [[ "$line" =~ $_ARR_CLOSE_RE ]]; then
in_block=false
if [[ -n "${HOST_MAP[$cur_key]+_}" ]]; then printf '%s' "${HOST_MAP[$cur_key]}"
else printf '%s' "$cur_block"; fi
cur_key=""; cur_block=""
fi
else
if [[ "$line" =~ ^[[:space:]]*declare[[:space:]]+-[a-zA-Z]+[[:space:]]+([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true; cur_block="$line"$'\n'
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*=\( ]]; then
cur_key="${BASH_REMATCH[1]}"; in_block=true; cur_block="$line"$'\n'
elif [[ "$line" =~ ^[[:space:]]*([A-Z0-9_]+)[[:space:]]*= ]]; then
if [[ "$line" =~ $_ARR_DECL_RE ]] || [[ "$line" =~ $_ARR_OPEN_RE ]]; then
cur_key="${BASH_REMATCH[1]}"
if [[ "$line" =~ $_ARR_ONELINE_RE ]]; then
if [[ -n "${HOST_MAP[$cur_key]+_}" ]]; then printf '%s' "${HOST_MAP[$cur_key]}"
else printf '%s\n' "$line"; fi
cur_key=""
else
in_block=true; cur_block="$line"$'\n'
fi
elif [[ "$line" =~ $_SCALAR_RE ]]; then
local k="${BASH_REMATCH[1]}"
if [[ -n "${HOST_MAP[$k]+_}" ]]; then printf '%s' "${HOST_MAP[$k]}"
else printf '%s\n' "$line"; fi