Merge pull request #108 from eric-milles/IVY-1662

IVY-1662: collect updates by conf and check transitive on old dependency
This commit is contained in:
Maarten Coene 2026-07-06 18:32:16 +02:00 committed by GitHub
commit 14dc81daa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 31 deletions

View File

@ -18,13 +18,16 @@
package org.apache.ivy.ant;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.ivy.core.module.descriptor.Configuration;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ConfigurationResolveReport;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.ResolveOptions;
@ -127,34 +130,43 @@ public class IvyDependencyUpdateChecker extends IvyPostResolveTask {
}
private void displayDependencyUpdates(ResolveReport originalReport, ResolveReport latestReport) {
log("Dependencies updates available :");
boolean dependencyUpdateDetected = false;
for (IvyNode latest : latestReport.getDependencies()) {
for (IvyNode originalDependency : originalReport.getDependencies()) {
if (latest.getModuleId().equals(originalDependency.getModuleId())) {
ArtifactInfo in1 = toArtifactInfo(latest);
ArtifactInfo in2 = toArtifactInfo(originalDependency);
ArtifactInfo out = getLatestStrategy(originalDependency).findLatest(new ArtifactInfo[]{in1, in2}, null);
if (out == in1) {
// is this dependency a transitive or a direct dependency?
// (unfortunately .isTransitive() methods do not have the same meaning)
boolean isTransitiveDependency = latest.getDependencyDescriptor(latest
.getRoot()) == null;
if (!isTransitiveDependency || showTransitive) {
log(String.format("\t%s#%s%s\t%s -> %s",
originalDependency.getResolvedId().getOrganisation(),
originalDependency.getResolvedId().getName(),
isTransitiveDependency ? " (transitive)" : "",
originalDependency.getResolvedId().getRevision(),
latest.getResolvedId().getRevision()));
dependencyUpdateDetected = true;
}
Set<String> updates = new LinkedHashSet<>();
for (String conf : latestReport.getConfigurations()) {
ConfigurationResolveReport newReport = latestReport.getConfigurationReport(conf);
ConfigurationResolveReport oldReport = originalReport.getConfigurationReport(conf);
// NOTE: getModuleRevisionIds() filters evicted and problem deps
for (ModuleRevisionId latest : newReport.getModuleRevisionIds()) {
Iterable<IvyNode> iter = oldReport.getNodes(latest.getModuleId());
if (iter == null) {
continue;
}
for (IvyNode node : iter) {
ArtifactInfo in1 = toArtifactInfo(latest.getRevision());
ArtifactInfo in2 = toArtifactInfo(node.getResolvedId().getRevision());
ArtifactInfo out = getLatestStrategy(node).findLatest(new ArtifactInfo[]{in1, in2}, null);
boolean revisionGT = (out == in1);
boolean transitive = (node.getDependencyDescriptor(node.getRoot()) == null);
if (revisionGT && (!transitive || showTransitive)) {
String update = String.format("\t%s#%s%s\t%s -> %s",
node.getResolvedId().getOrganisation(),
node.getResolvedId().getName(),
transitive ? " (transitive)" : "",
node.getResolvedId().getRevision(),
latest.getRevision());
updates.add(update);
}
}
}
}
if (!dependencyUpdateDetected) {
log("\tAll dependencies are up to date");
log("Dependencies updates available :");
if (updates.isEmpty()) {
log("All dependencies are up to date");
} else {
updates.forEach(this::log);
}
}
@ -211,15 +223,15 @@ public class IvyDependencyUpdateChecker extends IvyPostResolveTask {
return getSettings().getDefaultLatestStrategy();
}
private static ArtifactInfo toArtifactInfo(IvyNode node) {
private static ArtifactInfo toArtifactInfo(String revision) {
return new ArtifactInfo() {
@Override
public String getRevision() {
return node.getResolvedId().getRevision();
return revision;
}
@Override
public long getLastModified() {
return node.getLastModified();
return 0;
}
};
}

View File

@ -261,9 +261,11 @@ public class IvyDependencyUpdateCheckerTest extends AntTaskTestCase {
assertLogContaining("org1#mod1.2\t2.0 -> 2.2");
// ivy-extends-multiconf.xml declares org2:mod2.1:0.3
assertLogContaining("org2#mod2.1\t0.3 -> 0.7");
// org2:mod2.1:0.3 ivy.xml declares org1:mod1.1:1.0
assertLogContaining("org1#mod1.1\t1.0 -> 2.0");
// org1:mod1.1:2.0 ivy.xml declares org1:mod1.2:2.1
assertLogContaining("org1#mod1.2\t2.1 -> 2.2");
// org2:mod2.1:0.3 ivy.xml declares org1:mod1.1:1.0 -- but showTransitives is false
assertLogNotContaining("org1#mod1.1\t1.0 -> 2.0");
assertLogNotContaining("org1#mod1.1 (transitive)\t1.0 -> 2.0");
// org1:mod1.1:2.0 ivy.xml declares org1:mod1.2:2.1 -- it evicted direct dependency
assertLogNotContaining("org1#mod1.2\t2.1 -> 2.2");
assertLogNotContaining("org1#mod1.2 (transitive)\t2.1 -> 2.2");
}
}