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 23, 2022
1 parent acc5dbd commit 7f356c2
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 102 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 @@ -46,6 +54,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 @@ -60,6 +72,8 @@ public abstract class AbstractVersionDetails
*/
private boolean includeSnapshots = false;

private boolean verboseDetail = false;

/**
* 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 Down Expand Up @@ -441,7 +455,7 @@ protected Optional<String> getLowerBound( ArtifactVersion version, Optional<Segm
* @param candidate the version to check.
* @return true if the candidate version is within the range of the restriction parameter.
*/
private boolean isVersionInRestriction( Restriction restriction, ArtifactVersion candidate )
public boolean isVersionInRestriction( Restriction restriction, ArtifactVersion candidate )
{
ArtifactVersion lowerBound = restriction.getLowerBound();
ArtifactVersion upperBound = restriction.getUpperBound();
Expand All @@ -456,4 +470,75 @@ private boolean isVersionInRestriction( Restriction restriction, ArtifactVersion
}
return ( includeLower || lower != 0 ) && ( includeUpper || upper != 0 );
}

public final ArtifactVersion getReportNewestUpdate( Optional<Segment> updateScope )
{
return getArtifactVersionStream( updateScope )
.min( Collections.reverseOrder( getVersionComparator() ) ).orElse( null );
}

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] );
}

private Stream<ArtifactVersion> getArtifactVersionStream( Optional<Segment> updateScope )
{
if ( isCurrentVersionDefined() )
{
try
{
// 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 = VersionRange.createFromVersionSpec( getCurrentVersion().toString() )
.getRestrictions().stream().map( Restriction::getLowerBound ).filter( Objects::nonNull )
.max( getVersionComparator() ).orElse( getCurrentVersion() );
Restriction restriction = getVersionComparator().restrictionFor( highestLowerBound, updateScope );

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@
*/

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
Expand All @@ -32,6 +38,8 @@
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.ArtifactVersionsCache;
import org.codehaus.mojo.versions.api.ReportRenderer;
import org.codehaus.mojo.versions.api.Segment;
import org.codehaus.mojo.versions.ordering.BoundArtifactVersion;
import org.codehaus.plexus.i18n.I18N;

import static java.util.Optional.empty;
Expand Down Expand Up @@ -59,10 +67,10 @@ public abstract class AbstractVersionsReportRenderer<T> extends VersionsReportRe
protected T model;

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

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

protected AbstractVersionsReportRenderer( I18N i18n, Sink sink, Locale locale, String bundleName, T model )
{
Expand Down Expand Up @@ -207,9 +215,9 @@ protected void renderSummaryTableHeader( boolean hasScope, boolean hasType )
"report.latestIncremental", "report.latestMinor", "report.latestMajor" );
}

protected void renderSummaryTableRow( Dependency artifact, ArtifactVersions details,
boolean includeScope )
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 @@ -392,27 +400,7 @@ else if ( newestUpdateCache.get( details, of( MAJOR ) ) != null )
sink.text( getText( "report.updateVersions" ) );
sink.tableHeaderCell_();
sink.tableCell( cellAttributes );
for ( int i = 0; i < allUpdates.length; i++ )
{
if ( i > 0 )
{
sink.lineBreak();
}
String label = getLabel( allUpdates[i], details );
if ( label != null )
{
safeBold();
}
sink.text( allUpdates[i].toString() );
if ( label != null )
{
safeBold_();
sink.nonBreakingSpace();
safeItalic();
sink.text( label );
safeItalic_();
}
}
sinkVersions( details, allUpdates );
sink.tableCell_();
sink.tableRow_();
}
Expand Down Expand Up @@ -462,4 +450,78 @@ protected String getLabel( ArtifactVersion version, AbstractVersionDetails detai

return null;
}

private List<Restriction> getArtifactVersionRange( AbstractVersionDetails details )
{
String spec = details.getCurrentVersion().toString();
try
{
VersionRange range = VersionRange.createFromVersionSpec( spec );
return range.getRestrictions().stream().map(
restriction -> new Restriction(
restriction.getLowerBound() == null ? null
: new BoundArtifactVersion( restriction.getLowerBound(), Segment.of(
details.getVersionComparator().getSegmentCount( restriction.getLowerBound() ) - 0 ) ),
restriction.isLowerBoundInclusive(),
restriction.getLowerBound() == null ? null
: new BoundArtifactVersion( restriction.getLowerBound(), Segment.of(
details.getVersionComparator().getSegmentCount( restriction.getLowerBound() ) - 1 ) ),
restriction.isUpperBoundInclusive() )
).collect( Collectors.toList() );
}
catch ( InvalidVersionSpecificationException ignored )
{
// ignored
}
return Collections.EMPTY_LIST;
}

protected void sinkVersions( AbstractVersionDetails details, ArtifactVersion[] allUpdates )
{
List<Restriction> versionRange = getArtifactVersionRange( details );
boolean someNotAllowed = false;
for ( int i = 0; i < allUpdates.length; i++ )
{
if ( i > 0 )
{
sink.lineBreak();
}
// if candidate version in range, display no star.
ArtifactVersion candidate = allUpdates[i];
boolean allowed = versionRange.stream().anyMatch( restriction ->
details.isVersionInRestriction( restriction, candidate ) );
String label = getLabel( allUpdates[i], details );
if ( !allowed )
{
sink.text( "* " );
someNotAllowed = true;
}
if ( allowed && label != null )
{
safeBold();
}
sink.text( allUpdates[i].toString() );
if ( label != null )
{
if ( allowed )
{
safeBold_();
}
sink.nonBreakingSpace();
safeItalic();
sink.text( label );
safeItalic_();
}
}
if ( someNotAllowed )
{
sink.lineBreak();
sink.lineBreak();
sink.text( "* " );
safeItalic();
sink.text( getText( "report.excludedVersion" ) );
safeItalic_();
}
}

}
Loading

0 comments on commit 7f356c2

Please sign in to comment.