diff --git a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java
index 15e7449670..d374a9cc1d 100644
--- a/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java
+++ b/src/main/java/org/codehaus/mojo/versions/AbstractVersionsUpdaterMojo.java
@@ -345,32 +345,10 @@ public void execute()
protected ArtifactVersion findLatestVersion( Artifact artifact, VersionRange versionRange,
Boolean allowingSnapshots, boolean usePluginRepositories )
throws ArtifactMetadataRetrievalException, MojoExecutionException
- {
- return findLatestVersion( artifact, versionRange, allowingSnapshots, usePluginRepositories, false );
- }
-
- /**
- * Finds the latest version of the specified artifact that matches the version range.
- *
- * @param artifact The artifact.
- * @param versionRange The version range.
- * @param allowingSnapshots null
for no override, otherwise the local override to apply.
- * @param usePluginRepositories Use plugin repositories
- * @param allowDowngrade whether downgrades should be allowed
- * @return The latest version of the specified artifact that matches the specified version range or
- * null
if no matching version could be found.
- * @throws ArtifactMetadataRetrievalException If the artifact metadata could not be found.
- * @throws MojoExecutionException if something goes wrong.
- * @since 1.0-alpha-1
- */
- protected ArtifactVersion findLatestVersion( Artifact artifact, VersionRange versionRange,
- Boolean allowingSnapshots, boolean usePluginRepositories,
- boolean allowDowngrade )
- throws ArtifactMetadataRetrievalException, MojoExecutionException
{
boolean includeSnapshots = allowingSnapshots != null ? allowingSnapshots : this.allowSnapshots;
final ArtifactVersions artifactVersions = getHelper().lookupArtifactVersions( artifact, usePluginRepositories );
- return artifactVersions.getNewestVersion( versionRange, null, includeSnapshots, allowDowngrade );
+ return artifactVersions.getNewestVersion( versionRange, null, includeSnapshots, false );
}
/**
diff --git a/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java b/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java
index f7e62c01e6..e599fefd77 100644
--- a/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java
+++ b/src/main/java/org/codehaus/mojo/versions/UpdateParentMojo.java
@@ -22,6 +22,11 @@
import javax.inject.Inject;
import javax.xml.stream.XMLStreamException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
@@ -37,7 +42,10 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.repository.RepositorySystem;
+import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.PomHelper;
+import org.codehaus.mojo.versions.api.Segment;
+import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
@@ -95,6 +103,30 @@ public class UpdateParentMojo extends AbstractVersionsUpdaterMojo
defaultValue = "false" )
protected boolean allowDowngrade;
+ /**
+ * Whether to allow the major version number to be changed.
+ *
+ * @since 1.2
+ */
+ @Parameter( property = "allowMajorUpdates", defaultValue = "true" )
+ protected boolean allowMajorUpdates = true;
+
+ /**
+ * Whether to allow the minor version number to be changed.
+ *
+ * @since 1.2
+ */
+ @Parameter( property = "allowMinorUpdates", defaultValue = "true" )
+ protected boolean allowMinorUpdates = true;
+
+ /**
+ * Whether to allow the incremental version number to be changed.
+ *
+ * @since 1.2
+ */
+ @Parameter( property = "allowIncrementalUpdates", defaultValue = "true" )
+ protected boolean allowIncrementalUpdates = true;
+
// -------------------------- OTHER METHODS --------------------------
@Inject
@@ -135,10 +167,13 @@ protected void update( ModifiedPomXMLEventReader pom )
throw new MojoExecutionException( "skipResolution is only valid if parentVersion is set" );
}
- String initialVersion = parentVersion == null ? getProject().getParent().getVersion() : parentVersion;
+ String initialVersion = parentVersion == null
+ ? getProject().getParent().getVersion()
+ : parentVersion;
try
{
- ArtifactVersion artifactVersion = skipResolution ? new DefaultArtifactVersion( parentVersion )
+ ArtifactVersion artifactVersion = skipResolution
+ ? new DefaultArtifactVersion( parentVersion )
: resolveTargetVersion( initialVersion );
if ( artifactVersion != null )
{
@@ -166,10 +201,15 @@ protected void update( ModifiedPomXMLEventReader pom )
{
throw new MojoExecutionException( e.getMessage(), e );
}
+ catch ( InvalidSegmentException e )
+ {
+ throw new MojoExecutionException( "Invalid segment specification for version " + initialVersion, e );
+ }
}
- private ArtifactVersion resolveTargetVersion( String initialVersion )
- throws MojoExecutionException, ArtifactMetadataRetrievalException, InvalidVersionSpecificationException
+ protected ArtifactVersion resolveTargetVersion( String initialVersion )
+ throws MojoExecutionException, ArtifactMetadataRetrievalException, InvalidVersionSpecificationException,
+ InvalidSegmentException
{
Artifact artifact = getHelper().createDependencyArtifact( DependencyBuilder
.newBuilder()
@@ -186,14 +226,37 @@ private ArtifactVersion resolveTargetVersion( String initialVersion )
VersionRange.createFromVersionSpec( "[" + targetVersionRange.getRecommendedVersion() + ",)" ) );
}
- ArtifactVersion artifactVersion = findLatestVersion( artifact, targetVersionRange, null,
- false, allowDowngrade );
- if ( !shouldApplyUpdate( artifact, getProject().getParent().getVersion(), artifactVersion, forceUpdate ) )
+ final ArtifactVersions versions = getHelper().lookupArtifactVersions( artifact, false );
+ Optional unchangedSegment = determineUnchangedSegment( allowMajorUpdates, allowMinorUpdates,
+ allowIncrementalUpdates );
+
+ // currentVersion (set to parentVersion here) is not included in the version range for searching upgrades
+ // unless we set allowDowngrade to true
+ for ( ArtifactVersion candidate : reverse( versions.getNewerVersions( initialVersion, unchangedSegment,
+ allowSnapshots, !isBlank( parentVersion ) || allowDowngrade ) ) )
{
- getLog().debug( "Update not applied. Exiting." );
- return null;
+ if ( allowDowngrade
+ || targetVersionRange == null
+ || ArtifactVersions.isVersionInRange( candidate, targetVersionRange ) )
+ {
+ if ( shouldApplyUpdate( artifact, getProject().getParent().getVersion(), candidate, forceUpdate ) )
+ {
+ return candidate;
+ }
+ else
+ {
+ getLog().debug( "Update not applied. Exiting." );
+ return null;
+ }
+ }
}
- return artifactVersion;
+
+ getLog().info( "No versions found" );
+ return null;
}
+ private static Iterable reverse( T[] array )
+ {
+ return Arrays.stream( array ).sorted( Collections.reverseOrder() ).collect( Collectors.toList() );
+ }
}
diff --git a/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java b/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java
index 2eac6fe7db..747a448e47 100644
--- a/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java
+++ b/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java
@@ -177,20 +177,19 @@ public final ArtifactVersion getNewestVersion( VersionRange versionRange, Restri
// so we only need to find the first candidate fulfilling the criteria
for ( ArtifactVersion candidate : reverse( getVersions( includeSnapshots ) ) )
{
- if ( !allowDowngrade && versionRange != null
- && !ArtifactVersions.isVersionInRange( candidate, versionRange ) )
+ if ( allowDowngrade || versionRange == null
+ || ArtifactVersions.isVersionInRange( candidate, versionRange ) )
{
- continue;
- }
- if ( restriction != null && !isVersionInRestriction( restriction, candidate ) )
- {
- continue;
- }
- if ( !includeSnapshots && ArtifactUtils.isSnapshot( candidate.toString() ) )
- {
- continue;
+ if ( restriction != null && !isVersionInRestriction( restriction, candidate ) )
+ {
+ continue;
+ }
+ if ( !includeSnapshots && ArtifactUtils.isSnapshot( candidate.toString() ) )
+ {
+ continue;
+ }
+ return candidate;
}
- return candidate;
}
return null;
}
diff --git a/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java b/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java
index bb39a26728..6d945334de 100644
--- a/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java
+++ b/src/test/java/org/codehaus/mojo/versions/UpdateParentMojoTest.java
@@ -10,6 +10,7 @@
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Dependency;
@@ -20,6 +21,7 @@
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.mojo.versions.api.PomHelper;
import org.codehaus.mojo.versions.change.VersionChange;
+import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.utils.TestChangeRecorder;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -34,6 +36,7 @@
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
@@ -60,6 +63,8 @@ public static void setUpStatic()
{{
put( "parent-artifact", new String[] { "0.9.0", "1.0.0", "1.0.1-SNAPSHOT" } );
put( "issue-670-artifact", new String[] { "0.0.1-1", "0.0.1-1-impl-SNAPSHOT" } );
+ put( "dummy-parent2", new String[] { "1.0", "2.0", "3.0", "3.0-alpha-1", "3.0-beta-1" } );
+ put( "test-incremental", new String[] { "1.0.0", "1.1.0", "1.1.1", "2.0.0" } );
put( "unknown-artifact", new String[0] );
}} );
}
@@ -174,69 +179,46 @@ public void testParentDowngradeForbidden()
@Test
public void testParentDowngradeAllowedWithRange()
- throws MojoExecutionException, XMLStreamException, MojoFailureException
+ throws MojoExecutionException, ArtifactMetadataRetrievalException,
+ InvalidVersionSpecificationException, InvalidSegmentException
{
mojo.allowDowngrade = true;
mojo.getProject().setParent( new MavenProject()
{{
setGroupId( "default-group" );
setArtifactId( "parent-artifact" );
- setVersion( "[1.0.1-SNAPSHOT,)" );
}} );
- try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
- {
- pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) )
- .thenReturn( true );
- mojo.update( null );
- }
- assertThat( changeRecorder.getChanges(),
- hasItem( new VersionChange( "default-group", "parent-artifact", "[1.0.1-SNAPSHOT,)",
- "1.0.0" ) ) );
+ ArtifactVersion newVersion = mojo.resolveTargetVersion( "[1.0.1-SNAPSHOT,)" );
+ assertThat( newVersion, notNullValue() );
+ assertThat( newVersion.toString(), is( "1.0.0" ) );
}
@Test
public void testParentDowngradeForbiddenWithRange()
- throws MojoExecutionException, XMLStreamException, MojoFailureException
+ throws MojoExecutionException, ArtifactMetadataRetrievalException,
+ InvalidVersionSpecificationException, InvalidSegmentException
{
mojo.allowDowngrade = false;
- mojo.getProject().setParent( new MavenProject()
- {{
- setGroupId( "default-group" );
- setArtifactId( "parent-artifact" );
- setVersion( "[1.0.1-SNAPSHOT,)" );
- }} );
-
- try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
- {
- pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) )
- .thenReturn( true );
- mojo.update( null );
- }
- assertThat( changeRecorder.getChanges(), is( empty() ) );
+ ArtifactVersion newVersion = mojo.resolveTargetVersion( "[1.0.1-SNAPSHOT,)" );
+ assertThat( newVersion, nullValue() );
}
@Test
public void testAllowSnapshots()
- throws MojoExecutionException, XMLStreamException, MojoFailureException
+ throws MojoExecutionException, ArtifactMetadataRetrievalException,
+ InvalidVersionSpecificationException, InvalidSegmentException
{
mojo.allowSnapshots = true;
mojo.getProject().setParent( new MavenProject()
{{
setGroupId( "default-group" );
setArtifactId( "issue-670-artifact" );
- setVersion( "0.0.1-1" );
}} );
- try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
- {
- pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) )
- .thenReturn( true );
- mojo.update( null );
- }
- assertThat( changeRecorder.getChanges(), hasItem( new VersionChange( "default-group",
- "issue-670-artifact", "0.0.1-1",
- "0.0.1-1-impl-SNAPSHOT" ) ) );
+ ArtifactVersion newVersion = mojo.resolveTargetVersion( "0.0.1-1" );
+ assertThat( newVersion, notNullValue() );
+ assertThat( newVersion.toString(), is( "0.0.1-1-impl-SNAPSHOT" ) );
}
@Test
@@ -265,21 +247,16 @@ public void testAllowSnapshotsWithParentVersion()
@Test
public void testIgnoredVersions()
- throws MojoExecutionException, XMLStreamException, MojoFailureException, IllegalAccessException
+ throws MojoExecutionException, IllegalAccessException,
+ ArtifactMetadataRetrievalException, InvalidVersionSpecificationException, InvalidSegmentException
{
mojo.getProject().setParent( new MavenProject()
{{
setGroupId( "default-group" );
setArtifactId( "parent-artifact" );
- setVersion( "0.9.0" );
}} );
setVariableValueToObject( mojo, "ignoredVersions", singleton( "1.0.0" ) );
- try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
- {
- pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) ).thenReturn( true );
- mojo.update( null );
- }
- assertThat( changeRecorder.getChanges(), is( empty() ) );
+ assertThat( mojo.resolveTargetVersion( "0.9.0" ), nullValue() );
}
@Test
@@ -346,4 +323,85 @@ public void testShouldUpgradeToSnapshot() throws MojoExecutionException, XMLStre
hasItem( new VersionChange( "default-group", "parent-artifact", "0.9.0",
"1.0.1-SNAPSHOT" ) ) );
}
+
+ @Test
+ public void testAllowMinorUpdates()
+ throws MojoExecutionException, ArtifactMetadataRetrievalException,
+ InvalidVersionSpecificationException, InvalidSegmentException
+ {
+ mojo.getProject().setParent( new MavenProject()
+ {{
+ setGroupId( "default-group" );
+ setArtifactId( "parent-artifact" );
+ setVersion( "0.8.0" );
+ }} );
+ mojo.allowMajorUpdates = false;
+ mojo.allowMinorUpdates = true;
+ mojo.allowIncrementalUpdates = false;
+
+ ArtifactVersion newVersion = mojo.resolveTargetVersion( "0.8.0" );
+
+ assertThat( newVersion, notNullValue() );
+ assertThat( newVersion.toString(), is( "0.9.0" ) );
+ }
+
+ @Test
+ public void testAllowIncrementalUpdates()
+ throws MojoExecutionException, ArtifactMetadataRetrievalException,
+ InvalidVersionSpecificationException, InvalidSegmentException
+ {
+ mojo.getProject().setParent( new MavenProject()
+ {{
+ setGroupId( "default-group" );
+ setArtifactId( "test-incremental" );
+ }} );
+ mojo.allowMajorUpdates = false;
+ mojo.allowMinorUpdates = false;
+ mojo.allowIncrementalUpdates = true;
+
+ ArtifactVersion newVersion = mojo.resolveTargetVersion( "1.1.0" );
+
+ assertThat( newVersion, notNullValue() );
+ assertThat( newVersion.toString(), is( "1.1.1" ) );
+ }
+
+ @Test
+ public void testParentVersionRange() throws MojoExecutionException, XMLStreamException, MojoFailureException
+ {
+ mojo.getProject().setParent( new MavenProject()
+ {{
+ setGroupId( "default-group" );
+ setArtifactId( "dummy-parent2" );
+ setVersion( "1.0" );
+ }} );
+ mojo.allowSnapshots = true;
+ mojo.parentVersion = "[,3.0-!)";
+ try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
+ {
+ pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) ).thenReturn( true );
+ mojo.update( null );
+ }
+ assertThat( changeRecorder.getChanges(),
+ hasItem( new VersionChange( "default-group", "dummy-parent2", "1.0",
+ "2.0" ) ) );
+ }
+
+ @Test
+ public void testParentVersionRange2() throws MojoExecutionException, XMLStreamException, MojoFailureException
+ {
+ mojo.getProject().setParent( new MavenProject()
+ {{
+ setGroupId( "default-group" );
+ setArtifactId( "test-parent2" );
+ setVersion( "2.0" );
+ }} );
+ mojo.allowSnapshots = true;
+ mojo.parentVersion = "[,3.0-!)";
+ try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) )
+ {
+ pomHelper.when( () -> PomHelper.setProjectParentVersion( any(), any() ) ).thenReturn( true );
+ mojo.update( null );
+ }
+ assertThat( changeRecorder.getChanges(), empty() );
+ }
}