codeconsole commented on code in PR #16772:
URL: https://github.com/apache/grails-core/pull/16772#discussion_r4384591399


##########
grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy:
##########
@@ -418,6 +433,58 @@ class NavigableMap implements Map<String, Object>, 
Cloneable {
         }
     }
 
+    /**
+     * Whether a bracketed flat key exports the entry, so that the walk skips 
its dotted name. Below the map, the entry
+     * {@code /api/**} of {@code routes} is exported by {@code 
routes[/api/**]} when that key exports every name and value
+     * the entry would, and not when it holds another value, such as one a 
later dotted write left behind, or a map
+     * missing some of the entry's fields. At the map itself, a flat key such 
as {@code app.routes./api/**}, which a merge
+     * writes beside the nested entry, is skipped when a bracketed key such as 
{@code app.routes[/api/**]} splits it at
+     * one of its dots, since the walk of the nested maps exports the entry.
+     */
+    private static boolean isExportedInBrackets(NavigableMap owner, 
List<String> relativePath, String key, Object value) {
+        if (relativePath) {
+            String bracketedKey = 
"${relativePath.join('.')}[${key}]".toString()
+            return owner.containsKey(bracketedKey) && 
exportsAll(owner.get(bracketedKey), value)
+        }
+        for (int dot = key.indexOf('.'); dot > 0; dot = key.indexOf('.', dot + 
1)) {

Review Comment:
   Fixed in 1b27bef89f. At the root, the walk now skips a flat key such as 
`app.routes.k` only when the bracketed key exports the same value. After your 
merge and `put`, `app.routes[k]` holds `'old'`, so `app.routes.k=new` is 
exported, as on 7.0.x.
   
   The reverse order needed a second check. After `merge(['app.routes.k': 
'old'])` and `merge(['app.routes[k]': 'new'])`, the flat key `app.routes.k` 
keeps `'old'`, while the nested map and the bracketed key hold `'new'`. 
Comparing values at the root alone would have exported that stale `'old'`. So 
the walk also skips a nested entry only when the map it walks holds no flat key 
under the entry's dotted name with another value.
   
   Where the copies disagree, both are exported as on 7.0.x, and the value 
written last wins under the dotted name: `'new'` in both orders. The export 
can't tell a flat key a `put` wrote last from one a later merge left behind, so 
it keeps 7.0.x's answer for both. Where they agree, as for a map from 
application.yml, the entry is still exported once, in brackets.
   
   "The value written last under a dotted name or in brackets is flattened 
under the dotted name" in `ConfigMapSpec` covers your `put` and the reverse 
order through `toFlatConfig()` and `toProperties()`. Both rows fail at 
cfecb81969, the previous head, which merges in 7.0.x with #16769. Both modules' 
suites pass, including the YAML and CORS key sets.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to