gnodet commented on code in PR #13406:
URL: https://github.com/apache/maven/pull/13406#discussion_r4241620884


##########
impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultProfileInjector.java:
##########
@@ -103,6 +127,94 @@ public void mergeBuildBase(BuildBase.Builder builder, 
BuildBase target, BuildBas
             mergeBuildBase(builder, target, source, true, 
Collections.emptyMap());
         }
 
+        @Override
+        protected void mergeModelBase_Properties(
+                ModelBase.Builder builder,
+                ModelBase target,
+                ModelBase source,
+                boolean sourceDominant,
+                Map<Object, Object> context) {
+            Map<String, String> src = source.getProperties();
+            Map<String, String> tgt = target.getProperties();
+            Map<String, String> merged = new LinkedHashMap<>(tgt.size() + 
src.size() * 2);
+            if (sourceDominant) {
+                merged.putAll(tgt);
+                merged.putAll(src);
+            } else {
+                merged.putAll(src);
+                merged.putAll(tgt);
+            }
+
+            if (src.isEmpty()) {
+                builder.properties(merged);
+                builder.location(
+                        "properties",
+                        InputLocation.merge(
+                                target.getLocation("properties"), 
source.getLocation("properties"), sourceDominant));
+                return;
+            }
+
+            InputLocation propsLoc = source.getLocation("properties");
+            Map<Object, InputLocation> scopedLocs = new LinkedHashMap<>();
+            if (source instanceof Profile profile) {
+                String profileId = profile.getId();
+                if (profileId != null && !profileId.isEmpty()) {
+                    String prefix = "profile." + profileId + ".";
+                    // Note: Profile IDs containing dots (e.g., "foo.bar") may 
cause key collisions
+                    // if another profile (e.g., "foo") defines a property 
that shares the same prefix
+                    // (e.g., "bar.myprop"). In such cases, last-write-wins 
applies. Profile IDs without
+                    // dots or using hyphens are recommended.
+                    // Property names of the form "profile.<id>.*" are 
reserved for profile-scoped resolution.
+                    // If an existing model property matches a scoped key, the 
profile's value takes precedence
+                    // and a warning is logged.
+                    for (Map.Entry<String, String> entry : src.entrySet()) {
+                        String key = entry.getKey();
+                        String value = entry.getValue();
+                        // Do not re-prefix properties that already start with 
"profile." to avoid redundant double-scoping
+                        // (e.g. "profile.custom" defined in profile 
"myprofile" remains as "profile.custom" rather than
+                        // generating "profile.myprofile.profile.custom").
+                        if (!key.startsWith("profile.")) {

Review Comment:
   💡 **nit:** Add a comment explaining the prefix-exclusion guard:
   
   ```suggestion
                           // Skip re-prefixing: properties already in the 
profile.* namespace
                           // are user-declared scoped references — don't 
double-prefix them.
                           if (!key.startsWith("profile.")) {
   ```



-- 
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