Skip to content

Commit

Permalink
display versions outside range with star
Browse files Browse the repository at this point in the history
  • Loading branch information
sultan committed Nov 26, 2022
1 parent d4d0f26 commit 2c74328
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@
*/

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.Objects;
import java.util.Optional;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.codehaus.mojo.versions.ordering.BoundArtifactVersion;
Expand All @@ -47,6 +55,10 @@ public abstract class AbstractVersionDetails
implements VersionDetails
{

private static final Pattern PREVIEW_PATTERN =
Pattern.compile( "(?i)(?:.*[-.](alpha|a|beta|b|milestone|m|preview|rc)"
+ "[-.]?(\\d{0,2}[a-z]?|\\d{6}\\.\\d{4})|\\d{8}(?:\\.?\\d{6})?)$" );

/**
* The current version. Guarded by {@link #currentVersionLock}.
*
Expand All @@ -61,6 +73,8 @@ public abstract class AbstractVersionDetails
*/
private boolean includeSnapshots = false;

protected boolean verboseDetail = true;

/**
* Not sure if we need to be thread safe, but there's no harm being careful, after all we could be invoked from an
* IDE.
Expand All @@ -77,6 +91,24 @@ protected AbstractVersionDetails()
public Restriction restrictionFor( Optional<Segment> scope )
throws InvalidSegmentException
{
// one range spec can have multiple restrictions, and multiple 'lower bound', we want the highest one.
// [1.0,2.0),[3.0,4.0) -> 3.0
ArtifactVersion highestLowerBound = currentVersion;
if ( currentVersion != null )
{
try
{
highestLowerBound = VersionRange.createFromVersionSpec( currentVersion.toString() )
.getRestrictions().stream().map( Restriction::getLowerBound ).filter( Objects::nonNull )
.max( getVersionComparator() ).orElse( currentVersion );
}
catch ( InvalidVersionSpecificationException ignored )
{
ignored.printStackTrace( System.err );
}
}

final ArtifactVersion currentVersion = highestLowerBound;
ArtifactVersion nextVersion = scope
.filter( s -> s.isMajorTo( SUBINCREMENTAL ) )
.map( s -> (ArtifactVersion)
Expand Down Expand Up @@ -480,4 +512,87 @@ public boolean isVersionInRestriction( Restriction restriction, ArtifactVersion
}
return ( includeLower || lower != 0 ) && ( includeUpper || upper != 0 );
}

/**
* Returns the latest version newer than the specified current version, and within the specified update scope,
* or <code>null</code> if no such version exists.
* @param updateScope the scope of updates to include.
* @return the newest version after currentVersion within the specified update scope,
* or <code>null</code> if no version is available.
*/
public final ArtifactVersion getReportNewestUpdate( Optional<Segment> updateScope )
{
return getArtifactVersionStream( updateScope )
.min( Collections.reverseOrder( getVersionComparator() ) ).orElse( null );
}

/**
* Returns all versions newer than the specified current version, and within the specified update scope.
* @param updateScope the scope of updates to include.
* @return all versions after currentVersion within the specified update scope.
*/
public final ArtifactVersion[] getReportUpdates( Optional<Segment> updateScope )
{
TreeSet<ArtifactVersion> versions = getArtifactVersionStream( updateScope )
.collect( Collectors.toCollection( () -> new TreeSet<>( getVersionComparator() ) ) );
// filter out intermediate minor versions.
if ( !verboseDetail )
{
int major = 0;
int minor = 0;
boolean needOneMore = false;
for ( Iterator<ArtifactVersion> it = versions.descendingIterator(); it.hasNext(); )
{
ArtifactVersion version = it.next();
boolean isPreview = PREVIEW_PATTERN.matcher( version.toString() ).matches();

// encountered a version in same Major.Minor version, remove it.
if ( version.getMajorVersion() == major && version.getMinorVersion() == minor )
{
if ( needOneMore && !isPreview )
{
needOneMore = false;
continue;
}
it.remove();
continue;
}

// encountered a new Major.Minor version, keep it.
major = version.getMajorVersion();
minor = version.getMinorVersion();

// if version is a pre-release, also search for the last release.
needOneMore = isPreview;

}
}
return versions.toArray( new ArtifactVersion[0] );
}

/**
* Returns all versions newer than the specified current version, and within the specified update scope.
* @param updateScope the scope of updates to include.
* @return all versions after currentVersion within the specified update scope.
*/
private Stream<ArtifactVersion> getArtifactVersionStream( Optional<Segment> updateScope )
{
if ( isCurrentVersionDefined() )
{
try
{
Restriction restriction = restrictionFor( updateScope );

return Arrays.stream( getVersions() ).filter(
candidate -> ( isIncludeSnapshots() || !ArtifactUtils.isSnapshot( candidate.toString() ) )
&& isVersionInRestriction( restriction, candidate ) );
}
catch ( InvalidSegmentException ignored )
{
ignored.printStackTrace( System.err );
}
}
return Stream.empty();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals.1=${project.groupId}:${project.artifactId}:${project.version}:property-updates-report
invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:dependency-updates-report
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>localhost</groupId>
<artifactId>it-823-ranges-update-report</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>ranges-update-report</name>
<url>http://localhost/</url>

<properties>
<verion.dummy-api>[1.1.2,3.0]</verion.dummy-api>
</properties>
<dependencies>
<dependency>
<groupId>localhost</groupId>
<artifactId>dummy-api</artifactId>
<version>${verion.dummy-api}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

propertyUpdatesReport = new File( basedir, "target/site/property-updates-report.html" ).text
.replaceAll( '<[^>]+>', ' ' )
.replaceAll( '&[^;]+;', ' ' )
.replaceAll( '\\s+', ' ' )

assert ! ( propertyUpdatesReport =~ /\b1\.1\.0-2\b/ )
assert ! ( propertyUpdatesReport =~ /\b1\.1\.1-2\b/ )
// Summary
assert propertyUpdatesReport =~ / \[1\.1\.2,3\.0\] 1\.1\.3 1\.3 3/
// Detail
assert propertyUpdatesReport =~ /Newer versions 1\.1\.3 Latest Incremental/
assert propertyUpdatesReport =~ /\b1\.2\.2 1\.3 Latest Minor 2\.0 2\.1 3\.0\b/

dependencyUpdatesReport = new File( basedir, "target/site/dependency-updates-report.html" ).text
.replaceAll( '<[^>]+>', ' ' )
.replaceAll( '&[^;]+;', ' ' )
.replaceAll( '\\s+', ' ' )

assert ! ( dependencyUpdatesReport =~ /\b1\.1\.0-2\b/ )
assert ! ( dependencyUpdatesReport =~ /\b1\.1\.1-2\b/ )
// Summary
assert propertyUpdatesReport =~ / \[1\.1\.2,3\.0\] 1\.1\.3 1\.3 3/
// Detail
assert propertyUpdatesReport =~ /Newer versions 1\.1\.3 Latest Incremental/
assert propertyUpdatesReport =~ /\b1\.2\.2 1\.3 Latest Minor 2\.0 2\.1 3\.0\b/
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals.1=${project.groupId}:${project.artifactId}:${project.version}:property-updates-report
invoker.goals.2=${project.groupId}:${project.artifactId}:${project.version}:dependency-updates-report
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>localhost</groupId>
<artifactId>it-823-ranges-update-report</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>ranges-update-report</name>
<url>http://localhost/</url>

<properties>
<verion.dummy-api>[1.1.2,3.0)</verion.dummy-api>
</properties>
<dependencies>
<dependency>
<groupId>localhost</groupId>
<artifactId>dummy-api</artifactId>
<version>${verion.dummy-api}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

propertyUpdatesReport = new File( basedir, "target/site/property-updates-report.html" ).text
.replaceAll( '<[^>]+>', ' ' )
.replaceAll( '&[^;]+;', ' ' )
.replaceAll( '\\s+', ' ' )

assert ! ( propertyUpdatesReport =~ /\b1\.1\.0-2\b/ )
assert ! ( propertyUpdatesReport =~ /\b1\.1\.1-2\b/ )
// Summary
assert propertyUpdatesReport =~ / \[1\.1\.2,3\.0\) 1\.1\.3 1\.3 3/
// Detail
assert propertyUpdatesReport =~ /Newer versions 1\.1\.3 Latest Incremental/
assert propertyUpdatesReport =~ /\b1\.2\.2 1\.3 Latest Minor 2\.0 2\.1 \* 3\.0\b/

dependencyUpdatesReport = new File( basedir, "target/site/dependency-updates-report.html" ).text
.replaceAll( '<[^>]+>', ' ' )
.replaceAll( '&[^;]+;', ' ' )
.replaceAll( '\\s+', ' ' )

assert ! ( dependencyUpdatesReport =~ /\b1\.1\.0-2\b/ )
assert ! ( dependencyUpdatesReport =~ /\b1\.1\.1-2\b/ )
// Summary
assert propertyUpdatesReport =~ / \[1\.1\.2,3\.0\) 1\.1\.3 1\.3 3/
// Detail
assert propertyUpdatesReport =~ /Newer versions 1\.1\.3 Latest Incremental/
assert propertyUpdatesReport =~ /\b1\.2\.2 1\.3 Latest Minor 2\.0 2\.1 \* 3\.0\b/
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ public abstract class AbstractVersionsReportRenderer<T> extends VersionsReportRe
*/
protected T model;

protected ArtifactVersionsCache newestUpdateCache
= new ArtifactVersionsCache( AbstractVersionDetails::getNewestUpdate );
protected final ArtifactVersionsCache newestUpdateCache
= new ArtifactVersionsCache( AbstractVersionDetails::getReportNewestUpdate );

protected ArtifactVersionsCache allUpdatesCache
= new ArtifactVersionsCache( AbstractVersionDetails::getAllUpdates );
protected final ArtifactVersionsCache allUpdatesCache
= new ArtifactVersionsCache( AbstractVersionDetails::getReportUpdates );

protected final SinkEventAttributes headerAttributes
= new SinkEventAttributeSet( SinkEventAttributes.WIDTH, "30%" );
Expand Down Expand Up @@ -231,6 +231,7 @@ protected void renderSummaryTableHeader( boolean hasScope, boolean hasType )

protected void renderSummaryTableRow( Dependency artifact, ArtifactVersions details, boolean includeScope )
{
details.setCurrentVersion( artifact.getVersion() );
ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() );
boolean upToDate = allUpdates == null || allUpdates.length == 0;

Expand Down Expand Up @@ -263,7 +264,6 @@ protected void renderNewestVersions( AbstractVersionDetails details )
renderBoldCell( newestUpdateCache.get( details, of( MAJOR ) ) );
}

@SuppressWarnings( "checkstyle:MethodLength" )
protected void renderDependencyDetailTable( Dependency artifact, ArtifactVersions details, boolean includeScope )
{
ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() );
Expand Down Expand Up @@ -363,25 +363,10 @@ else if ( newestUpdateCache.get( details, of( MAJOR ) ) != null )
}
}

private List<Restriction> getArtifactVersionRange( AbstractVersionDetails details )
{
try
{
String spec = details.getCurrentVersion().toString();
VersionRange range = VersionRange.createFromVersionSpec( spec );
return range.getRestrictions();
}
catch ( InvalidVersionSpecificationException ignored )
{
ignored.printStackTrace( System.err );
}
return Collections.EMPTY_LIST;
}

/**
* Renders the list of versions that are available for the given artifact or property.
* @param allUpdates the list of all updates available.
* @param details TODO.
* @param details the versions details for the given artifact or property.
*/
protected void renderVersions( ArtifactVersion[] allUpdates, AbstractVersionDetails details )
{
Expand Down Expand Up @@ -463,4 +448,25 @@ protected String getLabel( ArtifactVersion version, AbstractVersionDetails detai
return null;
}

/**
* Builds the list of restrictions for the given artifact or property, based on its version range.
* used to determine if a candidate version is outside the range, and if it should be displayed with a star.
* @param details the artifact or property for which to render the versions.
* @return the list of restrictions for the spec versions range.
*/
private List<Restriction> getArtifactVersionRange( AbstractVersionDetails details )
{
try
{
String spec = details.getCurrentVersion().toString();
VersionRange range = VersionRange.createFromVersionSpec( spec );
return range.getRestrictions();
}
catch ( InvalidVersionSpecificationException ignored )
{
ignored.printStackTrace( System.err );
}
return Collections.EMPTY_LIST;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ protected void renderSummaryTableRow( Dependency artifact, PluginUpdatesDetails
sink.tableRow_();
}

@SuppressWarnings( "checkstyle:MethodLength" )
private void renderPluginDetail( Dependency artifact, PluginUpdatesDetails details )
{
sink.section2();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ private void renderPropertySummaryTableRow( Property property, PropertyVersions
sink.tableRow_();
}

@SuppressWarnings( "checkstyle:MethodLength" )
protected void renderPropertyDetailTable( Property property, PropertyVersions details )
{
ArtifactVersion[] allUpdates = allUpdatesCache.get( details, empty() );
Expand Down

0 comments on commit 2c74328

Please sign in to comment.