Merge "Allow multi-line config items in meta-section of local.conf"
diff --git a/functions-common b/functions-common
index 5b29fd3..1f90da7 100644
--- a/functions-common
+++ b/functions-common
@@ -119,6 +119,33 @@
[ -n "$line" ]
}
+# Add another config line for a multi-line option.
+# It's normally called after iniset of the same option and assumes
+# that the section already exists.
+#
+# Note that iniset_multiline requires all the 'lines' to be supplied
+# in the argument list. Doing that will cause incorrect configuration
+# if spaces are used in the config values.
+#
+# iniadd_literal config-file section option value
+function iniadd_literal {
+ local xtrace=$(set +o | grep xtrace)
+ set +o xtrace
+ local file=$1
+ local section=$2
+ local option=$3
+ local value=$4
+
+ [[ -z $section || -z $option ]] && return
+
+ # Add it
+ sed -i -e "/^\[$section\]/ a\\
+$option = $value
+" "$file"
+
+ $xtrace
+}
+
# Set an option in an INI file
# iniset config-file section option value
function iniset {
diff --git a/lib/config b/lib/config
index b44e79a..6e8219c 100644
--- a/lib/config
+++ b/lib/config
@@ -86,7 +86,11 @@
# having to do nasty quoting games
get_meta_section $file $matchgroup $configfile | \
$CONFIG_AWK_CMD -v configfile=$configfile '
- BEGIN { section = "" }
+ BEGIN {
+ section = ""
+ last_section = ""
+ section_count = 0
+ }
/^\[.+\]/ {
gsub("[][]", "", $1);
section=$1
@@ -106,10 +110,48 @@
# need to strip leading & trailing whitespace from value
sub(/^[ \t]*/, "", value)
sub(/[ \t]*$/, "", value)
- print "iniset " configfile " " section " " attr " \x27" value "\x27"
+
+ # cfg_attr_count: number of config lines per [section, attr]
+ # cfg_attr: two dimensional array to keep all the config lines per [section, attr]
+ # cfg_section: keep the section names in the same order as they appear in local.conf
+ # cfg_sec_attr_name: keep the attr names in the same order as they appear in local.conf
+ if (! (section, attr) in cfg_attr_count) {
+ if (section != last_section) {
+ cfg_section[section_count++] = section
+ last_section = section
+ }
+ attr_count = cfg_sec_attr_count[section_count - 1]++
+ cfg_sec_attr_name[section_count - 1][attr_count] = attr
+
+ cfg_attr[section, attr][0] = value
+ cfg_attr_count[section, attr] = 1
+ } else {
+ lno = cfg_attr_count[section, attr]++
+ cfg_attr[section, attr][lno] = value
+ }
+ }
+ END {
+ # Process each section in order
+ for (sno = 0; sno < section_count; sno++) {
+ section = cfg_section[sno]
+ # The ini routines simply append a config item immediately
+ # after the section header. To keep the same order as defined
+ # in local.conf, invoke the ini routines in the reverse order
+ for (attr_no = cfg_sec_attr_count[sno] - 1; attr_no >=0; attr_no--) {
+ attr = cfg_sec_attr_name[sno][attr_no]
+ if (cfg_attr_count[section, attr] == 1)
+ print "iniset " configfile " " section " " attr " \x27" cfg_attr[section, attr][0] "\x27"
+ else {
+ # For multiline, invoke the ini routines in the reverse order
+ count = cfg_attr_count[section, attr]
+ print "iniset " configfile " " section " " attr " \x27" cfg_attr[section, attr][count - 1] "\x27"
+ for (l = count -2; l >= 0; l--)
+ print "iniadd_literal " configfile " " section " " attr " \x27" cfg_attr[section, attr][l] "\x27"
+ }
+ }
+ }
}
' | while read a; do eval "$a"; done
-
}
diff --git a/tests/test_config.sh b/tests/test_config.sh
index 6fff29c..696e57f 100755
--- a/tests/test_config.sh
+++ b/tests/test_config.sh
@@ -104,6 +104,27 @@
[DEFAULT]
# next line has trailing space
attr = strip_trailing_space
+
+[[test-multi-sections|test-multi-sections.conf]]
+[sec-1]
+cfg_item1 = abcd
+cfg_item2 = efgh
+
+[sec-2]
+cfg_item1 = abcd
+cfg_item3 = /1/2/3/4:5
+cfg_item4 = end
+
+[sec-3]
+cfg_item5 = 5555
+cfg_item6 = 6666
+cfg_item5 = 5555another
+
+[[test-multiline|test-multiline.conf]]
+[multi]
+cfg_item1 = "ab":"cd", "ef": "gh"
+cfg_item1 = abcd
+cfg_item2 = efgh
EOF
echo -n "get_meta_section_files: test0 doesn't exist: "
@@ -185,8 +206,39 @@
# iniset adds a blank line if it creates the file...
EXPECT_VAL="
[ddd]
-additional = true
-type = new"
+type = new
+additional = true"
+check_result "$VAL" "$EXPECT_VAL"
+
+echo -n "merge_config_file test-multi-sections: "
+rm -f test-multi-sections.conf
+merge_config_file test.conf test-multi-sections test-multi-sections.conf
+VAL=$(cat test-multi-sections.conf)
+EXPECT_VAL='
+[sec-1]
+cfg_item1 = abcd
+cfg_item2 = efgh
+
+[sec-2]
+cfg_item1 = abcd
+cfg_item3 = /1/2/3/4:5
+cfg_item4 = end
+
+[sec-3]
+cfg_item5 = 5555
+cfg_item5 = 5555another
+cfg_item6 = 6666'
+check_result "$VAL" "$EXPECT_VAL"
+
+echo -n "merge_config_file test-multiline: "
+rm -f test-multiline.conf
+merge_config_file test.conf test-multiline test-multiline.conf
+VAL=$(cat test-multiline.conf)
+EXPECT_VAL='
+[multi]
+cfg_item1 = "ab":"cd", "ef": "gh"
+cfg_item1 = abcd
+cfg_item2 = efgh'
check_result "$VAL" "$EXPECT_VAL"
echo -n "merge_config_group test2: "
@@ -196,8 +248,8 @@
# iniset adds a blank line if it creates the file...
EXPECT_VAL="
[ddd]
-additional = true
-type = new"
+type = new
+additional = true"
check_result "$VAL" "$EXPECT_VAL"
echo -n "merge_config_group test2 no conf file: "
@@ -268,4 +320,5 @@
check_result "$VAL" "$EXPECT_VAL"
rm -f test.conf test1c.conf test2a.conf test-quote.conf test-space.conf test-equals.conf test-strip.conf
+rm -f test-multiline.conf test-multi-sections.conf
rm -rf test-etc