Browse code

Allow multi-line config items in meta-section of local.conf

It would behave such as the contents from each meta-section in
local.conf is copied to the destination files. One exception is the multiline
options not grouped together. In that case, the contents will be grouped
together in its destination config file.

Check tests/test_config.sh for examples.

Change-Id: I8c046b558eeb98ed221f6f1a59182d4179956ced
Partial-Bug: #1374118

Robert Li authored on 2014/10/11 01:43:05
Showing 3 changed files
... ...
@@ -119,6 +119,33 @@ function ini_has_option {
119 119
     [ -n "$line" ]
120 120
 }
121 121
 
122
+# Add another config line for a multi-line option.
123
+# It's normally called after iniset of the same option and assumes
124
+# that the section already exists.
125
+#
126
+# Note that iniset_multiline requires all the 'lines' to be supplied
127
+# in the argument list. Doing that will cause incorrect configuration
128
+# if spaces are used in the config values.
129
+#
130
+# iniadd_literal config-file section option value
131
+function iniadd_literal {
132
+    local xtrace=$(set +o | grep xtrace)
133
+    set +o xtrace
134
+    local file=$1
135
+    local section=$2
136
+    local option=$3
137
+    local value=$4
138
+
139
+    [[ -z $section || -z $option ]] && return
140
+
141
+    # Add it
142
+    sed -i -e "/^\[$section\]/ a\\
143
+$option = $value
144
+" "$file"
145
+
146
+    $xtrace
147
+}
148
+
122 149
 # Set an option in an INI file
123 150
 # iniset config-file section option value
124 151
 function iniset {
... ...
@@ -86,7 +86,11 @@ function merge_config_file {
86 86
     # having to do nasty quoting games
87 87
     get_meta_section $file $matchgroup $configfile | \
88 88
     $CONFIG_AWK_CMD -v configfile=$configfile '
89
-        BEGIN { section = "" }
89
+        BEGIN {
90
+            section = ""
91
+            last_section = ""
92
+            section_count = 0
93
+        }
90 94
         /^\[.+\]/ {
91 95
             gsub("[][]", "", $1);
92 96
             section=$1
... ...
@@ -106,10 +110,48 @@ function merge_config_file {
106 106
             # need to strip leading & trailing whitespace from value
107 107
             sub(/^[ \t]*/, "", value)
108 108
             sub(/[ \t]*$/, "", value)
109
-            print "iniset " configfile " " section " " attr " \x27" value "\x27"
109
+
110
+            # cfg_attr_count: number of config lines per [section, attr]
111
+            # cfg_attr: two dimensional array to keep all the config lines per [section, attr]
112
+            # cfg_section: keep the section names in the same order as they appear in local.conf
113
+            # cfg_sec_attr_name: keep the attr names in the same order as they appear in local.conf
114
+            if (! (section, attr) in cfg_attr_count) {
115
+                if (section != last_section) {
116
+                    cfg_section[section_count++] = section
117
+                    last_section = section
118
+                }
119
+                attr_count = cfg_sec_attr_count[section_count - 1]++
120
+                cfg_sec_attr_name[section_count - 1][attr_count] = attr
121
+
122
+                cfg_attr[section, attr][0] = value
123
+                cfg_attr_count[section, attr] = 1
124
+            } else {
125
+                lno = cfg_attr_count[section, attr]++
126
+                cfg_attr[section, attr][lno] = value
127
+            }
128
+        }
129
+        END {
130
+            # Process each section in order
131
+            for (sno = 0; sno < section_count; sno++) {
132
+                section = cfg_section[sno]
133
+                # The ini routines simply append a config item immediately
134
+                # after the section header. To keep the same order as defined
135
+                # in local.conf, invoke the ini routines in the reverse order
136
+                for (attr_no = cfg_sec_attr_count[sno] - 1; attr_no >=0; attr_no--) {
137
+                    attr = cfg_sec_attr_name[sno][attr_no]
138
+                    if (cfg_attr_count[section, attr] == 1)
139
+                        print "iniset " configfile " " section " " attr " \x27" cfg_attr[section, attr][0] "\x27"
140
+                    else {
141
+                        # For multiline, invoke the ini routines in the reverse order
142
+                        count = cfg_attr_count[section, attr]
143
+                        print "iniset " configfile " " section " " attr " \x27" cfg_attr[section, attr][count - 1] "\x27"
144
+                        for (l = count -2; l >= 0; l--)
145
+                            print "iniadd_literal " configfile " " section " " attr " \x27" cfg_attr[section, attr][l] "\x27"
146
+                    }
147
+                }
148
+            }
110 149
         }
111 150
     ' | while read a; do eval "$a"; done
112
-
113 151
 }
114 152
 
115 153
 
... ...
@@ -104,6 +104,27 @@ drivers = driver=python.import.path.Driver
104 104
 [DEFAULT]
105 105
 # next line has trailing space
106 106
 attr = strip_trailing_space 
107
+
108
+[[test-multi-sections|test-multi-sections.conf]]
109
+[sec-1]
110
+cfg_item1 = abcd
111
+cfg_item2 = efgh
112
+
113
+[sec-2]
114
+cfg_item1 = abcd
115
+cfg_item3 = /1/2/3/4:5
116
+cfg_item4 = end
117
+
118
+[sec-3]
119
+cfg_item5 = 5555
120
+cfg_item6 = 6666
121
+cfg_item5 = 5555another
122
+
123
+[[test-multiline|test-multiline.conf]]
124
+[multi]
125
+cfg_item1 = "ab":"cd", "ef":   "gh"
126
+cfg_item1 = abcd
127
+cfg_item2 = efgh
107 128
 EOF
108 129
 
109 130
 echo -n "get_meta_section_files: test0 doesn't exist: "
... ...
@@ -185,8 +206,39 @@ VAL=$(cat test2a.conf)
185 185
 # iniset adds a blank line if it creates the file...
186 186
 EXPECT_VAL="
187 187
 [ddd]
188
-additional = true
189
-type = new"
188
+type = new
189
+additional = true"
190
+check_result "$VAL" "$EXPECT_VAL"
191
+
192
+echo -n "merge_config_file test-multi-sections: "
193
+rm -f test-multi-sections.conf
194
+merge_config_file test.conf test-multi-sections test-multi-sections.conf
195
+VAL=$(cat test-multi-sections.conf)
196
+EXPECT_VAL='
197
+[sec-1]
198
+cfg_item1 = abcd
199
+cfg_item2 = efgh
200
+
201
+[sec-2]
202
+cfg_item1 = abcd
203
+cfg_item3 = /1/2/3/4:5
204
+cfg_item4 = end
205
+
206
+[sec-3]
207
+cfg_item5 = 5555
208
+cfg_item5 = 5555another
209
+cfg_item6 = 6666'
210
+check_result "$VAL" "$EXPECT_VAL"
211
+
212
+echo -n "merge_config_file test-multiline: "
213
+rm -f test-multiline.conf
214
+merge_config_file test.conf test-multiline test-multiline.conf
215
+VAL=$(cat test-multiline.conf)
216
+EXPECT_VAL='
217
+[multi]
218
+cfg_item1 = "ab":"cd", "ef":   "gh"
219
+cfg_item1 = abcd
220
+cfg_item2 = efgh'
190 221
 check_result "$VAL" "$EXPECT_VAL"
191 222
 
192 223
 echo -n "merge_config_group test2: "
... ...
@@ -196,8 +248,8 @@ VAL=$(cat test2a.conf)
196 196
 # iniset adds a blank line if it creates the file...
197 197
 EXPECT_VAL="
198 198
 [ddd]
199
-additional = true
200
-type = new"
199
+type = new
200
+additional = true"
201 201
 check_result "$VAL" "$EXPECT_VAL"
202 202
 
203 203
 echo -n "merge_config_group test2 no conf file: "
... ...
@@ -268,4 +320,5 @@ attr = strip_trailing_space"
268 268
 check_result "$VAL" "$EXPECT_VAL"
269 269
 
270 270
 rm -f test.conf test1c.conf test2a.conf test-quote.conf test-space.conf test-equals.conf test-strip.conf
271
+rm -f test-multiline.conf test-multi-sections.conf
271 272
 rm -rf test-etc