From 90a84aed9971bf197311d9b488e40800fb0702c5 Mon Sep 17 00:00:00 2001 From: Andrzej Jarmoniuk Date: Fri, 4 Nov 2022 16:19:54 +0100 Subject: [PATCH] Resolves #807 - Abstracting a common base for UseLatestVersionsMojo and UseLatestReleasesMojo. - Elaborating on the difference between a "release" and a "version" --- ...AbstractVersionsDependencyUpdaterMojo.java | 1 - .../mojo/versions/UseLatestReleasesMojo.java | 132 ++++++---------- .../mojo/versions/UseLatestVersionsMojo.java | 93 +++-------- .../versions/UseLatestVersionsMojoBase.java | 147 ++++++++++++++++++ .../versions/api/AbstractVersionDetails.java | 26 ++++ .../mojo/versions/api/VersionDetails.java | 17 ++ .../src/site/markdown/index.md | 3 +- .../versions/UseLatestVersionsMojoTest.java | 55 +++++++ 8 files changed, 308 insertions(+), 166 deletions(-) create mode 100644 versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java index 89fa4fc2d..571fbdc01 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDependencyUpdaterMojo.java @@ -507,5 +507,4 @@ private int findFirstChar( final String includeString, final String chars ) } return nextRangeStartDelimiterIndex; } - } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java index d0464d1f4..8c248d122 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestReleasesMojo.java @@ -22,11 +22,9 @@ import javax.inject.Inject; import javax.xml.stream.XMLStreamException; -import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; -import java.util.List; import java.util.Optional; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.maven.artifact.Artifact; @@ -37,7 +35,6 @@ 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.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; @@ -46,8 +43,6 @@ 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; @@ -55,16 +50,20 @@ import org.codehaus.mojo.versions.utils.SegmentUtils; import static java.util.Collections.singletonList; +import static java.util.Optional.empty; /** - * Replaces any release versions with the latest release version. + * Replaces any release versions (i.e. versions that are not snapshots and do not + * have a year-month-day suffix) with the latest release version. This goal + * will not replace versions of dependencies which use snapshots + * or versions with a year-month-day suffix. * * @author Stephen Connolly * @since 1.0-alpha-3 */ @Mojo( name = "use-latest-releases", threadSafe = true ) public class UseLatestReleasesMojo - extends AbstractVersionsDependencyUpdaterMojo + extends UseLatestVersionsMojoBase { // ------------------------------ FIELDS ------------------------------ @@ -80,7 +79,7 @@ public class UseLatestReleasesMojo * @since 1.2 */ @Parameter( property = "allowMajorUpdates", defaultValue = "true" ) - protected boolean allowMajorUpdates; + protected boolean allowMajorUpdates = true; /** *

Whether to allow the minor version number to be changed.

@@ -90,7 +89,7 @@ public class UseLatestReleasesMojo * @since 1.2 */ @Parameter( property = "allowMinorUpdates", defaultValue = "true" ) - protected boolean allowMinorUpdates; + protected boolean allowMinorUpdates = true; /** *

Whether to allow the incremental version number to be changed.

@@ -101,7 +100,7 @@ public class UseLatestReleasesMojo * @since 1.2 */ @Parameter( property = "allowIncrementalUpdates", defaultValue = "true" ) - protected boolean allowIncrementalUpdates; + protected boolean allowIncrementalUpdates = true; // ------------------------------ METHODS -------------------------- @@ -151,94 +150,51 @@ protected void update( ModifiedPomXMLEventReader pom ) } } + @SuppressWarnings( "unchecked" ) private void useLatestReleases( ModifiedPomXMLEventReader pom, Collection dependencies ) - throws XMLStreamException, MojoExecutionException, ArtifactMetadataRetrievalException + throws XMLStreamException, MojoExecutionException, ArtifactMetadataRetrievalException { Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog() ); - for ( Dependency dep : dependencies ) - { - if ( isExcludeReactor() && isProducedByReactor( dep ) ) - { - getLog().info( "Ignoring reactor dependency: " + toString( dep ) ); - continue; - } - - if ( isHandledByProperty( dep ) ) - { - getLog().debug( "Ignoring dependency with property as version: " + toString( dep ) ); - continue; - } - - String version = dep.getVersion(); - Matcher versionMatcher = matchSnapshotRegex.matcher( version ); - if ( !versionMatcher.matches() ) - { - Artifact artifact = this.toArtifact( dep ); - if ( !isIncluded( artifact ) ) - { - continue; - } - - ArtifactVersion selectedVersion = new DefaultArtifactVersion( version ); - getLog().debug( "Selected version: " + selectedVersion ); - - getLog().debug( "Looking for newer versions of " + toString( dep ) ); - ArtifactVersions versions = getHelper().lookupArtifactVersions( artifact, false ); - try + useLatestVersions( pom, dependencies, + ( dep, versions ) -> { - // TODO consider creating a search + filter in the Details services to get latest release. - ArtifactVersion[] newer = versions.getNewerVersions( version, unchangedSegment, false, false ); - ArtifactVersion[] filteredVersions = filterVersionsWithIncludes( newer, artifact ); - if ( filteredVersions.length > 0 ) + try { - String newVersion = filteredVersions[filteredVersions.length - 1].toString(); - if ( getProject().getParent() != null ) - { - if ( artifact.getId().equals( getProject().getParentArtifact().getId() ) - && isProcessingParent() ) - { - if ( PomHelper.setProjectParentVersion( pom, newVersion ) ) - { - getLog().debug( "Made parent update from " + version + " to " + newVersion ); - } - } - } - if ( PomHelper.setDependencyVersion( pom, dep.getGroupId(), dep.getArtifactId(), version, - newVersion, getProject().getModel() ) ) - { - getLog().info( "Updated " + toString( dep ) + " to version " + newVersion ); - - this.getChangeRecorder().recordUpdate( "useLatestReleases", dep.getGroupId(), - dep.getArtifactId(), version, newVersion ); - } + return getLastFiltered( versions.getNewerVersions( dep.getVersion(), unchangedSegment, + false, false ), dep ); } - } - catch ( InvalidSegmentException e ) - { - getLog().warn( String.format( "Skipping the processing of %s:%s:%s due to: %s", dep.getGroupId(), - dep.getArtifactId(), dep.getVersion(), e.getMessage() ) ); - } - } - } + catch ( InvalidSegmentException e ) + { + getLog().warn( String.format( "Skipping the processing of %s:%s:%s due to: %s", + dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), e.getMessage() ) ); + } + return empty(); + }, "useLatestReleases", + dep -> !matchSnapshotRegex.matcher( dep.getVersion() ).matches() ); } - private ArtifactVersion[] filterVersionsWithIncludes( ArtifactVersion[] newer, Artifact artifact ) + /** + * Returns the last element of the given {@link ArtifactVersion} array such as every version of the array + * is included in the {@code includes} and excluded by the {@code excludes} filters + * + * @param newer array of {@link ArtifactVersion} with newer versions + * @param dependency dependency prototype to create the artifacts from + * @return the newest version fulfilling the criteria + */ + private Optional getLastFiltered( ArtifactVersion[] newer, Dependency dependency ) { - List filteredNewer = new ArrayList<>( newer.length ); - for ( ArtifactVersion artifactVersion : newer ) - { - Artifact artefactWithNewVersion = - new DefaultArtifact( artifact.getGroupId(), artifact.getArtifactId(), - VersionRange.createFromVersion( artifactVersion.toString() ), artifact.getScope(), - artifact.getType(), null, new DefaultArtifactHandler(), false ); - if ( isIncluded( artefactWithNewVersion ) ) - { - filteredNewer.add( artifactVersion ); - } - } - return filteredNewer.toArray( new ArtifactVersion[0] ); + return Arrays.stream( newer ) + .filter( version -> + { + Artifact artefactWithNewVersion = + new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), + VersionRange.createFromVersion( version.toString() ), dependency.getScope(), + dependency.getType(), null, new DefaultArtifactHandler(), false ); + return isIncluded( artefactWithNewVersion ); + } ) + .reduce( ( v1, v2 ) -> v2 ); } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java index 8b9b23430..f5009dc2e 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojo.java @@ -26,13 +26,10 @@ import java.util.Collection; import java.util.Optional; -import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.manager.WagonManager; 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.DefaultArtifactVersion; import org.apache.maven.model.Dependency; import org.apache.maven.model.DependencyManagement; import org.apache.maven.plugin.MojoExecutionException; @@ -41,7 +38,6 @@ 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; @@ -50,16 +46,17 @@ import org.codehaus.mojo.versions.utils.SegmentUtils; import static java.util.Collections.singletonList; +import static java.util.Optional.empty; /** - * Replaces any version with the latest version. + * Replaces any version with the latest version found in the artifactory. * * @author Stephen Connolly * @since 1.0-alpha-3 */ @Mojo( name = "use-latest-versions", threadSafe = true ) public class UseLatestVersionsMojo - extends AbstractVersionsDependencyUpdaterMojo + extends UseLatestVersionsMojoBase { /** * Whether to allow the major version number to be changed. @@ -67,7 +64,7 @@ public class UseLatestVersionsMojo * @since 1.2 */ @Parameter( property = "allowMajorUpdates", defaultValue = "true" ) - private boolean allowMajorUpdates; + private boolean allowMajorUpdates = true; /** * Whether to allow the minor version number to be changed. @@ -76,7 +73,7 @@ public class UseLatestVersionsMojo * @since 1.2 */ @Parameter( property = "allowMinorUpdates", defaultValue = "true" ) - private boolean allowMinorUpdates; + private boolean allowMinorUpdates = true; /** * Whether to allow the incremental version number to be changed. @@ -86,7 +83,7 @@ public class UseLatestVersionsMojo * @since 1.2 */ @Parameter( property = "allowIncrementalUpdates", defaultValue = "true" ) - private boolean allowIncrementalUpdates; + private boolean allowIncrementalUpdates = true; /** *

Whether to downgrade a snapshot dependency if allowSnapshots is false @@ -162,81 +159,27 @@ protected void update( ModifiedPomXMLEventReader pom ) } } + @SuppressWarnings( "unchecked" ) private void useLatestVersions( ModifiedPomXMLEventReader pom, Collection dependencies ) - throws XMLStreamException, MojoExecutionException, ArtifactMetadataRetrievalException + throws XMLStreamException, MojoExecutionException, ArtifactMetadataRetrievalException { Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog() ); - for ( Dependency dep : dependencies ) - { - if ( isExcludeReactor() && isProducedByReactor( dep ) ) - { - getLog().info( "Ignoring reactor dependency: " + toString( dep ) ); - continue; - } - - if ( isHandledByProperty( dep ) ) - { - getLog().debug( "Ignoring dependency with property as version: " + toString( dep ) ); - continue; - } - - String version = dep.getVersion(); - Artifact artifact = this.toArtifact( dep ); - if ( !isIncluded( artifact ) ) - { - continue; - } - - ArtifactVersion selectedVersion = new DefaultArtifactVersion( version ); - getLog().debug( "Selected version:" + selectedVersion ); - - getLog().debug( "Looking for newer versions of " + toString( dep ) ); - ArtifactVersions versions = getHelper().lookupArtifactVersions( artifact, false ); - - try - { - ArtifactVersion[] newerVersions = versions.getNewerVersions( version, unchangedSegment, allowSnapshots, - allowDowngrade ); - - //ArtifactVersion[] filteredVersions = filter( unchangedSegment, selectedVersion, newerVersions ); - ArtifactVersion[] filteredVersions = newerVersions; - if ( filteredVersions.length > 0 ) + useLatestVersions( pom, dependencies, + ( dep, versions ) -> { - String newVersion = filteredVersions[filteredVersions.length - 1].toString(); - if ( getProject().getParent() != null ) + try { - final Artifact parentArtifact = getProject().getParentArtifact(); - if ( artifact.getId().equals( parentArtifact.getId() ) && isProcessingParent() ) - { - if ( PomHelper.setProjectParentVersion( pom, newVersion ) ) - { - getLog().debug( "Made parent update from " + version + " to " + newVersion ); - - this.getChangeRecorder().recordUpdate( "useLatestVersions", parentArtifact.getGroupId(), - parentArtifact.getArtifactId(), version, - newVersion ); - } - } + return versions.getNewestVersion( dep.getVersion(), unchangedSegment, allowSnapshots, + allowDowngrade ); } - if ( PomHelper.setDependencyVersion( pom, dep.getGroupId(), dep.getArtifactId(), version, - newVersion, - getProject().getModel() ) ) + catch ( InvalidSegmentException e ) { - getLog().info( "Updated " + toString( dep ) + " to version " + newVersion ); - - this.getChangeRecorder().recordUpdate( "useLatestVersions", dep.getGroupId(), - dep.getArtifactId(), version, newVersion ); + getLog().warn( String.format( "Skipping the processing of %s:%s:%s due to: %s", + dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), e.getMessage() ) ); } - } - } - catch ( InvalidSegmentException e ) - { - getLog().warn( String.format( "Skipping the processing of %s:%s:%s due to: %s", dep.getGroupId(), - dep.getArtifactId(), dep.getVersion(), e.getMessage() ) ); - } - } + return empty(); + }, "useLatestVersions" ); } - } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java new file mode 100644 index 000000000..05a657a62 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/UseLatestVersionsMojoBase.java @@ -0,0 +1,147 @@ +package org.codehaus.mojo.versions; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import javax.xml.stream.XMLStreamException; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Predicate; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.manager.WagonManager; +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.DefaultArtifactVersion; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.MojoExecutionException; +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.rewriting.ModifiedPomXMLEventReader; + +/** + * Common base class for {@link UseLatestVersionsMojo} + * and {@link UseLatestReleasesMojo} + */ +public abstract class UseLatestVersionsMojoBase + extends AbstractVersionsDependencyUpdaterMojo +{ + public UseLatestVersionsMojoBase( RepositorySystem repositorySystem, + MavenProjectBuilder projectBuilder, + ArtifactMetadataSource artifactMetadataSource, + WagonManager wagonManager, + ArtifactResolver artifactResolver ) + { + super( repositorySystem, projectBuilder, artifactMetadataSource, wagonManager, artifactResolver ); + } + + /** + * Updates the pom, given a set of dependencies, a function retrieving the newest version, + * and an optional array of filters against which the input dependencies are matched. + * + * @param pom POM to be modified + * @param dependencies collection of dependencies with the dependency versions before the change + * @param newestVersionProducer function providing the newest version given a dependency and + * an {@link ArtifactVersions} instance + * @param changeRecorderTitle title for the change recorder records + * @param filters optional array of filters + * @throws XMLStreamException thrown if the POM update doesn't succeed + * @throws ArtifactMetadataRetrievalException thrown if an artifact cannot be retried + */ + @SafeVarargs + protected final void useLatestVersions( ModifiedPomXMLEventReader pom, + Collection dependencies, + BiFunction> + newestVersionProducer, + String changeRecorderTitle, + Predicate... filters ) + throws XMLStreamException, MojoExecutionException, ArtifactMetadataRetrievalException + { + for ( Dependency dep : dependencies ) + { + if ( !Arrays.stream( filters ) + .map( f -> f.test( dep ) ) + .reduce( Boolean::logicalAnd ) + .orElse( true ) ) + { + continue; + } + + if ( isExcludeReactor() && isProducedByReactor( dep ) ) + { + getLog().info( "Ignoring reactor dependency: " + toString( dep ) ); + continue; + } + + if ( isHandledByProperty( dep ) ) + { + getLog().debug( "Ignoring dependency with property as version: " + toString( dep ) ); + continue; + } + + Artifact artifact = toArtifact( dep ); + if ( !isIncluded( artifact ) ) + { + continue; + } + + ArtifactVersion selectedVersion = new DefaultArtifactVersion( dep.getVersion() ); + getLog().debug( "Selected version:" + selectedVersion ); + + getLog().debug( "Looking for newer versions of " + toString( dep ) ); + ArtifactVersions versions = getHelper().lookupArtifactVersions( artifact, false ); + Optional newestVer = newestVersionProducer.apply( dep, versions ); + if ( newestVer.isPresent() ) + { + String verStr = newestVer.get().toString(); + if ( getProject().getParent() != null ) + { + final Artifact parentArtifact = getProject().getParentArtifact(); + if ( artifact.getId().equals( parentArtifact.getId() ) && isProcessingParent() ) + { + if ( PomHelper.setProjectParentVersion( pom, verStr ) ) + { + getLog().debug( "Made parent update from " + dep.getVersion() + " to " + verStr ); + + this.getChangeRecorder().recordUpdate( changeRecorderTitle, parentArtifact.getGroupId(), + parentArtifact.getArtifactId(), dep.getVersion(), + verStr ); + } + } + } + if ( PomHelper.setDependencyVersion( pom, dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), + verStr, + getProject().getModel() ) ) + { + getLog().info( "Updated " + toString( dep ) + " to version " + verStr ); + + this.getChangeRecorder().recordUpdate( changeRecorderTitle, dep.getGroupId(), + dep.getArtifactId(), dep.getVersion(), verStr ); + } + } + } + } +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java index 1d3f9665f..1b1a5a080 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/AbstractVersionDetails.java @@ -255,6 +255,32 @@ public final ArtifactVersion[] getNewerVersions( String versionString, Optional< return getVersions( restriction, includeSnapshots ); } + @Override + public Optional getNewestVersion( String versionString, Optional upperBoundSegment, + boolean includeSnapshots, boolean allowDowngrade ) + throws InvalidSegmentException + { + ArtifactVersion currentVersion = new DefaultArtifactVersion( versionString ); + ArtifactVersion lowerBound = allowDowngrade + ? getLowerBound( currentVersion, upperBoundSegment ) + .map( DefaultArtifactVersion::new ) + .orElse( null ) + : currentVersion; + ArtifactVersion upperBound = + upperBoundSegment + .map( s -> (ArtifactVersion) new BoundArtifactVersion( currentVersion, + s.isMajorTo( SUBINCREMENTAL ) + ? Segment.of( s.value() + 1 ) + : s ) ) + .orElse( null ); + + Restriction restriction = new Restriction( lowerBound, allowDowngrade, upperBound, allowDowngrade ); + return Arrays.stream( getVersions( includeSnapshots ) ) + .filter( candidate -> isVersionInRestriction( restriction, candidate ) ) + .filter( candidate -> includeSnapshots || !ArtifactUtils.isSnapshot( candidate.toString() ) ) + .max( getVersionComparator() ); + } + @Override public final ArtifactVersion[] getVersions( Restriction restriction, boolean includeSnapshots ) { diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java index 265b4fcfa..542130619 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/api/VersionDetails.java @@ -229,6 +229,23 @@ ArtifactVersion getNewestVersion( ArtifactVersion lowerBound, ArtifactVersion up */ ArtifactVersion getNewestVersion( VersionRange versionRange, boolean includeSnapshots ); + /** + * Returns the latest version, newer than the given version, given the upper bound segment and whether snapshots + * should be included. + * + * @param versionString current version + * @param upperBoundSegment the upper bound segment; empty() means no upper bound + * @param includeSnapshots whether snapshot versions should be included + * @param allowDowngrade whether to allow downgrading if the current version is a snapshots and snapshots + * are disallowed + * @return newer version or {@link Optional#empty()} if none can be found + * @throws InvalidSegmentException if the requested segment is outside the bounds (less than 1 or greater than + * the segment count) + */ + Optional getNewestVersion( String versionString, Optional upperBoundSegment, + boolean includeSnapshots, boolean allowDowngrade ) + throws InvalidSegmentException; + /** * Returns the newest version newer than the specified current version, but within the specified update scope or * null if no such version exists. diff --git a/versions-maven-plugin/src/site/markdown/index.md b/versions-maven-plugin/src/site/markdown/index.md index cf780e935..f008eb1a6 100644 --- a/versions-maven-plugin/src/site/markdown/index.md +++ b/versions-maven-plugin/src/site/markdown/index.md @@ -59,8 +59,7 @@ The Versions Plugin has the following goals. released and replaces them with the corresponding release version. * [versions:use-next-releases](./use-next-releases-mojo.html) searches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the next release version. -* [versions:use-latest-releases](./use-latest-releases-mojo.html) searches the pom for all non-SNAPSHOT versions which - have been a newer release and replaces them with the latest release version. +* [versions:use-latest-releases](./use-latest-releases-mojo.html) searches the pom for all dependencies using *release* versions (i.e. not SNAPSHOT and not versions ending with a year-month-day suffix) and replaces them with the latest *release* version. * [versions:use-next-snapshots](./use-next-snapshots-mojo.html) searches the pom for all non-SNAPSHOT versions which have been a newer -SNAPSHOT version and replaces them with the next -SNAPSHOT version. * [versions:use-latest-snapshots](./use-latest-snapshots-mojo.html) searches the pom for all non-SNAPSHOT versions diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java index e5b0ac4e1..ac0a033d9 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/UseLatestVersionsMojoTest.java @@ -31,6 +31,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.not; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; @@ -60,6 +62,7 @@ public void setUp() throws Exception "1.0.0-SNAPSHOT", "0.9.0"} ); put( "poison-artifact", new String[] {"1.1.1.1-SNAPSHOT", "1.1.1.0", "1.1.1.0-SNAPSHOT", "1.0.0.0", "1.0.0.0-SNAPSHOT", "0.9.0.0"} ); + put( "other-artifact", new String[] {"1.0", "2.0"} ); }} ); mojo = new UseLatestVersionsMojo( repositorySystemMock, @@ -263,4 +266,56 @@ public void testIgnoredVersions() } assertThat( changeRecorder.getChanges(), Is.is( empty() ) ); } + + @Test + public void testIncludeFilter() + throws MojoExecutionException, XMLStreamException, MojoFailureException, IllegalAccessException + { + mojo.getProject().getModel().setDependencies( Arrays.asList( + DependencyBuilder.dependencyWith( "default-group", "dependency-artifact", "0.9.0", + "default", "pom", SCOPE_COMPILE ), + DependencyBuilder.dependencyWith( "default-group", "other-artifact", "1.0", + "default", "pom", SCOPE_COMPILE ) + ) ); + setVariableValueToObject( mojo, "processDependencies", true ); + setVariableValueToObject( mojo, "includes", new String[] {"default-group:other-artifact"} ); + + + try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) ) + { + pomHelper.when( () -> PomHelper.setDependencyVersion( any(), any(), any(), any(), any(), any() ) ) + .thenReturn( true ); + mojo.update( null ); + } + assertThat( changeRecorder.getChanges(), hasSize( 1 ) ); + assertThat( changeRecorder.getChanges(), + hasItem( new VersionChange( "default-group", "other-artifact", "1.0", + "2.0" ) ) ); + } + + @Test + public void testExcludeFilter() + throws MojoExecutionException, XMLStreamException, MojoFailureException, IllegalAccessException + { + mojo.getProject().getModel().setDependencies( Arrays.asList( + DependencyBuilder.dependencyWith( "default-group", "dependency-artifact", "0.9.0", + "default", "pom", SCOPE_COMPILE ), + DependencyBuilder.dependencyWith( "default-group", "other-artifact", "1.0", + "default", "pom", SCOPE_COMPILE ) + ) ); + setVariableValueToObject( mojo, "processDependencies", true ); + setVariableValueToObject( mojo, "excludes", new String[] {"default-group:other-artifact"} ); + + + try ( MockedStatic pomHelper = mockStatic( PomHelper.class ) ) + { + pomHelper.when( () -> PomHelper.setDependencyVersion( any(), any(), any(), any(), any(), any() ) ) + .thenReturn( true ); + mojo.update( null ); + } + assertThat( changeRecorder.getChanges(), hasSize( 1 ) ); + assertThat( changeRecorder.getChanges(), + not( hasItem( new VersionChange( "default-group", "other-artifact", "1.0", + "2.0" ) ) ) ); + } }