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

Align update-parent and display-parent-update #1017

Merged
merged 9 commits into from
Nov 16, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,33 @@

import javax.inject.Inject;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.repository.RepositorySystem;
import org.apache.maven.wagon.Wagon;
import org.codehaus.mojo.versions.api.ArtifactVersions;
import org.codehaus.mojo.versions.api.Segment;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.api.recording.ChangeRecorder;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.SegmentUtils;

import static org.apache.maven.shared.utils.StringUtils.isBlank;

/**
* Displays any updates of the project's parent project
Expand All @@ -46,6 +60,78 @@ public class DisplayParentUpdatesMojo extends AbstractVersionsDisplayMojo {

public static final int MESSAGE_LENGTH = 68;

// ------------------------------ FIELDS ------------------------------

/**
* <p>If {@code skipResolution} is not set, specifies the <em>bottom</em> version considered
* for target version resolution. If it is a version range, the resolved version will be
* restricted by that range.</p>
*
* <p>If {@code skipResolution} is {@code true}, will specify the target version to which
* the parent artifact will be updated.</p>
* @since 2.17.0
*/
@Parameter(property = "parentVersion")
protected String parentVersion = null;
slawekjaranowski marked this conversation as resolved.
Show resolved Hide resolved

/**
* to update parent version by force when it is RELEASE or LATEST
*
* @since 2.17.0
*/
@Parameter(property = "forceUpdate", defaultValue = "false")
protected boolean forceUpdate = false;

/**
* Skips version resolution, only valid if {@code parentVersion} is set.
* Will effectively set the new parent version to the one from {@code parentVersion}
*
* @since 2.17.0
*/
@Parameter(property = "skipResolution", defaultValue = "false")
protected boolean skipResolution = false;

/**
* <p>Whether to downgrade a snapshot dependency if <code>allowSnapshots</code> is <code>false</code>
* and there exists a version within the range fulfilling the criteria.</p>
* <p>Default <code>false</code></p>
*
* @since 2.17.0
*/
@Parameter(property = "allowDowngrade", defaultValue = "false")
protected boolean allowDowngrade;

/**
* Whether to allow the major version number to be changed.
*
* @since 2.17.0
*/
@Parameter(property = "allowMajorUpdates", defaultValue = "true")
protected boolean allowMajorUpdates = true;

/**
* <p>Whether to allow the minor version number to be changed.</p>
*
* <p><b>Note: {@code false} also implies {@linkplain #allowMajorUpdates} {@code false}</b></p>
*
* @since 2.17.0
*/
@Parameter(property = "allowMinorUpdates", defaultValue = "true")
protected boolean allowMinorUpdates = true;

/**
* <p>Whether to allow the incremental version number to be changed.</p>
*
* <p><b>Note: {@code false} also implies {@linkplain #allowMajorUpdates}
* and {@linkplain #allowMinorUpdates} {@code false}</b></p>
*
* @since 2.17.0
*/
@Parameter(property = "allowIncrementalUpdates", defaultValue = "true")
protected boolean allowIncrementalUpdates = true;

// -------------------------- OTHER METHODS --------------------------

@Inject
public DisplayParentUpdatesMojo(
RepositorySystem repositorySystem,
Expand All @@ -68,36 +154,34 @@ public void execute() throws MojoExecutionException, MojoFailureException {
return;
}

String currentVersion = getProject().getParent().getVersion();
Artifact artifact = getHelper()
.createDependencyArtifact(DependencyBuilder.newBuilder()
.withGroupId(getProject().getParent().getGroupId())
.withArtifactId(getProject().getParent().getArtifactId())
.withVersion(currentVersion)
.withType("pom")
.build());

if (skipResolution && isBlank(parentVersion)) {
throw new MojoExecutionException("skipResolution is only valid if parentVersion is set");
}
String initialVersion = Optional.ofNullable(parentVersion)
.orElse(getProject().getParent().getVersion());
ArtifactVersion artifactVersion;
try {
artifactVersion = findLatestVersion(artifact, null, allowSnapshots, false);
} catch (VersionRetrievalException e) {
artifactVersion = skipResolution
? DefaultArtifactVersionCache.of(parentVersion)
: resolveTargetVersion(initialVersion);
} catch (VersionRetrievalException | InvalidVersionSpecificationException | InvalidSegmentException e) {
throw new MojoExecutionException(e.getMessage(), e);
}

if (artifactVersion == null || currentVersion.equals(artifactVersion.toString())) {
if (artifactVersion == null || initialVersion.equals(artifactVersion.toString())) {
logLine(false, "The parent project is the latest version:");
StringBuilder buf = new StringBuilder(MESSAGE_LENGTH);
buf.append(" ");
buf.append(getProject().getParent().getGroupId());
buf.append(':');
buf.append(getProject().getParent().getArtifactId());
buf.append(' ');
int padding = MESSAGE_LENGTH - currentVersion.length();
int padding = MESSAGE_LENGTH - initialVersion.length();
while (buf.length() < padding) {
buf.append('.');
}
buf.append(' ');
buf.append(currentVersion);
buf.append(initialVersion);
logLine(false, buf.toString());
} else {
logLine(false, "The parent project has a newer version:");
Expand All @@ -108,20 +192,70 @@ public void execute() throws MojoExecutionException, MojoFailureException {
buf.append(getProject().getParent().getArtifactId());
buf.append(' ');
int padding = MESSAGE_LENGTH
- currentVersion.length()
- initialVersion.length()
- artifactVersion.toString().length()
- " -> ".length();
while (buf.length() < padding) {
buf.append('.');
}
buf.append(' ');
buf.append(currentVersion);
buf.append(initialVersion);
buf.append(" -> ");
buf.append(artifactVersion);
logLine(false, buf.toString());
}
}

protected ArtifactVersion resolveTargetVersion(String initialVersion)
throws MojoExecutionException, VersionRetrievalException, InvalidVersionSpecificationException,
InvalidSegmentException {
Artifact artifact = getHelper()
.createDependencyArtifact(DependencyBuilder.newBuilder()
.withGroupId(getProject().getParent().getGroupId())
.withArtifactId(getProject().getParent().getArtifactId())
.withVersion(initialVersion)
.withType("pom")
.build());

VersionRange targetVersionRange = VersionRange.createFromVersionSpec(initialVersion);
if (targetVersionRange.getRecommendedVersion() != null) {
targetVersionRange = targetVersionRange.restrict(
VersionRange.createFromVersionSpec("[" + targetVersionRange.getRecommendedVersion() + ",)"));
}

final ArtifactVersions versions = getHelper().lookupArtifactVersions(artifact, false);
Optional<Segment> unchangedSegment = SegmentUtils.determineUnchangedSegment(
allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog());

// currentVersion (set to parentVersion here) is not included in the version range for searching upgrades
// unless we set allowDowngrade to true
for (ArtifactVersion candidate : reverse(versions.getNewerVersions(
initialVersion, unchangedSegment, allowSnapshots, !isBlank(parentVersion) || allowDowngrade))) {
if (allowDowngrade
|| targetVersionRange == null
|| ArtifactVersions.isVersionInRange(candidate, targetVersionRange)) {
if (shouldApplyUpdate(artifact, getProject().getParent().getVersion(), candidate, forceUpdate)) {
return candidate;
} else {
getLog().debug("Update not applied. Exiting.");
return null;
}
}
}

if (versions.isEmpty(allowSnapshots)) {
getLog().info("No versions found");
} else {
getLog().info("The parent project is the latest version");
}

return null;
}

private static <T> Iterable<T> reverse(T[] array) {
return Arrays.stream(array).sorted(Collections.reverseOrder()).collect(Collectors.toList());
}

@Override
protected void update(ModifiedPomXMLEventReader pom) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.repository.RepositorySystem;
Expand All @@ -46,11 +45,9 @@
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;
import org.codehaus.mojo.versions.utils.DefaultArtifactVersionCache;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.SegmentUtils;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static org.apache.maven.shared.utils.StringUtils.isBlank;
import static org.codehaus.mojo.versions.api.Segment.*;

/**
* Sets the parent version to the latest parent version.
Expand Down Expand Up @@ -166,7 +163,8 @@ protected void update(ModifiedPomXMLEventReader pom)
throw new MojoExecutionException("skipResolution is only valid if parentVersion is set");
}

String initialVersion = parentVersion == null ? getProject().getParent().getVersion() : parentVersion;
String initialVersion = Optional.ofNullable(parentVersion)
.orElse(getProject().getParent().getVersion());
try {
ArtifactVersion artifactVersion = skipResolution
? DefaultArtifactVersionCache.of(parentVersion)
Expand Down Expand Up @@ -215,27 +213,8 @@ protected ArtifactVersion resolveTargetVersion(String initialVersion)
}

final ArtifactVersions versions = getHelper().lookupArtifactVersions(artifact, false);
Log log = getLog();
if (log != null && !allowIncrementalUpdates) {
log.info("Assuming allowMinorUpdates false because allowIncrementalUpdates is false.");
}

if (log != null && !allowMinorUpdates) {
log.info("Assuming allowMajorUpdates false because allowMinorUpdates is false.");
}

Optional<Segment> unchangedSegment1 = allowMajorUpdates && allowMinorUpdates && allowIncrementalUpdates
? empty()
: allowMinorUpdates && allowIncrementalUpdates
? of(MAJOR)
: allowIncrementalUpdates ? of(MINOR) : of(INCREMENTAL);
if (log != null && log.isDebugEnabled()) {
log.debug(unchangedSegment1
.map(Segment::minorTo)
.map(Segment::toString)
.orElse("ALL") + " version changes allowed");
}
Optional<Segment> unchangedSegment = unchangedSegment1;
Optional<Segment> unchangedSegment = SegmentUtils.determineUnchangedSegment(
allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog());

// currentVersion (set to parentVersion here) is not included in the version range for searching upgrades
// unless we set allowDowngrade to true
Expand Down
Loading