Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolves #872: Make allowSnapshots an explicit argument in lookupDependencyUpdates and in reports #873

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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))
jarmoniuk marked this conversation as resolved.
Show resolved Hide resolved
.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))
jarmoniuk marked this conversation as resolved.
Show resolved Hide resolved
.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