diff --git a/lib/common.sh b/lib/common.sh index 209e62d..1e0bc2f 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -871,6 +871,55 @@ ini_set() { mv "$tmpfile" "$file" } +# Copy all key=value pairs from one INI section into a new section. +# Usage: ini_copy_section "file" "source_section" "dest_section" +ini_copy_section() { + local file="$1" src="$2" dst="$3" + # Read source section into arrays first (ini_set rewrites the file) + local in_section=false line k v + local keys=() vals=() + while IFS= read -r line; do + line="${line#"${line%%[![:space:]]*}"}" + line="${line%"${line##*[![:space:]]}"}" + [[ -z "$line" || "$line" == \#* ]] && continue + if [[ "$line" =~ ^\[([^]]+)\] ]]; then + if [[ "${BASH_REMATCH[1]}" == "$src" ]]; then in_section=true; else $in_section && break; fi + continue + fi + if $in_section && [[ "$line" =~ ^([^=]+)=(.*) ]]; then + k="${BASH_REMATCH[1]}"; v="${BASH_REMATCH[2]}" + k="${k#"${k%%[![:space:]]*}"}"; k="${k%"${k##*[![:space:]]}"}" + v="${v#"${v%%[![:space:]]*}"}"; v="${v%"${v##*[![:space:]]}"}" + keys+=("$k"); vals+=("$v") + fi + done < "$file" + # Now write to destination section + local i + for i in "${!keys[@]}"; do + ini_set "$file" "$dst" "${keys[$i]}" "${vals[$i]}" + done +} + +# Remove an entire INI section (header + all keys until next section). +# Usage: ini_remove_section "file" "section_name" +ini_remove_section() { + local file="$1" section="$2" + local tmpfile in_section=false + tmpfile=$(mktemp) + while IFS= read -r line; do + if [[ "$line" =~ ^[[:space:]]*\[([^]]+)\] ]]; then + if [[ "${BASH_REMATCH[1]}" == "$section" ]]; then + in_section=true; continue + else + in_section=false + fi + fi + $in_section && continue + printf '%s\n' "$line" >> "$tmpfile" + done < "$file" + mv "$tmpfile" "$file" +} + # --------------------------------------------------------------------------- # Install manifest — tracks what each setup script installs for rollback # ---------------------------------------------------------------------------