Skip to content

Commit

Permalink
mojohaus#454: Introducing "infinity-like" calculus for dependency ran…
Browse files Browse the repository at this point in the history
…ge computation
  • Loading branch information
jarmoniuk committed Oct 2, 2022
1 parent e7aa406 commit 1915032
Show file tree
Hide file tree
Showing 22 changed files with 433 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public abstract class AbstractVersionsDependencyUpdaterMojo

/**
* A comma separated list of artifact patterns to include. Follows the pattern
* "groupId:artifactId:type:classifier:version". Designed to allow specifing the set of includes from the command
* "groupId:artifactId:type:classifier:version". Designed to allow specifying the set of includes from the command
* line. When specifying includes from the pom, use the {@link #includes} configuration instead. If this property is
* specified then the {@link # include} configuration is ignored.
*
Expand All @@ -71,7 +71,7 @@ public abstract class AbstractVersionsDependencyUpdaterMojo

/**
* A comma separated list of artifact patterns to exclude. Follows the pattern
* "groupId:artifactId:type:classifier:version". Designed to allow specifing the set of excludes from the command
* "groupId:artifactId:type:classifier:version". Designed to allow specifying the set of excludes from the command
* line. When specifying excludes from the pom, use the {@link #excludes} configuration instead. If this property is
* specified then the {@link # exclude} configuration is ignored.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -780,40 +780,23 @@ private Set<String> getVersionsInRange( Property property, PropertyVersions vers

protected String getLabel( ArtifactVersion version, AbstractVersionDetails versions )
{
String label = null;
if ( equals( version, versions.getNewestUpdate( of( MAJOR ) ) ) )
{
label = getText( "report.latestMajor" );
}
else if ( equals( version, versions.getOldestUpdate( of( MAJOR ) ) ) )
{
label = getText( "report.nextMajor" );
}
else if ( equals( version, versions.getNewestUpdate( of( MINOR ) ) ) )
{
label = getText( "report.latestMinor" );
}
else if ( equals( version, versions.getOldestUpdate( of( MINOR ) ) ) )
{
label = getText( "report.nextMinor" );
}
else if ( equals( version, versions.getNewestUpdate( of( INCREMENTAL ) ) ) )
{
label = getText( "report.latestIncremental" );
}
else if ( equals( version, versions.getOldestUpdate( of( INCREMENTAL ) ) ) )
{
label = getText( "report.nextIncremental" );
}
else if ( equals( version, versions.getNewestUpdate( of( SUBINCREMENTAL ) ) ) )
{
label = getText( "report.latestSubIncremental" );
}
else if ( equals( version, versions.getOldestUpdate( of( SUBINCREMENTAL ) ) ) )
{
label = getText( "report.nextVersion" );
}
return label;
return equals( version, versions.getNewestUpdate( of( SUBINCREMENTAL ) ) )
? getText( "report.latestSubIncremental" )
: equals( version, versions.getOldestUpdate( of( SUBINCREMENTAL ) ) )
? getText( "report.nextVersion" )
: equals( version, versions.getOldestUpdate( of( INCREMENTAL ) ) )
? getText( "report.nextIncremental" )
: equals( version, versions.getNewestUpdate( of( INCREMENTAL ) ) )
? getText( "report.latestIncremental" )
: equals( version, versions.getOldestUpdate( of( MINOR ) ) )
? getText( "report.nextMinor" )
: equals( version, versions.getNewestUpdate( of( MINOR ) ) )
? getText( "report.latestMinor" )
: equals( version, versions.getOldestUpdate( of( MAJOR ) ) )
? getText( "report.nextMajor" )
: equals( version, versions.getNewestUpdate( of( MAJOR ) ) )
? getText( "report.latestMajor" )
: "";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ protected ArtifactVersion findLatestVersion( Artifact artifact, VersionRange ver
* @param versionRange The version range.
* @param allowingSnapshots <code>null</code> 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
* <code>null</code> if no matching version could be found.
* @throws ArtifactMetadataRetrievalException If the artifact metadata could not be found.
Expand Down Expand Up @@ -515,6 +516,7 @@ protected boolean shouldApplyUpdate( Artifact artifact, String currentVersion, A
* @param artifact The artifact.
* @param currentVersion The current version of the artifact.
* @param updateVersion The proposed new version of the artifact.
* @param forceUpdate if true, LATEST and RELEASE versions will be overwritten with the real version
* @return <code>true</code> if the update should be applied to the pom.
* @since 2.9
*/
Expand Down Expand Up @@ -575,7 +577,7 @@ protected boolean shouldApplyUpdate( Artifact artifact, String currentVersion, A
* @param allowMajorUpdates Allow major updates
* @param allowMinorUpdates Allow minor updates
* @param allowIncrementalUpdates Allow incremental updates
* @return Returns the segment (0-based) that is unchangable. If any segment can change, returns -1.
* @return Returns the segment (0-based) that is unchangeable. If any segment can change, returns -1.
*/
protected Optional<Segment> determineUnchangedSegment( boolean allowMajorUpdates, boolean allowMinorUpdates,
boolean allowIncrementalUpdates )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class DependencyUpdatesReport extends AbstractVersionsReport
protected boolean processDependencyManagement;

/**
* Whether to process the depdendencyManagement part transitive or not.
* Whether to process the dependencyManagement part transitive or not.
* In case of <code>&lt;type&gt;pom&lt;/type&gt;</code>and
* <code>&lt;scope&gt;import&lt;/scope&gt;</code> this means
* by default to report also the imported dependencies.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public class DisplayDependencyUpdatesMojo
private boolean processDependencyManagement;

/**
* Whether to process the depdendencyManagement part transitive or not.
* Whether to process the dependencyManagement part transitive or not.
* In case of <code>&lt;type&gt;pom&lt;/type&gt;</code>and
* <code>&lt;scope&gt;import&lt;/scope&gt;</code> this means
* by default to report also the imported dependencies.
Expand Down Expand Up @@ -691,12 +691,19 @@ private DependencyManagement getProjectDependencyManagement( MavenProject projec

private Optional<Segment> calculateUpdateScope()
{
return !allowAnyUpdates
? allowMajorUpdates ? of( MAJOR )
: allowMinorUpdates ? of( MINOR )
: allowIncrementalUpdates ? of( INCREMENTAL )
: empty()
: empty();
if ( !allowIncrementalUpdates && !allowMinorUpdates && !allowMajorUpdates && !allowAnyUpdates )
{
throw new IllegalArgumentException( "One of: allowAnyUpdates, allowMajorUpdates, allowMinorUpdates, "
+ "allowIncrementalUpdates must be true" );
}

return allowAnyUpdates && allowMajorUpdates && allowMinorUpdates
? empty()
: allowMajorUpdates && allowMinorUpdates
? of( MAJOR )
: allowMinorUpdates
? of( MINOR )
: of( INCREMENTAL );
}

private void logUpdates( Map<Dependency, ArtifactVersions> updates, String section )
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/codehaus/mojo/versions/SetMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,10 @@ public void execute() throws MojoExecutionException, MojoFailureException

/**
* Returns the incremented version, with the nextSnapshotIndexToIncrement indicating the 1-based index,
* conunting from the left, or the most major version component, of the version string.
* from the left, or the most major version component, of the version string.
*
* @param version input version
* @param nextSnapshotIndexToIncrement 1-based segment number to be incremented
* @return version with the incremented index specified by nextSnapshotIndexToIncrement or last index
* @throws MojoExecutionException thrown if the input parameters are invalid
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ private static <T> Iterable<T> reverse( T[] array )
public final ArtifactVersion getNewestVersion( VersionRange versionRange, Restriction restriction,
boolean includeSnapshots, boolean allowDowngrade )
{
final VersionComparator versionComparator = getVersionComparator();
// reverse( getVersions( ... ) ) will contain versions sorted from latest to oldest,
// so we only need to find the first candidate fulfilling the criteria
for ( ArtifactVersion candidate : reverse( getVersions( includeSnapshots ) ) )
Expand Down Expand Up @@ -346,7 +345,8 @@ public final ArtifactVersion getOldestUpdate( ArtifactVersion currentVersion, Op
{
try
{
return getOldestVersion( restrictionFor( currentVersion, updateScope ), includeSnapshots );
return getOldestVersion( getVersionComparator().restrictionFor( currentVersion, updateScope ),
includeSnapshots );
}
catch ( InvalidSegmentException e )
{
Expand All @@ -359,7 +359,8 @@ public final ArtifactVersion getNewestUpdate( ArtifactVersion currentVersion, Op
{
try
{
return getNewestVersion( restrictionFor( currentVersion, updateScope ), includeSnapshots );
return getNewestVersion( getVersionComparator().restrictionFor( currentVersion, updateScope ),
includeSnapshots );
}
catch ( InvalidSegmentException e )
{
Expand All @@ -372,7 +373,8 @@ public final ArtifactVersion[] getAllUpdates( ArtifactVersion currentVersion, Op
{
try
{
return getVersions( restrictionFor( currentVersion, updateScope ), includeSnapshots );
return getVersions( getVersionComparator().restrictionFor( currentVersion, updateScope ),
includeSnapshots );
}
catch ( InvalidSegmentException e )
{
Expand Down Expand Up @@ -438,7 +440,7 @@ public ArtifactVersion[] getAllUpdates( VersionRange versionRange, boolean inclu
* and the lowest unchanged segment index (0-based); -1 means that the whole version string can be changed,
* implying that there is also no string designation of the lower bound version.
*
* @param version {@link ArtifactVersion} object specyfing the verion for which the lower bound is being computed
* @param version {@link ArtifactVersion} object specifying the version for which the lower bound is being computed
* @param unchangedSegment first segment not to be changed; empty() means any segment can change
* @return {@link ArtifactVersion} the lowest artifact version with the given segment held or null if no such
* version can be found
Expand All @@ -458,7 +460,7 @@ protected ArtifactVersion getLowerBoundArtifactVersion( ArtifactVersion version,
* and the lowest unchanged segment index (0-based); -1 means that the whole version string can be changed,
* implying that there is also no string designation of the lower bound version.
*
* @param version {@link ArtifactVersion} object specyfing the verion for which the lower bound is being computed
* @param version {@link ArtifactVersion} object specifying the version for which the lower bound is being computed
* @param unchangedSegment first segment not to be changed; empty() means anything can change
* @return {@link Optional} string containing the lowest artifact version with the given segment held
* @throws InvalidSegmentException if the requested segment is outside of the bounds (less than 1 or greater than
Expand Down Expand Up @@ -527,26 +529,4 @@ private boolean isVersionInRestriction( Restriction restriction, ArtifactVersion
}
return ( includeLower || lower != 0 ) && ( includeUpper || upper != 0 );
}

/**
* Helper method to get the artifact boundaries for computing updates
*
* @param currentVersion The current version.
* @param scope scope of the restriction or Optional.empty() for no restriction
* @return {@linkplain Restriction} object based on the arguments
* @throws InvalidSegmentException if {@code segment} ∉ [0, segmentCount)
*/
protected Restriction restrictionFor( ArtifactVersion currentVersion, Optional<Segment> scope )
throws InvalidSegmentException
{
VersionComparator versionComparator = getVersionComparator();
ArtifactVersion lowerBound = scope.isPresent() && scope.get().value() < Segment.SUBINCREMENTAL.value()
? versionComparator.incrementSegment( currentVersion, scope.get() )
: currentVersion;
ArtifactVersion upperBound = scope.isPresent() && scope.get().value() > Segment.MAJOR.value()
? versionComparator.incrementSegment( currentVersion, Segment.of( scope.get().value() - 1 ) )
: null;
return new Restriction( lowerBound, lowerBound != currentVersion,
upperBound, false );
}
}
21 changes: 12 additions & 9 deletions src/main/java/org/codehaus/mojo/versions/api/Segment.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@
*/
public enum Segment implements Comparable<Segment>
{
MAJOR( 0 ), MINOR( 1 ), INCREMENTAL( 2 ), SUBINCREMENTAL( 3 );

private final int index;

Segment( int index )
{
this.index = index;
}
MAJOR, MINOR, INCREMENTAL, SUBINCREMENTAL;

/**
* Returns the 0-based sendex index
Expand All @@ -42,7 +35,7 @@ public enum Segment implements Comparable<Segment>
*/
public int value()
{
return index;
return ordinal();
}

public static Segment of( int index )
Expand All @@ -58,6 +51,16 @@ public static Segment of( int index )
}
}

/**
* Returns true if the given segment is more major than the other
* @param other other segment to compare
* @return true if the given segment is more major
*/
public boolean isMajorTo( Segment other )
{
return value() < other.value();
}

@Override
public String toString()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,17 @@ public final int getSegmentCount( ArtifactVersion v )
*/
public final ArtifactVersion incrementSegment( ArtifactVersion v, Segment segment ) throws InvalidSegmentException
{
return VersionComparators.copySnapshot( v, innerIncrementSegment( VersionComparators.stripSnapshot( v ),
segment ) );
if ( VersionComparators.isSnapshot( v ) )
{
return VersionComparators.copySnapshot( v, innerIncrementSegment( VersionComparators.stripSnapshot( v ),
segment ) );
}
int segmentCount = getSegmentCount( v );
if ( segment.value() >= segmentCount )
{
throw new InvalidSegmentException( segment, segmentCount, v );
}
return innerIncrementSegment( v, segment );
}

protected abstract ArtifactVersion innerIncrementSegment( ArtifactVersion v, Segment segment )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package org.codehaus.mojo.versions.ordering;

import java.util.Iterator;
import java.util.List;

import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.codehaus.mojo.versions.api.Segment;

import static org.codehaus.mojo.versions.ordering.ComparableVersion.IntegerItem.ZERO;

/**
* <p>Represents an artifact version with all segments more major or equal to a given segment
* held in place. It can be thought of as an artifact having +&infin; as its upper bound
* on all segments less major than the held segment.</p>
* <p>When compared with another artifact versions, this results with the other object
* with the segment versions up to the held segment being equal,
* always comparing lower than this object.</p>
* <p>This is particularly helpful for -SNAPSHOT and other versions with qualifiers, which
* are lower than version 0 in the Maven versioning system.</p>
*/
public class BoundArtifactVersion extends DefaultArtifactVersion
{
/**
* Most major segment that can change, i.e. not held in place.
* All segments that are more major than this one are held in place.
*/
private final Segment segment;

private final BoundComparableVersion comparator;

/**
* Constructs the instance
* @param artifactVersion artifact version containing the segment version values
* @param segment most major segment that can change, i.e. <em>not</em> held in place
* @param bound whether the object is held at the lower or the upper bound
*/
public BoundArtifactVersion( ArtifactVersion artifactVersion, Segment segment )
{
super( artifactVersion.toString() );
this.segment = segment;
this.comparator = new BoundComparableVersion( this );
}

/**
* Returns the most major segment that can change.
* All segments that are more major than this one are held in place.
* @return segment that can change
*/
public Segment getSegment()
{
return segment;
}

@Override
public int compareTo( ArtifactVersion other )
{
if ( other == null )
{
return -1;
}

return comparator.compareTo( new ComparableVersion( other.toString() ) );
}

protected static class BoundComparableVersion extends ComparableVersion
{
private BoundArtifactVersion artifactVersion;
protected BoundComparableVersion( BoundArtifactVersion artifactVersion )
{
super( artifactVersion.toString() );
this.artifactVersion = artifactVersion;
}

@Override
public int compareTo( ComparableVersion o )
{
return compareTo( ( (List<Item>) items ).iterator(),
( (Iterable<Item>) o.items ).iterator(), artifactVersion.segment.value() );

}

@SuppressWarnings( "checkstyle:InnerAssignment" )
private int compareTo( Iterator<Item> left, Iterator<Item> right, int comparisonLimit )
{
int r;
return !( comparisonLimit > 0 && right.hasNext() )
? 1
: ( r = -( right.next().compareTo( left.hasNext() ? left.next() : ZERO ) ) ) != 0
? r
: compareTo( left, right, comparisonLimit - 1 );
}
}
}
Loading

0 comments on commit 1915032

Please sign in to comment.