feat(lib): helper ini_set idempotent pour merge de fichiers INI #24

Closed
Damien wants to merge 3 commits from feat/lib-ini-set into main
Showing only changes of commit 1217b26ff9 - Show all commits
+35 -5
View File
@@ -159,12 +159,27 @@ ini_set() {
chmod "$(stat -c '%a' "$file")" "$tmp" 2>/dev/null || true chmod "$(stat -c '%a' "$file")" "$tmp" 2>/dev/null || true
chown "$(stat -c '%u:%g' "$file")" "$tmp" 2>/dev/null || true chown "$(stat -c '%u:%g' "$file")" "$tmp" 2>/dev/null || true
awk -v section="$section" -v key="$key" -v value="$value" ' # awk writes into $tmp regardless of its own exit status — a mid-stream
# death (OOM, signal, an exotic value tripping the regex) would still
# leave a truncated-but-nonempty $tmp for `mv` to install over $file.
# Gate the mv on awk's exit code so a failure leaves the original config
# untouched instead of silently destroying it.
if ! awk -v section="$section" -v key="$key" -v value="$value" '
# Blank lines are buffered rather than printed immediately while a
# section is still awaiting insertion: without this, a key inserted
# right before the next section header lands *after* that section'"'"'s
# trailing blank line(s) instead of before them. Flushed as soon as
# either a non-blank line or the insertion itself happens, so this
# never reorders anything except relative to that pending insertion.
function flush_blanks() {
while (blank_count > 0) { print ""; blank_count-- }
}
/^\[.*\]$/ { /^\[.*\]$/ {
if (in_section && !done) { if (in_section && !done) {
printf "%s = %s\n", key, value printf "%s = %s\n", key, value
done = 1 done = 1
} }
flush_blanks()
cur = $0 cur = $0
gsub(/^\[|\]$/, "", cur) gsub(/^\[|\]$/, "", cur)
in_section = (cur == section) in_section = (cur == section)
@@ -173,9 +188,19 @@ ini_set() {
next next
} }
{ {
if (in_section && !done && match($0, "^[ \t]*" key "[ \t]*=")) { if (in_section && !done) {
printf "%s = %s\n", key, value if (match($0, "^[ \t]*" key "[ \t]*=")) {
done = 1 flush_blanks()
printf "%s = %s\n", key, value
done = 1
next
}
if ($0 ~ /^[ \t]*$/) {
blank_count++
next
}
flush_blanks()
print
next next
} }
print print
@@ -185,13 +210,18 @@ ini_set() {
printf "%s = %s\n", key, value printf "%s = %s\n", key, value
done = 1 done = 1
} }
flush_blanks()
if (!section_found) { if (!section_found) {
if (NR > 0) print "" if (NR > 0) print ""
printf "[%s]\n", section printf "[%s]\n", section
printf "%s = %s\n", key, value printf "%s = %s\n", key, value
} }
} }
' "$file" > "$tmp" ' "$file" > "$tmp"; then
rm -f "$tmp"
log_error "ini_set: awk failed on ${file} (${section}.${key}), config left untouched."
return 1
fi
mv "$tmp" "$file" mv "$tmp" "$file"
} }