Skip to content

Commit

Permalink
Resolves mojohaus#872: Make allowSnapshots an explicit argument in lo…
Browse files Browse the repository at this point in the history
…okupDependencyUpdates and in reports
  • Loading branch information
jarmoniuk committed Dec 23, 2022
1 parent 2bed457 commit f1b3894
Show file tree
Hide file tree
Showing 41 changed files with 474 additions and 296 deletions.
Expand Up @@ -64,13 +64,6 @@ public abstract class AbstractVersionDetails implements VersionDetails {
*/
private ArtifactVersion currentVersion = null;

/**
* Do we want to include snapshots when snapshot inclusion is not specified. Guarded by {@link #currentVersionLock}.
*
* @since 1.0-beta-1
*/
private boolean includeSnapshots = false;

protected boolean verboseDetail = true;

/**
Expand Down Expand Up @@ -145,50 +138,18 @@ public final void setCurrentVersion(String currentVersion) {
setCurrentVersion(currentVersion == null ? null : new DefaultArtifactVersion(currentVersion));
}

@Override
public final boolean isIncludeSnapshots() {
synchronized (currentVersionLock) {
return includeSnapshots;
}
}

@Override
public final void setIncludeSnapshots(boolean includeSnapshots) {
synchronized (currentVersionLock) {
this.includeSnapshots = includeSnapshots;
}
}

@Override
public final ArtifactVersion[] getVersions() {
return getVersions(isIncludeSnapshots());
}

@Override
public abstract ArtifactVersion[] getVersions(boolean includeSnapshots);

@Override
public final ArtifactVersion[] getVersions(VersionRange versionRange, boolean includeSnapshots) {
return getVersions(versionRange, null, includeSnapshots);
}

@Override
public final ArtifactVersion[] getVersions(ArtifactVersion lowerBound, ArtifactVersion upperBound) {
return getVersions(lowerBound, upperBound, isIncludeSnapshots());
}

@Override
public final ArtifactVersion[] getVersions(
ArtifactVersion lowerBound, ArtifactVersion upperBound, boolean includeSnapshots) {
Restriction restriction = new Restriction(lowerBound, false, upperBound, false);
return getVersions(restriction, includeSnapshots);
}

@Override
public final ArtifactVersion getNewestVersion(ArtifactVersion lowerBound, ArtifactVersion upperBound) {
return getNewestVersion(lowerBound, upperBound, isIncludeSnapshots());
}

@Override
public final ArtifactVersion getNewestVersion(
ArtifactVersion lowerBound, ArtifactVersion upperBound, boolean includeSnapshots) {
Expand Down Expand Up @@ -334,16 +295,6 @@ public final ArtifactVersion[] getAllUpdates(
}
}

@Override
public final ArtifactVersion getNewestUpdate(Optional<Segment> updateScope) {
return getNewestUpdate(updateScope, isIncludeSnapshots());
}

@Override
public final ArtifactVersion[] getAllUpdates(Optional<Segment> updateScope) {
return getAllUpdates(updateScope, isIncludeSnapshots());
}

@Override
public final ArtifactVersion getNewestUpdate(Optional<Segment> updateScope, boolean includeSnapshots) {
if (isCurrentVersionDefined()) {
Expand All @@ -361,13 +312,8 @@ public final ArtifactVersion[] getAllUpdates(Optional<Segment> updateScope, bool
}

@Override
public final ArtifactVersion[] getAllUpdates() {
return getAllUpdates((VersionRange) null, isIncludeSnapshots());
}

@Override
public final ArtifactVersion[] getAllUpdates(VersionRange versionRange) {
return getAllUpdates(versionRange, isIncludeSnapshots());
public final ArtifactVersion[] getAllUpdates(boolean includeSnapshots) {
return getAllUpdates((VersionRange) null, includeSnapshots);
}

@Override
Expand Down Expand Up @@ -441,24 +387,26 @@ public boolean isVersionInRestriction(Restriction restriction, ArtifactVersion c

/**
* 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.
* or {@code null} if no such version exists.
* @param updateScope the scope of updates to include.
* @param includeSnapshots whether snapshots should be included
* @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)
public final ArtifactVersion getReportNewestUpdate(Optional<Segment> updateScope, boolean includeSnapshots) {
return getArtifactVersionStream(updateScope, includeSnapshots)
.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.
* @param includeSnapshots whether snapshots should be included
* @return all versions after currentVersion within the specified update scope.
*/
public final ArtifactVersion[] getReportUpdates(Optional<Segment> updateScope) {
TreeSet<ArtifactVersion> versions = getArtifactVersionStream(updateScope)
public final ArtifactVersion[] getReportUpdates(Optional<Segment> updateScope, boolean includeSnapshots) {
TreeSet<ArtifactVersion> versions = getArtifactVersionStream(updateScope, includeSnapshots)
.collect(Collectors.toCollection(() -> new TreeSet<>(getVersionComparator())));
// filter out intermediate minor versions.
if (!verboseDetail) {
Expand Down Expand Up @@ -493,16 +441,16 @@ public final ArtifactVersion[] getReportUpdates(Optional<Segment> updateScope) {
/**
* Returns all versions newer than the specified current version, and within the specified update scope.
* @param updateScope the scope of updates to include.
* @param includeSnapshots whether snapshots should be included
* @return all versions after currentVersion within the specified update scope.
*/
private Stream<ArtifactVersion> getArtifactVersionStream(Optional<Segment> updateScope) {
private Stream<ArtifactVersion> getArtifactVersionStream(Optional<Segment> updateScope, boolean includeSnapshots) {
if (isCurrentVersionDefined()) {
try {
Restriction restriction = restrictionFor(updateScope);

return Arrays.stream(getVersions())
.filter(candidate -> (isIncludeSnapshots() || !ArtifactUtils.isSnapshot(candidate.toString()))
&& isVersionInRestriction(restriction, candidate));
return Arrays.stream(getVersions(includeSnapshots))
.filter(candidate -> isVersionInRestriction(restriction, candidate));
} catch (InvalidSegmentException ignored) {
ignored.printStackTrace(System.err);
}
Expand Down
Expand Up @@ -91,7 +91,6 @@ public ArtifactVersions(ArtifactVersions other) {
versionComparator = other.versionComparator;
versions = other.versions;
setCurrentVersion(other.getCurrentVersion());
setIncludeSnapshots(other.isIncludeSnapshots());
}

@SuppressWarnings("checkstyle:InnerAssignment")
Expand Down Expand Up @@ -122,7 +121,7 @@ public boolean equals(Object o) {

return new EqualsBuilder()
.append(getArtifact(), that.getArtifact())
.append(getVersions(), that.getVersions())
.append(getVersions(true), that.getVersions(true))
.append(getVersionComparator(), that.getVersionComparator())
.isEquals();
}
Expand All @@ -131,7 +130,7 @@ public boolean equals(Object o) {
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(getArtifact())
.append(getVersions())
.append(getVersions(true))
.append(getVersionComparator())
.toHashCode();
}
Expand Down Expand Up @@ -218,6 +217,24 @@ public ArtifactVersion[] getVersions(boolean includeSnapshots) {
.toArray(ArtifactVersion[]::new);
}

/**
* Says whether the versions present in the {@link ArtifactVersions} collection are empty.
* If {@code includeSnapshots} is {@code true}, snapshots will not counted, which means that
* the method will only count release versions.
*
* @param includeSnapshots {@code includeSnapshots} is {@code true}, snapshots will not counted, which means that
* * the method will only count release versions.
* @return if {@code includeSnapshots} is {@code true}, returns {@code true} if there are no versions.
* if {@code includeSnapshots} is {@code false}, returns {@code true} if there are no releases.
*/
public boolean isEmpty(boolean includeSnapshots) {
return includeSnapshots
? versions.isEmpty()
// the below means: the only versions that could be present in the collection
// are snapshots
: versions.stream().map(Object::toString).allMatch(ArtifactUtils::isSnapshot);
}

public VersionComparator getVersionComparator() {
return versionComparator;
}
Expand Down
Expand Up @@ -22,24 +22,24 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.function.TriFunction;
import org.apache.commons.lang3.tuple.Triple;

/**
* Utility providing a cached {@link ArtifactVersions#getNewestUpdate(Optional)} API
* Utility providing a cached {@link ArtifactVersions#getNewestUpdate(Optional, boolean)} API
*/
public class ArtifactVersionsCache {
private BiFunction<AbstractVersionDetails, Optional<Segment>, ?> cachedFunction;

private Map<Pair<? extends AbstractVersionDetails, Optional<Segment>>, Object> updateCache = new HashMap<>();
private TriFunction<AbstractVersionDetails, Optional<Segment>, Boolean, ?> cachedFunction;
private Map<Triple<? extends AbstractVersionDetails, Optional<Segment>, Boolean>, Object> updateCache =
new HashMap<>();

/**
* Constructs a new instance given the concrete function for obtaining the details
*
* @param cachedFunction reference to the function computing the required information
*/
public ArtifactVersionsCache(BiFunction<AbstractVersionDetails, Optional<Segment>, ?> cachedFunction) {
public ArtifactVersionsCache(TriFunction<AbstractVersionDetails, Optional<Segment>, Boolean, ?> cachedFunction) {
this.cachedFunction = cachedFunction;
}

Expand All @@ -52,11 +52,14 @@ public ArtifactVersionsCache(BiFunction<AbstractVersionDetails, Optional<Segment
* @param <R> return type of the cached function
* @param artifactVersions {@linkplain ArtifactVersions} object referring to the given dependency
* @param updateScope update scope
* @param allowSnapshots whether snapshots should be included
* @return last retrieved update information
*/
@SuppressWarnings("unchecked")
public <V extends AbstractVersionDetails, R> R get(V artifactVersions, Optional<Segment> updateScope) {
public <V extends AbstractVersionDetails, R> R get(
V artifactVersions, Optional<Segment> updateScope, boolean allowSnapshots) {
return (R) updateCache.computeIfAbsent(
Pair.of(artifactVersions, updateScope), pair -> cachedFunction.apply(pair.getLeft(), pair.getRight()));
Triple.of(artifactVersions, updateScope, allowSnapshots),
triple -> cachedFunction.apply(triple.getLeft(), triple.getMiddle(), triple.getRight()));
}
}
Expand Up @@ -422,23 +422,16 @@ public ArtifactVersion createArtifactVersion(String version) {
return new DefaultArtifactVersion(version);
}

/**
* Returns a map of all possible updates per dependency. The lookup is done in parallel using
* {@code LOOKUP_PARALLEL_THREADS} threads.
*
* @param dependencies The set of {@link Dependency} instances to look up.
* @param usePluginRepositories Search the plugin repositories.
* @return map containing the ArtifactVersions object per dependency
*/
@Override
public Map<Dependency, ArtifactVersions> lookupDependenciesUpdates(
Set<Dependency> dependencies, boolean usePluginRepositories) throws VersionRetrievalException {
Set<Dependency> dependencies, boolean usePluginRepositories, boolean allowSnapshots)
throws VersionRetrievalException {
ExecutorService executor = Executors.newFixedThreadPool(LOOKUP_PARALLEL_THREADS);
try {
Map<Dependency, ArtifactVersions> dependencyUpdates = new TreeMap<>(DependencyComparator.INSTANCE);
List<Future<? extends Pair<Dependency, ArtifactVersions>>> futures = dependencies.stream()
.map(dependency -> executor.submit(() -> new ImmutablePair<>(
dependency, lookupDependencyUpdates(dependency, usePluginRepositories))))
dependency, lookupDependencyUpdates(dependency, usePluginRepositories, allowSnapshots))))
.collect(Collectors.toList());
for (Future<? extends Pair<Dependency, ArtifactVersions>> details : futures) {
Pair<Dependency, ArtifactVersions> pair = details.get();
Expand All @@ -455,13 +448,14 @@ dependency, lookupDependencyUpdates(dependency, usePluginRepositories))))
}

@Override
public ArtifactVersions lookupDependencyUpdates(Dependency dependency, boolean usePluginRepositories)
public ArtifactVersions lookupDependencyUpdates(
Dependency dependency, boolean usePluginRepositories, boolean allowSnapshots)
throws VersionRetrievalException {
ArtifactVersions allVersions =
lookupArtifactVersions(createDependencyArtifact(dependency), usePluginRepositories);
return new ArtifactVersions(
allVersions.getArtifact(),
Arrays.stream(allVersions.getAllUpdates()).collect(Collectors.toList()),
Arrays.stream(allVersions.getAllUpdates(allowSnapshots)).collect(Collectors.toList()),
allVersions.getVersionComparator());
}

Expand Down Expand Up @@ -498,13 +492,13 @@ public PluginUpdatesDetails lookupPluginUpdates(Plugin plugin, boolean allowSnap
pluginDependencies.addAll(plugin.getDependencies());
}
Map<Dependency, ArtifactVersions> pluginDependencyDetails =
lookupDependenciesUpdates(pluginDependencies, false);
lookupDependenciesUpdates(pluginDependencies, false, allowSnapshots);

ArtifactVersions allVersions = lookupArtifactVersions(
createPluginArtifact(plugin.getGroupId(), plugin.getArtifactId(), version), true);
ArtifactVersions updatedVersions = new ArtifactVersions(
allVersions.getArtifact(),
Arrays.stream(allVersions.getAllUpdates()).collect(Collectors.toList()),
Arrays.stream(allVersions.getAllUpdates(allowSnapshots)).collect(Collectors.toList()),
allVersions.getVersionComparator());
return new PluginUpdatesDetails(updatedVersions, pluginDependencyDetails, allowSnapshots);
}
Expand Down

0 comments on commit f1b3894

Please sign in to comment.