Repository: vackosar/gitflow-incremental-builder (java)

Issue:
GIB should handle -N similar to -pl (and -f)
`mvn -N` will cause GIB to apply `*ForUpstreamModules` but instead it would be more consistent to behave like this: https://github.com/vackosar/gitflow-incremental-builder#explicitly-selected-projects

Pull request description:
Issue #172: handle -N similar to -pl/-f
Resolves #172 

Patch:
diff --git a/README.md b/README.md
index 039091d..58bf30a 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@ This extension is **not limited to Git Flow setups!** The [extensive configurati
 - [Explicitly selected projects](#explicitly-selected-projects)
   - [mvn -pl](#mvn--pl)
   - [mvn -f and others](#mvn--f-and-others)
+  - [mvn -N](#mvn--N)
 
 - [Authentication](#authentication)
   - [HTTP](#http)
@@ -546,7 +547,13 @@ A "leaf module" is a module without submodules.
 
 The same applies if the current directory is changed from the root directory of the multi-module-project to the leaf module subdirectory via `cd`.
 
-In contrast, a module _with_ submodules that is selected via `-f` or via `cd` is subject to the regular change detection rules (unless [`-pl`](#mvn--pl) is added).
+In contrast, a module _with_ submodules that is selected via `-f` or via `cd` is subject to the regular change detection rules (unless [`-pl`](#mvn--pl) or [`-N`](#mvn--N) is added).
+
+### mvn -N
+
+Since 3.10.2, GIB will _always_ build a "node module" when non-recursive build is activated via `mvn -N` (or `--non-recursive`), **regardless of being changed or not!**
+
+A "node module" is a module _with_ submodules.
 
 ## Authentication
 
diff --git a/pom.xml b/pom.xml
index 20d4fd2..ddef5a0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,7 +66,7 @@
         <version.junit>4.13</version.junit>
         <version.powermock-reflect>2.0.7</version.powermock-reflect>
         <version.mockito>3.3.3</version.mockito>
-        <version.jetty>9.4.29.v20200521</version.jetty>
+        <version.jetty>9.4.28.v20200408</version.jetty>
 
         <!-- Plugin versions -->
         <version.maven-enforcer-plugin>3.0.0-M3</version.maven-enforcer-plugin>
diff --git a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
index 96ff161..22472da 100644
--- a/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
+++ b/src/main/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemover.java
@@ -52,9 +52,11 @@ class UnchangedProjectsRemover {
                     mavenSession.getProjects().stream().map(MavenProject::getArtifactId).collect(Collectors.joining(", ")));
             return;
         }
-        // do nothing if only one "leaf" project/module is present (cases: mvn -f ... or cd ... or unusual case of non-multi-module project)
+        // do nothing if:
+        // - building non-recursively (-N)
+        // - or only one "leaf" project/module is present (cases: mvn -f ... or cd ... or unusual case of non-multi-module project)
         // the assumption here (similar to the -pl approach above): the user has decided to build a single module, so don't mess with that
-        if (onlySingleLeafModulePresent()) {
+        if (!mavenSession.getRequest().isRecursive() || onlySingleLeafModulePresent()) {
             printDelimiter();
             logger.info("Building single project (without any adjustment): {}", mavenSession.getCurrentProject().getArtifactId());
             return;


Test patch:
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
index f4fb45b..a056a05 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/BaseUnchangedProjectsRemoverTest.java
@@ -88,6 +88,7 @@ public abstract class BaseUnchangedProjectsRemoverTest {
         when(mavenSessionMock.getCurrentProject()).thenReturn(moduleA);
         when(mavenSessionMock.getTopLevelProject()).thenReturn(moduleA);
 
+        when(mavenExecutionRequestMock.isRecursive()).thenReturn(true);
         when(mavenSessionMock.getRequest()).thenReturn(mavenExecutionRequestMock);
         when(mavenSessionMock.getProjects()).thenReturn(projects);
         when(mavenSessionMock.getProjectDependencyGraph()).thenReturn(projectDependencyGraphMock);
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenIntegrationTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenIntegrationTest.java
index 7703186..442e533 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenIntegrationTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/MavenIntegrationTest.java
@@ -102,9 +102,9 @@ public class MavenIntegrationTest extends BaseRepoTest {
     }
 
     @Test
-    public void logChanges() throws Exception {
-        final String output = executeBuild("-X", "-N");
-        Assert.assertTrue(output.contains("[WARNING] Ignoring changed file in non-reactor module: "));
+    public void nonRecursive() throws Exception {
+        final String output = executeBuild("-N");
+        Assert.assertTrue(output.contains("Building single project (without any adjustment): parent"));
     }
 
     @Test
diff --git a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemoverTest.java b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemoverTest.java
index 9f6d681..7bc8d2b 100644
--- a/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemoverTest.java
+++ b/src/test/java/com/vackosar/gitflowincrementalbuild/boundary/UnchangedProjectsRemoverTest.java
@@ -23,7 +23,7 @@ import com.vackosar.gitflowincrementalbuild.control.Property;
 
 /**
  * Tests {@link UnchangedProjectsRemover} with Mockito mocks.
- * 
+ *
  * @author famod
  */
 public class UnchangedProjectsRemoverTest extends BaseUnchangedProjectsRemoverTest {
@@ -61,7 +61,7 @@ public class UnchangedProjectsRemoverTest extends BaseUnchangedProjectsRemoverTe
         assertProjectPropertiesEqual(unchangedModuleMock, ImmutableMap.of("maven.test.skip", "true"));
     }
 
-    // mvn -N ... or mvn -f ... for a multi-module-submodule
+    // mvn -f ... for a multi-module-submodule
     @Test
     public void nothingChanged_singleModule_withSubmodules() throws GitAPIException, IOException {
         // note: a more realistic setup would require a proper parent/root
@@ -77,6 +77,23 @@ public class UnchangedProjectsRemoverTest extends BaseUnchangedProjectsRemoverTe
         assertProjectPropertiesEqual(moduleA, Collections.emptyMap());
     }
 
+    // mvn -N ... for a multi-module-submodule
+    @Test
+    public void nothingChanged_singleModule_withSubmodules_nonRecursive() throws GitAPIException, IOException {
+        // note: a more realistic setup would require a proper parent/root
+        moduleA.getModel().addModule("test");
+        when(mavenExecutionRequestMock.isRecursive()).thenReturn(false);
+
+        underTest.act();
+
+        assertEquals("Unexpected goals", Collections.emptyList(), mavenSessionMock.getGoals());
+
+        verify(mavenSessionMock, never()).setProjects(anyList());
+        verify(moduleA).getModel();   // only once due to test setup
+
+        assertProjectPropertiesEqual(moduleA, Collections.emptyMap());
+    }
+
     // mvn -f module-B (or unusal case of a non-multi-module project)
     @Test
     public void nothingChanged_singleModule_leaf() throws GitAPIException, IOException {