From 1aaa4dc30695dff36995372f3bdf0418d91019a4 Mon Sep 17 00:00:00 2001 From: "Andrzej J." Date: Fri, 15 Nov 2024 19:31:09 +0100 Subject: [PATCH] Fixed #1182: Bug fix (update scope determination) + slight refactoring --- .../versions/AbstractVersionsDisplayMojo.java | 103 ++++++++++ .../DisplayDependencyUpdatesMojo.java | 80 +------- .../versions/DisplayExtensionUpdatesMojo.java | 190 ++++++------------ .../DisplayExtensionUpdatesMojoTest.java | 77 +++++++ 4 files changed, 252 insertions(+), 198 deletions(-) diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java index 9e005a8b2d..f27ac402c7 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/AbstractVersionsDisplayMojo.java @@ -25,17 +25,29 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardOpenOption; +import java.util.ArrayList; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.apache.commons.lang3.StringUtils; +import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.Restriction; +import org.apache.maven.model.Dependency; import org.apache.maven.plugins.annotations.Parameter; 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.recording.ChangeRecorder; +import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.eclipse.aether.RepositorySystem; +import static java.util.Optional.empty; + /** * Abstract base class for the Display___ mojos. * @@ -46,6 +58,13 @@ public abstract class AbstractVersionsDisplayMojo extends AbstractVersionsUpdate private static final int DEFAULT_OUTPUT_LINE_WIDTH = 80; + /** + * The width to pad info messages. + * + * @since 1.0-alpha-1 + */ + static final int INFO_PAD_SIZE = 72; + /** * If specified then the display output will be sent to the specified file. * @@ -161,4 +180,88 @@ protected void logLine(boolean error, String line) { protected int getOutputLineWidthOffset() { return this.outputLineWidth - DEFAULT_OUTPUT_LINE_WIDTH; } + + /** + * Defines the list of dependencies using current versions and the list of dependencies having updates + */ + protected interface DependencyUpdatesResult { + + /** + * @return Dependencies using the latest version + */ + List getUsingLatest(); + + /** + * @return Dependencies with updates available + */ + List getWithUpdates(); + } + + /** + * Compiles a {@link DependencyUpdatesResult} object containing dependency updates for the given dependency map + * and the given unchanged segment. + * @param updates map of available versions per dependency + * @param unchangedSegment the most major segment not allowed to be updated or {@code Optional.empty()} if + * all segments are allowed to be updated + * @return a {@link DependencyUpdatesResult} object containing the result + */ + protected DependencyUpdatesResult getDependencyUpdates( + Map updates, Optional unchangedSegment) { + List withUpdates = new ArrayList<>(); + List usingCurrent = new ArrayList<>(); + for (ArtifactVersions versions : updates.values()) { + String left = " " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " "; + String currentVersion; + Optional latestVersion; + if (versions.getCurrentVersion() != null) { + currentVersion = versions.getCurrentVersion().toString(); + try { + latestVersion = versions.getNewestVersion(currentVersion, unchangedSegment, allowSnapshots, false); + } catch (InvalidSegmentException e) { + latestVersion = empty(); + } + } else { + currentVersion = versions.getArtifact().getVersionRange().toString(); + ArtifactVersion actualVersion = + versions.getNewestVersion(versions.getArtifact().getVersionRange(), allowSnapshots); + Restriction newVersionRestriction; + try { + Restriction segmentRestriction = + versions.restrictionForUnchangedSegment(actualVersion, unchangedSegment, false); + newVersionRestriction = new Restriction( + actualVersion, + false, + segmentRestriction.getUpperBound(), + segmentRestriction.isUpperBoundInclusive()); + } catch (InvalidSegmentException e) { + throw new RuntimeException(e); + } + latestVersion = Optional.of(newVersionRestriction) + .map(restriction -> versions.getNewestVersion(restriction, allowSnapshots)); + } + String right = + " " + latestVersion.map(v -> currentVersion + " -> " + v).orElse(currentVersion); + List t = latestVersion.isPresent() ? withUpdates : usingCurrent; + if (right.length() + left.length() + 3 > INFO_PAD_SIZE + getOutputLineWidthOffset()) { + t.add(left + "..."); + t.add(StringUtils.leftPad(right, INFO_PAD_SIZE + getOutputLineWidthOffset())); + + } else { + t.add(StringUtils.rightPad(left, INFO_PAD_SIZE + getOutputLineWidthOffset() - right.length(), ".") + + right); + } + } + + return new DependencyUpdatesResult() { + @Override + public List getUsingLatest() { + return usingCurrent; + } + + @Override + public List getWithUpdates() { + return withUpdates; + } + }; + } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java index f256b28de5..4a63bf5bf3 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayDependencyUpdatesMojo.java @@ -21,7 +21,6 @@ import javax.inject.Inject; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -30,10 +29,7 @@ import java.util.TreeSet; import org.apache.commons.lang3.StringUtils; -import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; -import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.artifact.versioning.Restriction; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -45,14 +41,12 @@ import org.codehaus.mojo.versions.api.VersionRetrievalException; import org.codehaus.mojo.versions.api.recording.ChangeRecorder; import org.codehaus.mojo.versions.filtering.WildcardMatcher; -import org.codehaus.mojo.versions.ordering.InvalidSegmentException; import org.codehaus.mojo.versions.rewriting.MutableXMLStreamReader; import org.codehaus.mojo.versions.utils.DependencyComparator; import org.codehaus.mojo.versions.utils.SegmentUtils; import org.eclipse.aether.RepositorySystem; import static java.util.Collections.emptySet; -import static java.util.Optional.empty; import static org.codehaus.mojo.versions.filtering.DependencyFilter.filterDependencies; import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromDependencyManagement; import static org.codehaus.mojo.versions.utils.MavenProjectUtils.extractDependenciesFromPlugins; @@ -71,13 +65,6 @@ public class DisplayDependencyUpdatesMojo extends AbstractVersionsDisplayMojo { // ------------------------------ FIELDS ------------------------------ - /** - * The width to pad info messages. - * - * @since 1.0-alpha-1 - */ - private static final int INFO_PAD_SIZE = 72; - /** * Whether to process the dependencyManagement section of the project. * @@ -503,79 +490,32 @@ static void validateGAVList(List gavList, int numSections, String argume } } - private void logUpdates(Map updates, String section) { - List withUpdates = new ArrayList<>(); - List usingCurrent = new ArrayList<>(); - for (ArtifactVersions versions : updates.values()) { - String left = " " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " "; - String currentVersion; - Optional latestVersion; - Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( - allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); - if (versions.getCurrentVersion() != null) { - currentVersion = versions.getCurrentVersion().toString(); - try { - latestVersion = versions.getNewestVersion(currentVersion, unchangedSegment, allowSnapshots, false); - } catch (InvalidSegmentException e) { - latestVersion = empty(); - } - } else { - currentVersion = versions.getArtifact().getVersionRange().toString(); - ArtifactVersion actualVersion = - versions.getNewestVersion(versions.getArtifact().getVersionRange(), allowSnapshots); - Restriction newVersionRestriction; - try { - Restriction segmentRestriction = - versions.restrictionForUnchangedSegment(actualVersion, unchangedSegment, false); - newVersionRestriction = new Restriction( - actualVersion, - false, - segmentRestriction.getUpperBound(), - segmentRestriction.isUpperBoundInclusive()); - } catch (InvalidSegmentException e) { - throw new RuntimeException(e); - } - latestVersion = Optional.of(newVersionRestriction) - .map(restriction -> versions.getNewestVersion(restriction, allowSnapshots)); - } - String right = - " " + latestVersion.map(v -> currentVersion + " -> " + v).orElse(currentVersion); - List t = latestVersion.isPresent() ? withUpdates : usingCurrent; - if (right.length() + left.length() + 3 > INFO_PAD_SIZE + getOutputLineWidthOffset()) { - t.add(left + "..."); - t.add(StringUtils.leftPad(right, INFO_PAD_SIZE + getOutputLineWidthOffset())); - - } else { - t.add(StringUtils.rightPad(left, INFO_PAD_SIZE + getOutputLineWidthOffset() - right.length(), ".") - + right); - } - } + private void logUpdates(Map versionMap, String section) { + Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( + allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); + DependencyUpdatesResult updates = getDependencyUpdates(versionMap, unchangedSegment); if (isVerbose()) { - if (usingCurrent.isEmpty()) { - if (!withUpdates.isEmpty()) { + if (updates.getUsingLatest().isEmpty()) { + if (!updates.getWithUpdates().isEmpty()) { logLine(false, "No dependencies in " + section + " are using the newest version."); logLine(false, ""); } } else { logLine(false, "The following dependencies in " + section + " are using the newest version:"); - for (String s : usingCurrent) { - logLine(false, s); - } + updates.getUsingLatest().forEach(s -> logLine(false, s)); logLine(false, ""); } } - if (withUpdates.isEmpty()) { - if (!usingCurrent.isEmpty()) { + if (updates.getWithUpdates().isEmpty()) { + if (!updates.getUsingLatest().isEmpty()) { logLine(false, "No dependencies in " + section + " have newer versions."); logLine(false, ""); } } else { logLine(false, "The following dependencies in " + section + " have newer versions:"); - for (String withUpdate : withUpdates) { - logLine(false, withUpdate); - } + updates.getWithUpdates().forEach(s -> logLine(false, s)); logLine(false, ""); } } diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java index 503b04be78..57bd527115 100644 --- a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojo.java @@ -20,21 +20,17 @@ import javax.xml.transform.TransformerException; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.lang3.StringUtils; -import org.apache.maven.artifact.ArtifactUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; -import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.Extension; @@ -59,8 +55,7 @@ import org.codehaus.mojo.versions.utils.SegmentUtils; import org.eclipse.aether.RepositorySystem; -import static java.util.Optional.of; -import static org.codehaus.mojo.versions.api.Segment.MAJOR; +import static java.util.Optional.ofNullable; /** * Displays all build and core extensions that have newer versions available. @@ -73,20 +68,11 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { // ------------------------------ FIELDS ------------------------------ - /** - * The width to pad info messages. - * - * @since 1.0-alpha-1 - */ - private static final int INFO_PAD_SIZE = 72; - /** *

Specifies a comma-separated list of GAV patterns to consider * when looking for updates. If the trailing parts of the GAV are omitted, then can assume any value.

- * *

The wildcard "*" can be used as the only, first, last or both characters in each token. * The version token does support version ranges.

- * * Examples: {@code "mygroup:artifact:*"}, {@code "mygroup:artifact"}, {@code "mygroup"} * * @since 2.15.0 @@ -97,12 +83,9 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { /** *

Specifies a comma-separated list of GAV patterns to NOT consider * when looking for updates. If the trailing parts of the GAV are omitted, then can assume any value.

- * *

This list is taken into account after {@link #extensionIncludes}

. - * *

The wildcard "*" can be used as the only, first, last or both characters in each token. * The version token does support version ranges.

- * * Examples: {@code "mygroup:artifact:*"}, {@code "mygroup:artifact"}, {@code "mygroup"} * * @since 2.15.0 @@ -120,7 +103,6 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { /** *

Whether to allow the minor version number to be changed.

- * *

Note: {@code false} also implies {@linkplain #allowMajorUpdates} * to be {@code false}

* @@ -131,7 +113,6 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { /** *

Whether to allow the incremental version number to be changed.

- * *

Note: {@code false} also implies {@linkplain #allowMajorUpdates} * and {@linkplain #allowMinorUpdates} to be {@code false}

* @@ -142,6 +123,7 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { /** *

Whether to process core extensions. Default is {@code true}.

+ * * @since 2.15.0 */ @Parameter(property = "processCoreExtensions", defaultValue = "true") @@ -149,6 +131,7 @@ public class DisplayExtensionUpdatesMojo extends AbstractVersionsDisplayMojo { /** *

Whether to process build extensions. Default is {@code true}.

+ * * @since 2.15.0 */ @Parameter(property = "processBuildExtensions", defaultValue = "true") @@ -193,56 +176,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { DependencyFilter includeFilter = DependencyFilter.parseFrom(extensionIncludes); DependencyFilter excludeFilter = DependencyFilter.parseFrom(extensionExcludes); - Set dependencies; try { - Stream extensions; - if (processCoreExtensions) { - extensions = CoreExtensionUtils.getCoreExtensions(project); - } else { - extensions = Stream.empty(); - } - if (processBuildExtensions) { - if (!interpolateProperties) { - extensions = Stream.concat( - extensions, - PomHelper.getChildModels(session.getCurrentProject(), getLog()).values().stream() - .map(Model::getBuild) - .filter(Objects::nonNull) - .map(Build::getExtensions) - .map(List::stream) - .reduce(Stream::concat) - .orElse(Stream.empty())); - } else { - List rawModels = getRawModels(); - for (ModelNode node : rawModels) { - if (node.getModel() == null) { - // unlikely - continue; - } - Map properties = new HashMap<>(); - for (ModelNode p = node; p != null; p = p.getParent().orElse(null)) { - p.getModel() - .getProperties() - .forEach((key, value) -> - properties.putIfAbsent(String.valueOf(key), String.valueOf(value))); - } - extensions = Stream.concat( - extensions, - Optional.ofNullable(node.getModel().getBuild()) - .map(Build::getExtensions) - .orElse(Collections.emptyList()) - .stream() - .map(e -> ExtensionBuilder.newBuilder() - .withGroupId(PomHelper.evaluate(e.getGroupId(), properties, getLog())) - .withArtifactId( - PomHelper.evaluate(e.getArtifactId(), properties, getLog())) - .withVersion(PomHelper.evaluate(e.getVersion(), properties, getLog())) - .build())); - } - } - } + Stream coreExtensions = + processCoreExtensions ? CoreExtensionUtils.getCoreExtensions(project) : Stream.empty(); + Stream buildExtensions = processBuildExtensions ? getBuildExtensions() : Stream.empty(); - dependencies = extensions + Collection dependencies = Stream.concat(coreExtensions, buildExtensions) .map(e -> DependencyBuilder.newBuilder() .withGroupId(e.getGroupId()) .withArtifactId(e.getArtifactId()) @@ -251,19 +190,55 @@ public void execute() throws MojoExecutionException, MojoFailureException { .filter(includeFilter::matchersMatch) .filter(excludeFilter::matchersDontMatch) .collect(Collectors.toSet()); + + if (dependencies.isEmpty()) { + getLog().info("Extensions set filtered by include- and exclude-filters is empty. Nothing to do."); + return; + } + + logUpdates(getHelper().lookupDependenciesUpdates(dependencies.stream(), true, true, allowSnapshots)); } catch (IOException | XMLStreamException e) { throw new MojoExecutionException(e.getMessage()); + } catch (VersionRetrievalException e) { + throw new MojoExecutionException(e.getMessage(), e); } - if (dependencies.isEmpty()) { - getLog().info("Extensions set filtered by include- and exclude-filters is empty. Nothing to do."); - return; + } + + private Stream getBuildExtensions() throws IOException, MojoFailureException { + if (!interpolateProperties) { + return PomHelper.getChildModels(getProject(), getLog()).values().stream() + .map(Model::getBuild) + .filter(Objects::nonNull) + .map(Build::getExtensions) + .map(List::stream) + .reduce(Stream::concat) + .orElse(Stream.empty()); + } else { + return getRawModels().stream() + .filter(node -> Objects.nonNull(node.getModel())) + .filter(node -> ofNullable(node.getModel().getBuild()) + .map(Build::getExtensions) + .map(list -> !list.isEmpty()) + .orElse(false)) + .map(node -> Pair.of(node.getModel().getBuild().getExtensions(), getNodeProperties(node))) + .flatMap(pair -> pair.getLeft().stream().map(e -> Pair.of(e, pair.getRight()))) + .map(pair -> ExtensionBuilder.newBuilder() + .withGroupId(PomHelper.evaluate(pair.getLeft().getGroupId(), pair.getRight(), getLog())) + .withArtifactId( + PomHelper.evaluate(pair.getLeft().getArtifactId(), pair.getRight(), getLog())) + .withVersion(PomHelper.evaluate(pair.getLeft().getVersion(), pair.getRight(), getLog())) + .build()); } + } - try { - logUpdates(getHelper().lookupDependenciesUpdates(dependencies.stream(), true, true, allowSnapshots)); - } catch (VersionRetrievalException e) { - throw new MojoExecutionException(e.getMessage(), e); + private static Map getNodeProperties(ModelNode node) { + Map properties = new HashMap<>(); + for (ModelNode p = node; p != null; p = p.getParent().orElse(null)) { + p.getModel() + .getProperties() + .forEach((key, value) -> properties.putIfAbsent(String.valueOf(key), String.valueOf(value))); } + return properties; } private List getRawModels() throws MojoFailureException { @@ -280,73 +255,32 @@ private List getRawModels() throws MojoFailureException { return rawModels; } - private Optional calculateUpdateScope() { - return of(SegmentUtils.determineUnchangedSegment( - allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()) - .map(Segment::minorTo) - .orElse(MAJOR)); - } - - private void logUpdates(Map updates) { - List withUpdates = new ArrayList<>(); - List usingCurrent = new ArrayList<>(); - for (ArtifactVersions versions : updates.values()) { - String left = " " + ArtifactUtils.versionlessKey(versions.getArtifact()) + " "; - final String current; - ArtifactVersion latest; - if (versions.getCurrentVersion() != null) { - current = versions.getCurrentVersion().toString(); - latest = versions.getNewestUpdateWithinSegment(calculateUpdateScope(), allowSnapshots); - } else { - ArtifactVersion newestVersion = - versions.getNewestVersion(versions.getArtifact().getVersionRange(), allowSnapshots); - current = versions.getArtifact().getVersionRange().toString(); - latest = newestVersion == null - ? null - : versions.getNewestUpdateWithinSegment(newestVersion, calculateUpdateScope(), allowSnapshots); - if (latest != null - && ArtifactVersions.isVersionInRange( - latest, versions.getArtifact().getVersionRange())) { - latest = null; - } - } - String right = " " + (latest == null ? current : current + " -> " + latest); - List t = latest == null ? usingCurrent : withUpdates; - if (right.length() + left.length() + 3 > INFO_PAD_SIZE + getOutputLineWidthOffset()) { - t.add(left + "..."); - t.add(StringUtils.leftPad(right, INFO_PAD_SIZE + getOutputLineWidthOffset())); - - } else { - t.add(StringUtils.rightPad(left, INFO_PAD_SIZE + getOutputLineWidthOffset() - right.length(), ".") - + right); - } - } + private void logUpdates(Map versionMap) { + Optional unchangedSegment = SegmentUtils.determineUnchangedSegment( + allowMajorUpdates, allowMinorUpdates, allowIncrementalUpdates, getLog()); + DependencyUpdatesResult updates = getDependencyUpdates(versionMap, unchangedSegment); if (verbose) { - if (usingCurrent.isEmpty()) { - if (!withUpdates.isEmpty()) { + if (updates.getUsingLatest().isEmpty()) { + if (!updates.getWithUpdates().isEmpty()) { logLine(false, "No extensions are using the newest version."); logLine(false, ""); } } else { logLine(false, "The following extensions are using the newest version:"); - for (String s : usingCurrent) { - logLine(false, s); - } + updates.getUsingLatest().forEach(s -> logLine(false, s)); logLine(false, ""); } } - if (withUpdates.isEmpty()) { - if (!usingCurrent.isEmpty()) { + if (updates.getWithUpdates().isEmpty()) { + if (!updates.getUsingLatest().isEmpty()) { logLine(false, "No extensions have newer versions."); logLine(false, ""); } } else { logLine(false, "The following extensions have newer versions:"); - for (String withUpdate : withUpdates) { - logLine(false, withUpdate); - } + updates.getWithUpdates().forEach(s -> logLine(false, s)); logLine(false, ""); } } diff --git a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java index ed5ecfc686..17a6bafc68 100644 --- a/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java +++ b/versions-maven-plugin/src/test/java/org/codehaus/mojo/versions/DisplayExtensionUpdatesMojoTest.java @@ -181,4 +181,81 @@ public void testIncludesExcludesMakesSetEmpty() assertThat(Files.readAllLines(tempPath), empty()); } + + @Test + public void testMajorUpdates() + throws MojoExecutionException, MojoFailureException, IOException, IllegalAccessException { + setVariableValueToObject(mojo, "extensionExcludes", emptyList()); + setVariableValueToObject(mojo, "extensionIncludes", singletonList("*")); + mojo.getProject().setBuild(new Build()); + mojo.getProject() + .getBuild() + .setExtensions(Collections.singletonList(ExtensionBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("artifactA") + .withVersion("1.0.0") + .build())); + + try (MockedStatic pomHelper = mockStatic(PomHelper.class)) { + pomHelper + .when(() -> PomHelper.getChildModels(ArgumentMatchers.any(MavenProject.class), any())) + .then(i -> Collections.singletonMap(null, ((MavenProject) i.getArgument(0)).getModel())); + mojo.execute(); + } + + assertThat(String.join("", Files.readAllLines(tempPath)), containsString("1.0.0 -> 2.0.0")); + } + + @Test + public void testMinorUpdates() + throws MojoExecutionException, MojoFailureException, IOException, IllegalAccessException { + setVariableValueToObject(mojo, "extensionExcludes", emptyList()); + setVariableValueToObject(mojo, "extensionIncludes", singletonList("*")); + mojo.getProject().setBuild(new Build()); + mojo.getProject() + .getBuild() + .setExtensions(Collections.singletonList(ExtensionBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("artifactB") + .withVersion("1.0.0") + .build())); + + try (MockedStatic pomHelper = mockStatic(PomHelper.class)) { + pomHelper + .when(() -> PomHelper.getChildModels(ArgumentMatchers.any(MavenProject.class), any())) + .then(i -> Collections.singletonMap(null, ((MavenProject) i.getArgument(0)).getModel())); + mojo.execute(); + } + + assertThat(String.join("", Files.readAllLines(tempPath)), containsString("1.0.0 -> 1.1.0")); + } + + @Test + public void testIncrementalUpdates() + throws MojoExecutionException, MojoFailureException, IOException, IllegalAccessException { + setVariableValueToObject(mojo, "extensionExcludes", emptyList()); + setVariableValueToObject(mojo, "extensionIncludes", singletonList("*")); + mojo.getProject().setBuild(new Build()); + mojo.getProject() + .getBuild() + .setExtensions(Collections.singletonList(ExtensionBuilder.newBuilder() + .withGroupId("default-group") + .withArtifactId("artifactD") + .withVersion("1.0.0") + .build())); + mojo.repositorySystem = mockAetherRepositorySystem(new HashMap() { + { + put("artifactD", new String[] {"1.0.0", "1.0.1"}); + } + }); + + try (MockedStatic pomHelper = mockStatic(PomHelper.class)) { + pomHelper + .when(() -> PomHelper.getChildModels(ArgumentMatchers.any(MavenProject.class), any())) + .then(i -> Collections.singletonMap(null, ((MavenProject) i.getArgument(0)).getModel())); + mojo.execute(); + } + + assertThat(String.join("", Files.readAllLines(tempPath)), containsString("1.0.0 -> 1.0.1")); + } }