This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git


The following commit(s) were added to refs/heads/master by this push:
     new a97109a  SLING-13291 - Fix false repo-init conflict detection caused 
by first primaryType in create path (#61)
a97109a is described below

commit a97109a634b4f6e7176cce9c33f86e1bff2445c0
Author: michalwedzik <[email protected]>
AuthorDate: Thu Aug 6 15:31:13 2026 +0200

    SLING-13291 - Fix false repo-init conflict detection caused by first 
primaryType in create path (#61)
    
    ---------
    
    Co-authored-by: sii12877 <[email protected]>
---
 pom.xml                                            |   5 +
 .../RepoInitConflictsValidator.java                |  17 +--
 .../task/impl/CheckRepoInitConflictsTest.java      | 120 +++++++++++++++------
 3 files changed, 103 insertions(+), 39 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9c239eb..b8c389d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,6 +164,11 @@
             <artifactId>junit-jupiter-api</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
diff --git 
a/src/main/java/org/apache/sling/feature/analyser/task/impl/repoinitconflicts/RepoInitConflictsValidator.java
 
b/src/main/java/org/apache/sling/feature/analyser/task/impl/repoinitconflicts/RepoInitConflictsValidator.java
index ae4ffbc..f912a39 100644
--- 
a/src/main/java/org/apache/sling/feature/analyser/task/impl/repoinitconflicts/RepoInitConflictsValidator.java
+++ 
b/src/main/java/org/apache/sling/feature/analyser/task/impl/repoinitconflicts/RepoInitConflictsValidator.java
@@ -95,20 +95,17 @@ public class RepoInitConflictsValidator {
         List<PathSegmentDefinition> aDefs = a.getDefinitions();
         List<PathSegmentDefinition> bDefs = b.getDefinitions();
 
-        // different depth → no conflict
-        if (aDefs.size() != bDefs.size()) {
+        String aWithoutTypes = pathWithoutTypes(a);
+        String bWithoutTypes = pathWithoutTypes(b);
+        if (!aWithoutTypes.equals(bWithoutTypes)) {
             return Collections.emptyList();
         }
+
         List<CreatePath[]> conflicts = new ArrayList<>();
         for (int i = 0; i < aDefs.size(); i++) {
             PathSegmentDefinition aSeg = aDefs.get(i);
             PathSegmentDefinition bSeg = bDefs.get(i);
 
-            // segments diverge → stop comparing this pair
-            if (!Objects.equals(aSeg.getSegment(), bSeg.getSegment())) {
-                return Collections.emptyList();
-            }
-
             // same segment but different type → conflict
             if (!Objects.equals(aSeg.getPrimaryType(), bSeg.getPrimaryType())) 
{
                 CreatePath[] conflict = new CreatePath[2];
@@ -121,4 +118,10 @@ public class RepoInitConflictsValidator {
         }
         return conflicts;
     }
+
+    private static String pathWithoutTypes(final CreatePath createPath) {
+        return createPath.getDefinitions().stream()
+                .map(PathSegmentDefinition::getSegment)
+                .collect(Collectors.joining("/"));
+    }
 }
diff --git 
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoInitConflictsTest.java
 
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoInitConflictsTest.java
index 35c17c7..cd46394 100644
--- 
a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoInitConflictsTest.java
+++ 
b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckRepoInitConflictsTest.java
@@ -18,15 +18,24 @@
  */
 package org.apache.sling.feature.analyser.task.impl;
 
+import java.util.stream.Stream;
+
 import org.apache.sling.feature.Extension;
 import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.analyser.task.AnalyserTask;
 import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
 import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.contains;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 class CheckRepoInitConflictsTest {
 
@@ -40,84 +49,131 @@ class CheckRepoInitConflictsTest {
 
     @Test
     void shouldNotReportWarningWhenNoRepoinit() {
-        final AnalyserTaskContext ctx = 
Mockito.mock(AnalyserTaskContext.class);
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
+
+        Feature feature = mock(Feature.class);
+        org.apache.sling.feature.Extensions extensions = 
mock(org.apache.sling.feature.Extensions.class);
+
+        when(ctx.getFeature()).thenReturn(feature);
+        when(feature.getExtensions()).thenReturn(extensions);
+        when(extensions.getByName("repoinit")).thenReturn(null);
+
+        CheckRepoInitConflicts task = new CheckRepoInitConflicts();
+        task.execute(ctx);
+
+        verify(ctx).getFeature();
+        verifyNoMoreInteractions(ctx);
+    }
 
-        Feature feature = Mockito.mock(Feature.class);
-        org.apache.sling.feature.Extensions extensions = 
Mockito.mock(org.apache.sling.feature.Extensions.class);
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("nonConflictingRepoinitStatements")
+    void shouldNotReportWarningWhenNoConflicts(String scenario, String 
repoinitText) {
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
 
-        Mockito.when(ctx.getFeature()).thenReturn(feature);
-        Mockito.when(feature.getExtensions()).thenReturn(extensions);
-        Mockito.when(extensions.getByName("repoinit")).thenReturn(null);
+        Feature feature = featureWithExtension(textExtension(repoinitText));
+
+        when(ctx.getFeature()).thenReturn(feature);
 
         CheckRepoInitConflicts task = new CheckRepoInitConflicts();
         task.execute(ctx);
 
-        Mockito.verify(ctx).getFeature();
-        Mockito.verifyNoMoreInteractions(ctx);
+        verify(ctx).getFeature();
+        verifyNoMoreInteractions(ctx);
+    }
+
+    private static Stream<Arguments> nonConflictingRepoinitStatements() {
+        return Stream.of(
+                Arguments.of(
+                        "shouldNotReportWarningWhenNoConflicts",
+                        "create path (sling:Folder) /apps/a/b\n" + "create 
path (sling:Folder) /apps/a/c"),
+                Arguments.of(
+                        
"shouldNotReportWarningWhenDifferentTypesOnTheBeginning",
+                        "create path (sling:Folder) /content/dam/a\n"
+                                + "create path (sling:OrderedFolder) 
/content/dam/b"),
+                Arguments.of(
+                        "shouldNotReportWarningWhenSimilarPaths",
+                        "create path (sling:Folder) /con/tent/my/nestedpath\n"
+                                + "create path (sling:Folder) 
/content/my/nested/path(cq:ClientLibraryFolder)"));
     }
 
     @Test
-    void shouldNotReportWarningWhenNoConflicts() {
-        final AnalyserTaskContext ctx = 
Mockito.mock(AnalyserTaskContext.class);
+    void shouldNotReportWarningWhenOddNumberOfPaths() {
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
 
-        Feature feature = featureWithExtension(
-                textExtension("create path (sling:Folder) /apps/a/b\n" + 
"create path (sling:Folder) /apps/a/c"));
+        Feature feature = featureWithExtension(textExtension("create path 
(sling:Folder) /content/dam/a\n"));
 
-        Mockito.when(ctx.getFeature()).thenReturn(feature);
+        when(ctx.getFeature()).thenReturn(feature);
 
         CheckRepoInitConflicts task = new CheckRepoInitConflicts();
         task.execute(ctx);
 
-        Mockito.verify(ctx).getFeature();
-        Mockito.verifyNoMoreInteractions(ctx);
+        verify(ctx).getFeature();
+        verifyNoMoreInteractions(ctx);
     }
 
     @Test
     void shouldReportWarningWhenConflictExists() {
-        final AnalyserTaskContext ctx = 
Mockito.mock(AnalyserTaskContext.class);
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
 
         Feature feature =
                 featureWithExtension(textExtension("create path (sling:Folder) 
/apps/a/b(cq:ClientLibraryFolder)\n"
                         + "create path (sling:Folder) /apps/a/b"));
 
-        Mockito.when(ctx.getFeature()).thenReturn(feature);
+        when(ctx.getFeature()).thenReturn(feature);
+
+        CheckRepoInitConflicts task = new CheckRepoInitConflicts();
+        task.execute(ctx);
+
+        verify(ctx).getFeature();
+        verify(ctx).reportWarning(contains("conflicting repoinit"));
+        verify(ctx).reportWarning(contains("Conflicting statement"));
+    }
+
+    @Test
+    void shouldReportWarningWhenConflictExistsInTheFirstPrimaryType() {
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
+
+        Feature feature = featureWithExtension(textExtension(
+                "create path (sling:Folder) /content/dam/a\n" + "create path 
(sling:OrderedFolder) /content/dam/a"));
+
+        when(ctx.getFeature()).thenReturn(feature);
 
         CheckRepoInitConflicts task = new CheckRepoInitConflicts();
         task.execute(ctx);
 
-        Mockito.verify(ctx).getFeature();
-        Mockito.verify(ctx).reportWarning(Mockito.contains("conflicting 
repoinit"));
-        Mockito.verify(ctx).reportWarning(Mockito.contains("Conflicting 
statement"));
+        verify(ctx).getFeature();
+        verify(ctx).reportWarning(contains("conflicting repoinit"));
+        verify(ctx).reportWarning(contains("Conflicting statement"));
     }
 
     @Test
     void shouldIgnoreInvalidRepoinitSyntax() {
-        final AnalyserTaskContext ctx = 
Mockito.mock(AnalyserTaskContext.class);
+        final AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
 
         Feature feature = featureWithExtension(textExtension("invalid $$$"));
 
-        Mockito.when(ctx.getFeature()).thenReturn(feature);
+        when(ctx.getFeature()).thenReturn(feature);
 
         CheckRepoInitConflicts task = new CheckRepoInitConflicts();
         task.execute(ctx);
 
-        Mockito.verify(ctx).getFeature();
-        Mockito.verifyNoMoreInteractions(ctx);
+        verify(ctx).getFeature();
+        verifyNoMoreInteractions(ctx);
     }
 
     private Extension textExtension(String text) {
-        Extension extension = Mockito.mock(Extension.class);
-        Mockito.when(extension.getType()).thenReturn(ExtensionType.TEXT);
-        Mockito.when(extension.getText()).thenReturn(text);
+        Extension extension = mock(Extension.class);
+        when(extension.getType()).thenReturn(ExtensionType.TEXT);
+        when(extension.getText()).thenReturn(text);
         return extension;
     }
 
     private Feature featureWithExtension(Extension extension) {
-        Feature feature = Mockito.mock(Feature.class);
-        org.apache.sling.feature.Extensions extensions = 
Mockito.mock(org.apache.sling.feature.Extensions.class);
+        Feature feature = mock(Feature.class);
+        org.apache.sling.feature.Extensions extensions = 
mock(org.apache.sling.feature.Extensions.class);
 
-        Mockito.when(feature.getExtensions()).thenReturn(extensions);
-        Mockito.when(extensions.getByName("repoinit")).thenReturn(extension);
+        when(feature.getExtensions()).thenReturn(extensions);
+        when(extensions.getByName("repoinit")).thenReturn(extension);
 
         return feature;
     }

Reply via email to