Stop conf_upgrade losing every key that follows a single-line array
This commit is contained in:
+50
-20
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user