diff --git a/src/it/it-set-018-issue-82/invoker.properties b/src/it/it-set-018-issue-82/invoker.properties
index 2760b545a2..500af68ea4 100644
--- a/src/it/it-set-018-issue-82/invoker.properties
+++ b/src/it/it-set-018-issue-82/invoker.properties
@@ -1,3 +1,3 @@
-invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:set -fmodule-a1 -DnewVersion=2.5.0-SNAPSHOT
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:set -fmodule-a1 -DnewVersion=2.5.0-SNAPSHOT -DprocessFromLocalAggregationRoot=false
invoker.nonRecursive=true
invoker.buildResult=success
diff --git a/src/it/it-set-019-issue-426/invoker.properties b/src/it/it-set-019-issue-426/invoker.properties
new file mode 100644
index 0000000000..2760b545a2
--- /dev/null
+++ b/src/it/it-set-019-issue-426/invoker.properties
@@ -0,0 +1,3 @@
+invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:set -fmodule-a1 -DnewVersion=2.5.0-SNAPSHOT
+invoker.nonRecursive=true
+invoker.buildResult=success
diff --git a/src/it/it-set-019-issue-426/module-a1/module-b1/pom.xml b/src/it/it-set-019-issue-426/module-a1/module-b1/pom.xml
new file mode 100644
index 0000000000..8cbd8af820
--- /dev/null
+++ b/src/it/it-set-019-issue-426/module-a1/module-b1/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+ localdomain.localhost
+ module-a1
+ 2.0.7-SNAPSHOT
+
+ module-b1
+ pom
+
diff --git a/src/it/it-set-019-issue-426/module-a1/module-b2/pom.xml b/src/it/it-set-019-issue-426/module-a1/module-b2/pom.xml
new file mode 100644
index 0000000000..1b31645f98
--- /dev/null
+++ b/src/it/it-set-019-issue-426/module-a1/module-b2/pom.xml
@@ -0,0 +1,13 @@
+
+
+ 4.0.0
+
+ localdomain.localhost
+ module-a1
+ 2.0.7-SNAPSHOT
+
+ module-b2
+ 2.0.7-SNAPSHOT
+ pom
+
diff --git a/src/it/it-set-019-issue-426/module-a1/module-b3/pom.xml b/src/it/it-set-019-issue-426/module-a1/module-b3/pom.xml
new file mode 100644
index 0000000000..76501f10e5
--- /dev/null
+++ b/src/it/it-set-019-issue-426/module-a1/module-b3/pom.xml
@@ -0,0 +1,13 @@
+
+
+ 4.0.0
+
+ localdomain.localhost
+ module-a1
+ 2.0.7-SNAPSHOT
+
+ module-b3
+ 2.0.7-SNAPSHOT
+ pom
+
diff --git a/src/it/it-set-019-issue-426/module-a1/pom.xml b/src/it/it-set-019-issue-426/module-a1/pom.xml
new file mode 100644
index 0000000000..784519ec8d
--- /dev/null
+++ b/src/it/it-set-019-issue-426/module-a1/pom.xml
@@ -0,0 +1,13 @@
+
+
+ 4.0.0
+ localdomain.localhost
+ module-a1
+ pom
+ 2.0.7-SNAPSHOT
+
+ module-b1
+ module-b2
+ module-b3
+
+
diff --git a/src/it/it-set-019-issue-426/module-a2/pom.xml b/src/it/it-set-019-issue-426/module-a2/pom.xml
new file mode 100644
index 0000000000..cabca3391e
--- /dev/null
+++ b/src/it/it-set-019-issue-426/module-a2/pom.xml
@@ -0,0 +1,17 @@
+
+
+ 4.0.0
+ localdomain.localhost
+ module-a2
+ pom
+ 1.0.3-SNAPSHOT
+
+
+
+ localdomain.localhost
+ module-b1
+ 2.0.7-SNAPSHOT
+
+
+
+
diff --git a/src/it/it-set-019-issue-426/pom.xml b/src/it/it-set-019-issue-426/pom.xml
new file mode 100644
index 0000000000..c8a4012349
--- /dev/null
+++ b/src/it/it-set-019-issue-426/pom.xml
@@ -0,0 +1,103 @@
+
+
+
+ 4.0.0
+ localdomain.localhost
+ project-a
+ pom
+ 1.2.0-SNAPSHOT
+ mversions-82
+
+
+ invoking versions:set on child pom - make sure all child poms are affected
+
+
+
+ module-a1
+ module-a2
+
+
+
+
+
+
+ maven-antrun-plugin
+ 1.1
+
+
+ maven-assembly-plugin
+ 2.2-beta-2
+
+
+ maven-clean-plugin
+ 2.2
+
+
+ maven-compiler-plugin
+ 2.0.2
+
+
+ maven-dependency-plugin
+ 2.0
+
+
+ maven-deploy-plugin
+ 2.3
+
+
+ maven-ear-plugin
+ 2.3.1
+
+
+ maven-ejb-plugin
+ 2.1
+
+
+ maven-install-plugin
+ 2.2
+
+
+ maven-jar-plugin
+ 2.2
+
+
+ maven-javadoc-plugin
+ 2.4
+
+
+ maven-plugin-plugin
+ 2.4.1
+
+
+ maven-rar-plugin
+ 2.2
+
+
+ maven-release-plugin
+ 2.0-beta-7
+
+
+ maven-resources-plugin
+ 2.2
+
+
+ maven-site-plugin
+ 2.0
+
+
+ maven-source-plugin
+ 2.0.4
+
+
+ maven-surefire-plugin
+ 2.4.2
+
+
+ maven-war-plugin
+ 2.1-alpha-1
+
+
+
+
+
+
diff --git a/src/it/it-set-019-issue-426/verify.groovy b/src/it/it-set-019-issue-426/verify.groovy
new file mode 100644
index 0000000000..b91b89bc96
--- /dev/null
+++ b/src/it/it-set-019-issue-426/verify.groovy
@@ -0,0 +1,67 @@
+import org.apache.commons.lang.StringUtils
+
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.xpath.XPathFactory
+
+class Checker
+{
+ def result = true;
+
+ def basedir;
+
+ public Checker(File basedir) {
+ this.basedir = basedir;
+ }
+
+ def readXPath( String pom, String xPathExpression )
+ {
+ def stream = new FileInputStream( new File( basedir, pom ) );
+ try
+ {
+ return XPathFactory.newInstance()
+ .newXPath()
+ .evaluate( xPathExpression, DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder()
+ .parse( stream ).documentElement );
+ }
+ finally
+ {
+ stream.close();
+ }
+ }
+
+ Checker check( String message, String pom, String xpath, String expected )
+ {
+ if ( result )
+ {
+ try
+ {
+ def actual = readXPath( pom, xpath )
+ if ( !StringUtils.equals( expected, actual ) )
+ {
+ System.out.println( pom + " [xpath:" + xpath + "] expected '" + expected + "' found '" + actual + "' : " + message );
+ result = false;
+ }
+ }
+ catch ( Throwable t )
+ {
+ t.printStackTrace();
+ result = false;
+ }
+ }
+ return this;
+ }
+}
+
+return new Checker(basedir)
+ .check( "root pom unchanged", "pom.xml", "/project/version", "1.2.0-SNAPSHOT" )
+ .check( "module-a1 changed", "module-a1/pom.xml", "/project/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a1/module-b1 parent changed", "module-a1/module-b1/pom.xml", "/project/parent/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a1/module-b1 remains unspecified", "module-a1/module-b1/pom.xml", "/project/version", "" )
+ .check( "module-a1/module-b2 parent changed", "module-a1/module-b2/pom.xml", "/project/parent/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a1/module-b2 version changed", "module-a1/module-b2/pom.xml", "/project/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a1/module-b3 parent changed", "module-a1/module-b3/pom.xml", "/project/parent/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a1/module-b3 version changed", "module-a1/module-b3/pom.xml", "/project/version", "2.5.0-SNAPSHOT" )
+ .check( "module-a2 unchanged", "module-a2/pom.xml", "/project/version", "1.0.3-SNAPSHOT" )
+ .check( "module-a2 dependency changed", "module-a2/pom.xml", "/project/dependencies/dependency/version", "2.5.0-SNAPSHOT" )
+ .result;
diff --git a/src/main/java/org/codehaus/mojo/versions/SetMojo.java b/src/main/java/org/codehaus/mojo/versions/SetMojo.java
index 3f823b428b..72b52799a6 100644
--- a/src/main/java/org/codehaus/mojo/versions/SetMojo.java
+++ b/src/main/java/org/codehaus/mojo/versions/SetMojo.java
@@ -192,6 +192,16 @@ public class SetMojo
@Parameter( property = "processAllModules", defaultValue = "false" )
private boolean processAllModules;
+ /**
+ * Whether to start processing at the local aggregation root (which might be a parent module
+ * of that module where Maven is executed in, and the version change may affect parent and sibling modules).
+ * Setting to fale makes sure only the module (and it's submodule) where Maven is executed for is affected.
+ *
+ * @since 2.9
+ */
+ @Parameter( property = "processFromLocalAggregationRoot", defaultValue = "true" )
+ private boolean processFromLocalAggregationRoot;
+
/**
* The changes to module coordinates. Guarded by this.
*/
@@ -285,7 +295,13 @@ public void execute()
try
{
- final MavenProject project = getProject();
+ final MavenProject project;
+ if ( processFromLocalAggregationRoot ) {
+ project = PomHelper.getLocalRoot( projectBuilder, getProject(), localRepository, null, getLog() );
+ }
+ else {
+ project = getProject();
+ }
getLog().info( "Local aggregation root: " + project.getBasedir() );
Map reactorModels = PomHelper.getReactorModels( project, getLog() );
diff --git a/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java b/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java
index 4c814eba53..4de12acd67 100644
--- a/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java
+++ b/src/main/java/org/codehaus/mojo/versions/api/PomHelper.java
@@ -1355,6 +1355,55 @@ public static String getGroupId( Model model )
return targetGroupId;
}
+ /**
+ * Finds the local root of the specified project.
+ *
+ * @param project The project to find the local root for.
+ * @param localRepository the local repo.
+ * @param globalProfileManager the global profile manager.
+ * @param logger The logger to log to.
+ * @return The local root (note this may be the project passed as an argument).
+ */
+ public static MavenProject getLocalRoot( MavenProjectBuilder builder, MavenProject project,
+ ArtifactRepository localRepository, ProfileManager globalProfileManager,
+ Log logger )
+ {
+ logger.info( "Searching for local aggregator root..." );
+ while ( true )
+ {
+ final File parentDir = project.getBasedir().getParentFile();
+ if ( parentDir != null && parentDir.isDirectory() )
+ {
+ logger.debug( "Checking to see if " + parentDir + " is an aggregator parent" );
+ File parent = new File( parentDir, "pom.xml" );
+ if ( parent.isFile() )
+ {
+ try
+ {
+ final MavenProject parentProject =
+ builder.build( parent, localRepository, globalProfileManager );
+ if ( getAllChildModules( parentProject, logger ).contains( project.getBasedir().getName() ) )
+ {
+ logger.debug( parentDir + " is an aggregator parent" );
+ project = parentProject;
+ continue;
+ }
+ else
+ {
+ logger.debug( parentDir + " is not an aggregator parent" );
+ }
+ }
+ catch ( ProjectBuildingException e )
+ {
+ logger.warn( e );
+ }
+ }
+ }
+ logger.debug( "Local aggregation root is " + project.getBasedir() );
+ return project;
+ }
+ }
+
/**
* Builds a map of raw models keyed by module path.
*