Skip to content

Commit

Permalink
Resolves mojohaus#600: Add allowDowngrade capability to UseLatestRele…
Browse files Browse the repository at this point in the history
…asesMojo, UseNextReleasesMojo, UseNextVersionsMojo
  • Loading branch information
andrzejj0 committed Dec 27, 2022
1 parent 09ce5a2 commit 782c769
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ public class UseLatestReleasesMojo extends UseLatestVersionsMojoBase {
@Parameter(property = "allowIncrementalUpdates", defaultValue = "true")
protected boolean allowIncrementalUpdates = true;

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

// ------------------------------ METHODS --------------------------

@Inject
Expand Down Expand Up @@ -148,7 +158,8 @@ private void useLatestReleases(
(dep, versions) -> {
try {
return getLastFiltered(
versions.getNewerVersions(dep.getVersion(), unchangedSegment, false, false), dep);
versions.getNewerVersions(dep.getVersion(), unchangedSegment, false, allowDowngrade),
dep);
} catch (InvalidSegmentException e) {
getLog().warn(String.format(
"Skipping the processing of %s:%s:%s due to: %s",
Expand All @@ -157,7 +168,8 @@ private void useLatestReleases(
return empty();
},
changeKind,
dep -> !SNAPSHOT_REGEX.matcher(dep.getVersion()).matches());
dep -> allowDowngrade
|| !SNAPSHOT_REGEX.matcher(dep.getVersion()).matches());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,22 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;

import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
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.PomHelper;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.api.recording.ChangeRecord;
import org.codehaus.mojo.versions.api.recording.ChangeRecorder;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;

import static java.util.Collections.singletonList;
Expand All @@ -59,6 +62,16 @@ public class UseNextReleasesMojo extends UseLatestVersionsMojoBase {
*/
private static final Pattern MATCH_SNAPSHOT_REGEX = Pattern.compile("^(.+)-((SNAPSHOT)|(\\d{8}\\.\\d{6}-\\d+))$");

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

// ------------------------------ METHODS --------------------------

@Inject
Expand Down Expand Up @@ -107,8 +120,16 @@ private void useNextReleases(
useLatestVersions(
pom,
dependencies,
(dep, versions) -> of(versions.getNewerVersions(dep.getVersion(), false)[0]),
(dep, versions) -> {
try {
return of(versions.getNewerVersions(dep.getVersion(), Optional.empty(), false, allowDowngrade))
.map(v -> v.length > 0 ? v[0] : null);
} catch (InvalidSegmentException e) {
throw new RuntimeException(e);
}
},
changeKind,
dep -> !SNAPSHOT_REGEX.matcher(dep.getVersion()).matches());
dep -> allowDowngrade
|| !SNAPSHOT_REGEX.matcher(dep.getVersion()).matches());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,21 @@
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;

import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
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.PomHelper;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.api.recording.ChangeRecord;
import org.codehaus.mojo.versions.api.recording.ChangeRecorder;
import org.codehaus.mojo.versions.ordering.InvalidSegmentException;
import org.codehaus.mojo.versions.rewriting.ModifiedPomXMLEventReader;

import static java.util.Collections.singletonList;
Expand All @@ -51,6 +54,16 @@
@Mojo(name = "use-next-versions", threadSafe = true)
public class UseNextVersionsMojo extends UseLatestVersionsMojoBase {

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

// ------------------------------ METHODS --------------------------

@Inject
Expand Down Expand Up @@ -97,7 +110,15 @@ private void useNextVersions(
useLatestVersions(
pom,
dependencies,
(dep, versions) -> of(versions.getNewerVersions(dep.getVersion(), allowSnapshots)[0]),
(dep, versions) -> {
try {
return of(versions.getNewerVersions(
dep.getVersion(), Optional.empty(), allowSnapshots, allowDowngrade))
.map(v -> v.length > 0 ? v[0] : null);
} catch (InvalidSegmentException e) {
throw new RuntimeException(e);
}
},
changeKind);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.mojo.versions.api.PomHelper;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.change.DefaultVersionChange;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.TestChangeRecorder;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
Expand All @@ -28,7 +28,10 @@
import static org.codehaus.mojo.versions.utils.MockUtils.mockAetherRepositorySystem;
import static org.codehaus.mojo.versions.utils.MockUtils.mockMavenSession;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItem;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -113,6 +116,67 @@ public void testDontUpgradeToBeta()
.thenReturn(mojo.getProject().getModel());
mojo.update(null);
}
assertThat(changeRecorder.getChanges(), Matchers.empty());
assertThat(changeRecorder.getChanges(), empty());
}

@Test
public void testAllowDowngrade()
throws MojoExecutionException, XMLStreamException, MojoFailureException, VersionRetrievalException {
mojo.aetherRepositorySystem = mockAetherRepositorySystem(new HashMap<String, String[]>() {
{
put("artifactA", new String[] {"1.0.0", "1.0.1-SNAPSHOT"});
}
});
mojo.getProject()
.setDependencies(singletonList(DependencyBuilder.newBuilder()
.withGroupId("default-group")
.withArtifactId("artifactA")
.withVersion("1.0.1-SNAPSHOT")
.build()));
mojo.allowDowngrade = true;

try (MockedStatic<PomHelper> pomHelper = mockStatic(PomHelper.class)) {
pomHelper
.when(() -> PomHelper.setDependencyVersion(
any(), anyString(), anyString(), anyString(), anyString(), any(Model.class)))
.thenReturn(true);
pomHelper
.when(() -> PomHelper.getRawModel(any(MavenProject.class)))
.thenReturn(mojo.getProject().getModel());
mojo.update(null);
}
assertThat(
changeRecorder.getChanges(),
hasItem(new DefaultVersionChange(
"default-group", "artifactA",
"1.0.1-SNAPSHOT", "1.0.0")));
}

@Test
public void testDisallowDowngrade()
throws MojoExecutionException, XMLStreamException, MojoFailureException, VersionRetrievalException {
mojo.aetherRepositorySystem = mockAetherRepositorySystem(new HashMap<String, String[]>() {
{
put("artifactA", new String[] {"1.0.0", "1.0.1-SNAPSHOT"});
}
});
mojo.getProject()
.setDependencies(singletonList(DependencyBuilder.newBuilder()
.withGroupId("default-group")
.withArtifactId("artifactA")
.withVersion("1.0.1-SNAPSHOT")
.build()));

try (MockedStatic<PomHelper> pomHelper = mockStatic(PomHelper.class)) {
pomHelper
.when(() -> PomHelper.setDependencyVersion(
any(), anyString(), anyString(), anyString(), anyString(), any(Model.class)))
.thenReturn(true);
pomHelper
.when(() -> PomHelper.getRawModel(any(MavenProject.class)))
.thenReturn(mojo.getProject().getModel());
mojo.update(null);
}
assertThat(changeRecorder.getChanges(), empty());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.codehaus.mojo.versions;

import javax.xml.stream.XMLStreamException;

import java.util.HashMap;

import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.testing.stubs.DefaultArtifactHandlerStub;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.mojo.versions.api.PomHelper;
import org.codehaus.mojo.versions.api.VersionRetrievalException;
import org.codehaus.mojo.versions.change.DefaultVersionChange;
import org.codehaus.mojo.versions.utils.DependencyBuilder;
import org.codehaus.mojo.versions.utils.TestChangeRecorder;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;

import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE;
import static org.codehaus.mojo.versions.utils.MockUtils.mockAetherRepositorySystem;
import static org.codehaus.mojo.versions.utils.MockUtils.mockMavenSession;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItem;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

/**
* Unit test suite for {@link UseNextReleasesMojo}
*/
public class UseNextReleasesMojoTest {
private UseNextReleasesMojo mojo;
private TestChangeRecorder changeRecorder;

@Before
public void setUp() throws Exception {
RepositorySystem repositorySystemMock = mock(RepositorySystem.class);
when(repositorySystemMock.createDependencyArtifact(any(Dependency.class)))
.thenAnswer(invocation -> {
Dependency dependency = invocation.getArgument(0);
return new DefaultArtifact(
dependency.getGroupId(),
dependency.getArtifactId(),
dependency.getVersion(),
dependency.getScope(),
dependency.getType(),
dependency.getClassifier() != null ? dependency.getClassifier() : "default",
new DefaultArtifactHandlerStub("default"));
});

org.eclipse.aether.RepositorySystem aetherRepositorySystem = mockAetherRepositorySystem();

changeRecorder = new TestChangeRecorder();

mojo = new UseNextReleasesMojo(repositorySystemMock, aetherRepositorySystem, null, changeRecorder.asTestMap()) {
{
reactorProjects = emptyList();
MavenProject project = new MavenProject() {
{
setModel(new Model() {
{
setGroupId("default-group");
setArtifactId("project-artifact");
setVersion("1.0.0-SNAPSHOT");

setDependencies(singletonList(DependencyBuilder.newBuilder()
.withGroupId("default-group")
.withArtifactId("artifactA")
.withVersion("1.0.0")
.withScope(SCOPE_COMPILE)
.withType("jar")
.withClassifier("default")
.build()));
}
});
}
};
setProject(project);

session = mockMavenSession();
}
};
}

@Test
public void testAllowDowngrade()
throws MojoExecutionException, XMLStreamException, MojoFailureException, VersionRetrievalException {
mojo.aetherRepositorySystem = mockAetherRepositorySystem(new HashMap<String, String[]>() {
{
put("artifactA", new String[] {"1.0.0", "1.0.1-SNAPSHOT"});
}
});
mojo.getProject()
.setDependencies(singletonList(DependencyBuilder.newBuilder()
.withGroupId("default-group")
.withArtifactId("artifactA")
.withVersion("1.0.1-SNAPSHOT")
.build()));
mojo.allowDowngrade = true;

try (MockedStatic<PomHelper> pomHelper = mockStatic(PomHelper.class)) {
pomHelper
.when(() -> PomHelper.setDependencyVersion(
any(), anyString(), anyString(), anyString(), anyString(), any(Model.class)))
.thenReturn(true);
pomHelper
.when(() -> PomHelper.getRawModel(any(MavenProject.class)))
.thenReturn(mojo.getProject().getModel());
mojo.update(null);
}
assertThat(
changeRecorder.getChanges(),
hasItem(new DefaultVersionChange(
"default-group", "artifactA",
"1.0.1-SNAPSHOT", "1.0.0")));
}

@Test
public void testDisallowDowngrade()
throws MojoExecutionException, XMLStreamException, MojoFailureException, VersionRetrievalException {
mojo.aetherRepositorySystem = mockAetherRepositorySystem(new HashMap<String, String[]>() {
{
put("artifactA", new String[] {"1.0.0", "1.0.1-SNAPSHOT"});
}
});
mojo.getProject()
.setDependencies(singletonList(DependencyBuilder.newBuilder()
.withGroupId("default-group")
.withArtifactId("artifactA")
.withVersion("1.0.1-SNAPSHOT")
.build()));

try (MockedStatic<PomHelper> pomHelper = mockStatic(PomHelper.class)) {
pomHelper
.when(() -> PomHelper.setDependencyVersion(
any(), anyString(), anyString(), anyString(), anyString(), any(Model.class)))
.thenReturn(true);
pomHelper
.when(() -> PomHelper.getRawModel(any(MavenProject.class)))
.thenReturn(mojo.getProject().getModel());
mojo.update(null);
}
assertThat(changeRecorder.getChanges(), empty());
}
}
Loading

0 comments on commit 782c769

Please sign in to comment.