From c6ae2533d5230796ec503d1b8708d243ebc45999 Mon Sep 17 00:00:00 2001 From: twogee Date: Thu, 1 Feb 2018 14:54:30 +0100 Subject: [PATCH] IVY-1485 Ensure dependency is applicable to all configurations --- asciidoc/release-notes.adoc | 1 + .../org/apache/ivy/core/resolve/IvyNode.java | 2 +- .../ivy/core/resolve/ResolveEngine.java | 21 +- .../apache/ivy/core/resolve/ResolveTest.java | 191 ++++++++++++++++++ .../IVY-1485/ivy-overlap-transitive-newer.xml | 32 +++ .../IVY-1485/ivy-overlap-transitive-older.xml | 32 +++ test/repositories/IVY-1485/ivy-simple.xml | 31 +++ test/repositories/IVY-1485/ivysettings.xml | 27 +++ .../IVY-1485/overlap-newer/modA/1/ivy.xml | 26 +++ .../IVY-1485/overlap-newer/modA/5/ivy.xml | 26 +++ .../IVY-1485/overlap-newer/modB/1/ivy.xml | 29 +++ .../IVY-1485/overlap-older/modA/1/ivy.xml | 26 +++ .../IVY-1485/overlap-older/modA/5/ivy.xml | 26 +++ .../IVY-1485/overlap-older/modB/1/ivy.xml | 29 +++ .../IVY-1485/simple/modA/1/ivy.xml | 26 +++ .../IVY-1485/simple/modA/5/ivy.xml | 26 +++ .../IVY-1485/simple/modB/1/ivy.xml | 29 +++ 17 files changed, 577 insertions(+), 3 deletions(-) create mode 100644 test/repositories/IVY-1485/ivy-overlap-transitive-newer.xml create mode 100644 test/repositories/IVY-1485/ivy-overlap-transitive-older.xml create mode 100644 test/repositories/IVY-1485/ivy-simple.xml create mode 100644 test/repositories/IVY-1485/ivysettings.xml create mode 100644 test/repositories/IVY-1485/overlap-newer/modA/1/ivy.xml create mode 100644 test/repositories/IVY-1485/overlap-newer/modA/5/ivy.xml create mode 100644 test/repositories/IVY-1485/overlap-newer/modB/1/ivy.xml create mode 100644 test/repositories/IVY-1485/overlap-older/modA/1/ivy.xml create mode 100644 test/repositories/IVY-1485/overlap-older/modA/5/ivy.xml create mode 100644 test/repositories/IVY-1485/overlap-older/modB/1/ivy.xml create mode 100644 test/repositories/IVY-1485/simple/modA/1/ivy.xml create mode 100644 test/repositories/IVY-1485/simple/modA/5/ivy.xml create mode 100644 test/repositories/IVY-1485/simple/modB/1/ivy.xml diff --git a/asciidoc/release-notes.adoc b/asciidoc/release-notes.adoc index 38ca44bd..776a8e2d 100644 --- a/asciidoc/release-notes.adoc +++ b/asciidoc/release-notes.adoc @@ -122,6 +122,7 @@ Here is the list of people who have contributed source code and documentation up * Stéphane Bailliez * Karl Baum * Andrew Bernhagen +* Timothy Bingaman * Mikkel Bjerg * Per Arnold Blaasmo * Jeffrey Blattman diff --git a/src/java/org/apache/ivy/core/resolve/IvyNode.java b/src/java/org/apache/ivy/core/resolve/IvyNode.java index 82110213..6bb51b02 100644 --- a/src/java/org/apache/ivy/core/resolve/IvyNode.java +++ b/src/java/org/apache/ivy/core/resolve/IvyNode.java @@ -438,7 +438,7 @@ public class IvyNode implements Comparable { return loadedRootModuleConfs.add(rootModuleConf); } - private boolean isRootModuleConfLoaded(String rootModuleConf) { + public boolean isRootModuleConfLoaded(String rootModuleConf) { return loadedRootModuleConfs.contains(rootModuleConf); } diff --git a/src/java/org/apache/ivy/core/resolve/ResolveEngine.java b/src/java/org/apache/ivy/core/resolve/ResolveEngine.java index 3d538aee..eaf26b6e 100644 --- a/src/java/org/apache/ivy/core/resolve/ResolveEngine.java +++ b/src/java/org/apache/ivy/core/resolve/ResolveEngine.java @@ -67,6 +67,7 @@ import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry; import org.apache.ivy.plugins.repository.url.URLResource; import org.apache.ivy.plugins.resolver.DependencyResolver; import org.apache.ivy.plugins.version.VersionMatcher; +import org.apache.ivy.util.ConfigurationUtils; import org.apache.ivy.util.Message; import org.apache.ivy.util.filter.Filter; @@ -329,11 +330,27 @@ public class ResolveEngine { String forcedRev = forcedRevisionId == null ? rev : forcedRevisionId .getRevision(); + String[] moduleConfigurations = ConfigurationUtils.replaceWildcards( + dd.getModuleConfigurations(), md); + boolean dependencyConfApplicableToAllTopLevelDepConfs = true; + for (String moduleConfiguration : moduleConfigurations) { + if (!dependency.isRootModuleConfLoaded(moduleConfiguration)) { + dependencyConfApplicableToAllTopLevelDepConfs = false; + break; + } + } + // The evicted modules have no description, so we can't put the status String status = depDescriptor == null ? "?" : depDescriptor.getStatus(); Message.debug("storing dependency " + depResolvedId + " in props"); - props.put(depRevisionId.encodeToString(), rev + " " + status + " " - + forcedRev + " " + depResolvedId.getBranch()); + String depRevisionIdString = depRevisionId.encodeToString(); + // don't replace a dep revision we've already added unless it is + // applicable to all the confs of the matching top-level dep. + if (!props.containsKey(depRevisionIdString) + || dependencyConfApplicableToAllTopLevelDepConfs) { + props.put(depRevisionIdString, rev + " " + status + " " + forcedRev + + " " + depResolvedId.getBranch()); + } } } } diff --git a/test/java/org/apache/ivy/core/resolve/ResolveTest.java b/test/java/org/apache/ivy/core/resolve/ResolveTest.java index a41f91f1..e9153030 100644 --- a/test/java/org/apache/ivy/core/resolve/ResolveTest.java +++ b/test/java/org/apache/ivy/core/resolve/ResolveTest.java @@ -2312,6 +2312,197 @@ public class ResolveTest { assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists()); } + /** + * Test case for IVY-1485. + * + * @throws Exception if something goes wrong + * @see IVY-1485 + */ + @Test + public void testDeliverWithTransitiveDepsInDifferentConfs() throws Exception { + ivy = Ivy.newInstance(); + ivy.configure(new File("test/repositories/IVY-1485/ivysettings.xml")); + + ResolveOptions opts = new ResolveOptions(); + opts.setConfs(new String[] {"*"}); + opts.setResolveId("resolveid"); + opts.setTransitive(true); + + ResolveReport report = ivy.resolve( + new File("test/repositories/IVY-1485/ivy-simple.xml").toURI().toURL(), opts); + assertFalse(report.hasError()); + + ModuleRevisionId modAExpectedRevId = ModuleRevisionId.newInstance("simple", "modA", "5"); + + // check that the resolve report has the expected results, namely that the transitive dep on modA#1 has not + // overridden the direct dep on modA#5. This is about testing the consistency of results between the resolve + // report and the delivered descriptor. + + Set reportMrids = report.getConfigurationReport("conf1").getModuleRevisionIds(); + assertEquals(new HashSet<>(Collections.singletonList(modAExpectedRevId)), reportMrids); + + DeliverOptions dopts = new DeliverOptions(); + dopts.setGenerateRevConstraint(true); + dopts.setConfs(new String[] { "*" }); + dopts.setStatus("release"); + dopts.setPubdate(new Date()); + dopts.setResolveId("resolveid"); + String pubrev = "1"; + String deliveryPattern = "build/test/deliver/assembly-[revision].xml"; + + ivy.deliver(pubrev, deliveryPattern, dopts); + + // now check that the resolve report has the same info as the delivered descriptor + + File deliveredIvyFile = new File("build/test/deliver/assembly-1.xml"); + assertTrue(deliveredIvyFile.exists()); + ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor( + ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false); + DependencyDescriptor[] dds = md.getDependencies(); + assertEquals(2, dds.length); + assertEquals(ModuleRevisionId.newInstance("simple", "modB", "1"), dds[1].getDependencyRevisionId()); + assertEquals(ModuleRevisionId.newInstance("simple", "modA", "5"), dds[0].getDependencyRevisionId()); + } + + /** + * Test case for IVY-1485. + * + * @throws Exception if something goes wrong + * @see IVY-1485 + */ + @Test + public void testDeliverWithTransitiveDepsInOverlappingConfsTransitiveNewer() throws Exception { + ivy = Ivy.newInstance(); + ivy.configure(new File("test/repositories/IVY-1485/ivysettings.xml")); + + ResolveOptions opts = new ResolveOptions(); + opts.setConfs(new String[] {"*"}); + opts.setResolveId("resolveid"); + opts.setTransitive(true); + + ResolveReport report = ivy.resolve( + new File("test/repositories/IVY-1485/ivy-overlap-transitive-newer.xml").toURI().toURL(), opts); + assertFalse(report.hasError()); + + ModuleRevisionId conf1ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-newer", "modA", "1"); + ModuleRevisionId conf2ModBExpectedRevId = ModuleRevisionId.newInstance("overlap-newer", "modB", "1"); + ModuleRevisionId conf2ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-newer", "modA", "5"); + ModuleRevisionId conf3ModBExpectedRevId = ModuleRevisionId.newInstance("overlap-newer", "modB", "1"); + ModuleRevisionId conf3ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-newer", "modA", "5"); + + Set conf1ReportMrids = report.getConfigurationReport("conf1").getModuleRevisionIds(); + assertEquals(new HashSet<>(Collections.singletonList(conf1ModAExpectedRevId)), conf1ReportMrids); + Set conf2ReportMrids = report.getConfigurationReport("conf2").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf2ModBExpectedRevId, conf2ModAExpectedRevId)), + conf2ReportMrids); + Set conf3ReportMrids = report.getConfigurationReport("conf3").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf3ModBExpectedRevId, conf3ModAExpectedRevId)), + conf3ReportMrids); + + DeliverOptions dopts = new DeliverOptions(); + dopts.setGenerateRevConstraint(true); + dopts.setConfs(new String[] { "*" }); + dopts.setStatus("release"); + dopts.setPubdate(new Date()); + dopts.setResolveId("resolveid"); + String pubrev = "1"; + String deliveryPattern = "build/test/deliver/assembly-[revision].xml"; + + ivy.deliver(pubrev, deliveryPattern, dopts); + + // now check that the resolve report has the same info as the delivered descriptor + + File deliveredIvyFile = new File("build/test/deliver/assembly-1.xml"); + assertTrue(deliveredIvyFile.exists()); + + ResolveReport report2 = ivy.resolve(deliveredIvyFile.toURI().toURL(), opts); + assertFalse(report.hasError()); + + Set conf1ReportMrids2 = report2.getConfigurationReport("conf1").getModuleRevisionIds(); + assertEquals(new HashSet<>(Collections.singletonList(conf1ModAExpectedRevId)), conf1ReportMrids2); + Set conf2ReportMrids2 = report2.getConfigurationReport("conf2").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf2ModBExpectedRevId, conf2ModAExpectedRevId)), + conf2ReportMrids2); + Set conf3ReportMrids2 = report2.getConfigurationReport("conf3").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf3ModBExpectedRevId, conf3ModAExpectedRevId)), + conf3ReportMrids2); + + ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor( + ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false); + DependencyDescriptor[] dds = md.getDependencies(); + assertEquals(2, dds.length); + assertEquals(ModuleRevisionId.newInstance("overlap-newer", "modA", "1"), dds[0].getDependencyRevisionId()); + assertEquals(ModuleRevisionId.newInstance("overlap-newer", "modB", "1"), dds[1].getDependencyRevisionId()); + } + + /** + * Test case for IVY-1485. + * + * @throws Exception if something goes wrong + * @see IVY-1485 + */ + @Test + public void testDeliverWithTransitiveDepsInOverlappingConfsTransitiveOlder() throws Exception { + ivy = Ivy.newInstance(); + ivy.configure(new File("test/repositories/IVY-1485/ivysettings.xml")); + + ResolveOptions opts = new ResolveOptions(); + opts.setConfs(new String[] {"*"}); + opts.setResolveId("resolveid"); + opts.setTransitive(true); + + ResolveReport report = ivy.resolve( + new File("test/repositories/IVY-1485/ivy-overlap-transitive-older.xml").toURI().toURL(), opts); + assertFalse(report.hasError()); + + ModuleRevisionId conf1ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-older", "modA", "5"); + ModuleRevisionId conf2ModBExpectedRevId = ModuleRevisionId.newInstance("overlap-older", "modB", "1"); + ModuleRevisionId conf2ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-older", "modA", "5"); + ModuleRevisionId conf3ModBExpectedRevId = ModuleRevisionId.newInstance("overlap-older", "modB", "1"); + ModuleRevisionId conf3ModAExpectedRevId = ModuleRevisionId.newInstance("overlap-older", "modA", "1"); + + Set conf1ReportMrids = report.getConfigurationReport("conf1").getModuleRevisionIds(); + assertEquals(new HashSet<>(Collections.singletonList(conf1ModAExpectedRevId)), conf1ReportMrids); + Set conf2ReportMrids = report.getConfigurationReport("conf2").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf2ModBExpectedRevId, conf2ModAExpectedRevId)), + conf2ReportMrids); + Set conf3ReportMrids = report.getConfigurationReport("conf3").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf3ModBExpectedRevId, conf3ModAExpectedRevId)), + conf3ReportMrids); + + DeliverOptions dopts = new DeliverOptions(); + dopts.setGenerateRevConstraint(true); + dopts.setConfs(new String[] { "*" }); + dopts.setStatus("release"); + dopts.setPubdate(new Date()); + dopts.setResolveId("resolveid"); + String pubrev = "1"; + String deliveryPattern = "build/test/deliver/assembly-[revision].xml"; + + ivy.deliver(pubrev, deliveryPattern, dopts); + + // now check that the resolve report has the same info as the delivered descriptor + + File deliveredIvyFile = new File("build/test/deliver/assembly-1.xml"); + assertTrue(deliveredIvyFile.exists()); + + ResolveReport report2 = ivy.resolve(deliveredIvyFile.toURI().toURL(), opts); + assertFalse(report.hasError()); + + Set conf1ReportMrids2 = report2.getConfigurationReport("conf1").getModuleRevisionIds(); + assertEquals(new HashSet<>(Collections.singletonList(conf1ModAExpectedRevId)), conf1ReportMrids2); + Set conf2ReportMrids2 = report2.getConfigurationReport("conf2").getModuleRevisionIds(); + assertEquals(new HashSet<>(Arrays.asList(conf2ModBExpectedRevId, conf2ModAExpectedRevId)), + conf2ReportMrids2); + + ModuleDescriptor md = XmlModuleDescriptorParser.getInstance().parseDescriptor( + ivy.getSettings(), deliveredIvyFile.toURI().toURL(), false); + DependencyDescriptor[] dds = md.getDependencies(); + assertEquals(2, dds.length); + assertEquals(ModuleRevisionId.newInstance("overlap-older", "modA", "5"), dds[0].getDependencyRevisionId()); + assertEquals(ModuleRevisionId.newInstance("overlap-older", "modB", "1"), dds[1].getDependencyRevisionId()); + } + /** * Test case for IVY-590. * diff --git a/test/repositories/IVY-1485/ivy-overlap-transitive-newer.xml b/test/repositories/IVY-1485/ivy-overlap-transitive-newer.xml new file mode 100644 index 00000000..6fac61c1 --- /dev/null +++ b/test/repositories/IVY-1485/ivy-overlap-transitive-newer.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/test/repositories/IVY-1485/ivy-overlap-transitive-older.xml b/test/repositories/IVY-1485/ivy-overlap-transitive-older.xml new file mode 100644 index 00000000..2dbe080c --- /dev/null +++ b/test/repositories/IVY-1485/ivy-overlap-transitive-older.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/test/repositories/IVY-1485/ivy-simple.xml b/test/repositories/IVY-1485/ivy-simple.xml new file mode 100644 index 00000000..addbf811 --- /dev/null +++ b/test/repositories/IVY-1485/ivy-simple.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + diff --git a/test/repositories/IVY-1485/ivysettings.xml b/test/repositories/IVY-1485/ivysettings.xml new file mode 100644 index 00000000..4fa0207e --- /dev/null +++ b/test/repositories/IVY-1485/ivysettings.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-newer/modA/1/ivy.xml b/test/repositories/IVY-1485/overlap-newer/modA/1/ivy.xml new file mode 100644 index 00000000..1df2a5a2 --- /dev/null +++ b/test/repositories/IVY-1485/overlap-newer/modA/1/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-newer/modA/5/ivy.xml b/test/repositories/IVY-1485/overlap-newer/modA/5/ivy.xml new file mode 100644 index 00000000..cc8146bd --- /dev/null +++ b/test/repositories/IVY-1485/overlap-newer/modA/5/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-newer/modB/1/ivy.xml b/test/repositories/IVY-1485/overlap-newer/modB/1/ivy.xml new file mode 100644 index 00000000..5bff715e --- /dev/null +++ b/test/repositories/IVY-1485/overlap-newer/modB/1/ivy.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-older/modA/1/ivy.xml b/test/repositories/IVY-1485/overlap-older/modA/1/ivy.xml new file mode 100644 index 00000000..db0ecb44 --- /dev/null +++ b/test/repositories/IVY-1485/overlap-older/modA/1/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-older/modA/5/ivy.xml b/test/repositories/IVY-1485/overlap-older/modA/5/ivy.xml new file mode 100644 index 00000000..d927cf52 --- /dev/null +++ b/test/repositories/IVY-1485/overlap-older/modA/5/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/overlap-older/modB/1/ivy.xml b/test/repositories/IVY-1485/overlap-older/modB/1/ivy.xml new file mode 100644 index 00000000..6eab94ea --- /dev/null +++ b/test/repositories/IVY-1485/overlap-older/modB/1/ivy.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/test/repositories/IVY-1485/simple/modA/1/ivy.xml b/test/repositories/IVY-1485/simple/modA/1/ivy.xml new file mode 100644 index 00000000..796a6847 --- /dev/null +++ b/test/repositories/IVY-1485/simple/modA/1/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/simple/modA/5/ivy.xml b/test/repositories/IVY-1485/simple/modA/5/ivy.xml new file mode 100644 index 00000000..88c51357 --- /dev/null +++ b/test/repositories/IVY-1485/simple/modA/5/ivy.xml @@ -0,0 +1,26 @@ + + + + + + + + + diff --git a/test/repositories/IVY-1485/simple/modB/1/ivy.xml b/test/repositories/IVY-1485/simple/modB/1/ivy.xml new file mode 100644 index 00000000..e8ec0672 --- /dev/null +++ b/test/repositories/IVY-1485/simple/modB/1/ivy.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + +