Skip to content

Commit

Permalink
Resolves #872: Make allowSnapshots an explicit argument in lookupDepe…
Browse files Browse the repository at this point in the history
…ndencyUpdates and in reports
  • Loading branch information
andrzejj0 authored and slawekjaranowski committed Dec 23, 2022
1 parent 2fe2c3d commit 67c1800
Show file tree
Hide file tree
Showing 41 changed files with 474 additions and 296 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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()));
}
}
Original file line number Diff line number Diff line change
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
Loading

0 comments on commit 67c1800

Please sign in to comment.