167778
From 7e2b7bb44c4996c425a93f6aacf151480cd08595 Mon Sep 17 00:00:00 2001
167778
From: Robbie Harwood <rharwood@redhat.com>
167778
Date: Tue, 10 Apr 2018 15:55:41 -0400
167778
Subject: [PATCH] Merge duplicate subsections in profile library
167778
167778
Modify profile_add_node() to return the existing node, rather than
167778
making a new one, when adding subsection configuration.
167778
167778
This fixes an issue where the first instance of a subsection will hide
167778
the second instance entirely.  In particular, it was previously
167778
impossible to split realm-specific configuration across multiple
167778
config files.
167778
167778
[ghudson@mit.edu: adjusted style, added test case]
167778
167778
(cherry picked from commit efab9fa5a6d23c486467264e20b58bf5a9c60f0c)
167778
167778
ticket: 7863
167778
version_fixed: 1.16.1
167778
167778
(cherry picked from commit 98d0061c8083af960438ad1ac088f60497694a68)
167778
---
167778
 src/util/profile/prof_test1  | 22 ++++++++++++++++++++++
167778
 src/util/profile/prof_tree.c | 15 +++++++++++----
167778
 src/util/profile/test.ini    |  6 ++++++
167778
 3 files changed, 39 insertions(+), 4 deletions(-)
167778
167778
diff --git a/src/util/profile/prof_test1 b/src/util/profile/prof_test1
167778
index 7e30fc12f..7d13c9389 100644
167778
--- a/src/util/profile/prof_test1
167778
+++ b/src/util/profile/prof_test1
167778
@@ -341,6 +341,27 @@ proc test9 {} {
167778
     puts "OK: test9: profile_flush_to_file with no changes"
167778
 }
167778
 
167778
+proc test10 {} {
167778
+    global wd verbose
167778
+
167778
+    # Regression test for #7863: multiply-specified subsections should
167778
+    # be merged.
167778
+    set p [profile_init_path $wd/test2.ini]
167778
+    set x [profile_get_values $p {{test section 2} child_section2 child}]
167778
+    if $verbose { puts "Read $x from profile" }
167778
+    if ![string equal $x "slick harry {john\tb } ron"] {
167778
+	puts stderr "Error: test10: Did not get expected merged children."
167778
+	exit 1
167778
+    }
167778
+
167778
+    set x [profile_get_string $p {test section 2} child_section2 chores]
167778
+    if $verbose { puts "Read $x from profile" }
167778
+    if ![string equal $x "cleaning"] {
167778
+	puts stderr "Error: test10: Did not find expected chores."
167778
+	exit 1
167778
+    }
167778
+}
167778
+
167778
 test1
167778
 test2
167778
 test3
167778
@@ -350,5 +371,6 @@ test6
167778
 test7
167778
 test8
167778
 test9
167778
+test10
167778
 
167778
 exit 0
167778
diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c
167778
index 081f688e4..38aadc4e5 100644
167778
--- a/src/util/profile/prof_tree.c
167778
+++ b/src/util/profile/prof_tree.c
167778
@@ -9,7 +9,7 @@
167778
  *
167778
  * Each node may represent either a relation or a section header.
167778
  *
167778
- * A section header must have its value field set to 0, and may a one
167778
+ * A section header must have its value field be null, and may have one
167778
  * or more child nodes, pointed to by first_child.
167778
  *
167778
  * A relation has as its value a pointer to allocated memory
167778
@@ -159,15 +159,22 @@ errcode_t profile_add_node(struct profile_node *section, const char *name,
167778
         return PROF_ADD_NOT_SECTION;
167778
 
167778
     /*
167778
-     * Find the place to insert the new node.  We look for the
167778
-     * place *after* the last match of the node name, since
167778
+     * Find the place to insert the new node.  If we are adding a subsection
167778
+     * and already have a subsection with that name, merge them.  Otherwise,
167778
+     * we look for the place *after* the last match of the node name, since
167778
      * order matters.
167778
      */
167778
     for (p=section->first_child, last = 0; p; last = p, p = p->next) {
167778
         int cmp;
167778
         cmp = strcmp(p->name, name);
167778
-        if (cmp > 0)
167778
+        if (cmp > 0) {
167778
             break;
167778
+        } else if (value == NULL && cmp == 0 &&
167778
+                   p->value == NULL && p->deleted != 1) {
167778
+            /* Found duplicate subsection, so don't make a new one. */
167778
+            *ret_node = p;
167778
+            return 0;
167778
+        }
167778
     }
167778
     retval = profile_create_node(name, value, &new;;
167778
     if (retval)
167778
diff --git a/src/util/profile/test.ini b/src/util/profile/test.ini
167778
index 23ca89677..6622df108 100644
167778
--- a/src/util/profile/test.ini
167778
+++ b/src/util/profile/test.ini
167778
@@ -10,6 +10,12 @@ this is a comment.  Everything up to the first square brace is ignored.
167778
 	}
167778
 	child_section2 = foo
167778
 
167778
+[test section 2]
167778
+	child_section2 = {
167778
+		child = ron
167778
+		chores = cleaning
167778
+	}
167778
+
167778
 [realms]
167778
 ATHENA.MIT.EDU = {
167778
 	server = KERBEROS.MIT.EDU:88