You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by ja...@apache.org on 2018/08/13 10:19:37 UTC

ant-ivy git commit: IVY-1588 Don't throw a CircularDependencyException when parsing the pom of a import scoped dependency in dependencyManagement section

Repository: ant-ivy
Updated Branches:
  refs/heads/master c274756eb -> 26b2de729


IVY-1588 Don't throw a CircularDependencyException when parsing the pom of a import scoped dependency in dependencyManagement section


Project: http://git-wip-us.apache.org/repos/asf/ant-ivy/repo
Commit: http://git-wip-us.apache.org/repos/asf/ant-ivy/commit/26b2de72
Tree: http://git-wip-us.apache.org/repos/asf/ant-ivy/tree/26b2de72
Diff: http://git-wip-us.apache.org/repos/asf/ant-ivy/diff/26b2de72

Branch: refs/heads/master
Commit: 26b2de729617d0594e5b935b930fd7e775ba1c82
Parents: c274756
Author: Jaikiran Pai <ja...@apache.org>
Authored: Mon Aug 13 15:47:13 2018 +0530
Committer: Jaikiran Pai <ja...@apache.org>
Committed: Mon Aug 13 15:49:05 2018 +0530

----------------------------------------------------------------------
 asciidoc/release-notes.adoc                     |  1 +
 .../parser/m2/PomModuleDescriptorParser.java    | 63 +++++++++++++-------
 .../apache/ivy/core/resolve/ResolveTest.java    | 24 ++++++++
 .../org/apache/dm/parent/1.0/parent-1.0.pom     | 24 ++++++++
 .../org/apache/dm/sibling1/1.0/sibling1-1.0.pom | 42 +++++++++++++
 .../org/apache/dm/sibling2/1.0/sibling2-1.0.pom | 31 ++++++++++
 6 files changed, 164 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/asciidoc/release-notes.adoc
----------------------------------------------------------------------
diff --git a/asciidoc/release-notes.adoc b/asciidoc/release-notes.adoc
index cc460ca..47643e3 100644
--- a/asciidoc/release-notes.adoc
+++ b/asciidoc/release-notes.adoc
@@ -82,6 +82,7 @@ For details about the following changes, check our JIRA install at link:https://
 - FIX: Make Main.run() public (usable with REPL) (jira:IVY-1321[] jira:IVY-1578[]) (Thanks to Greg Perry)
 - FIX: Make ivy.deps.changed work with extra attributes (jira:IVY-1104[]) (Thanks to Arseny Aprelev)
 - FIX: Implement dependency configuration negation (jira:IVY-982[] jira:IVY-1547[]) (Thanks to Arseny Aprelev)
+- FIX: Don't throw a CircularDependencyException when parsing an import scoped dependency in dependencyManagement section of a pom (jira:IVY-1588[])
 
 - IMPROVEMENT: Throw an IllegalStateException when retrieving the resolutionCacheRoot on the DefaultResolutionCacheManager if the basedir (or IvySettings) is not set (jira:IVY-1482[])
 - IMPROVEMENT: Optimization: limit the revision numbers scanned if revision prefix is specified (Thanks to Ernestas Vaiciukevi&ccaron;ius)

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParser.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParser.java b/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParser.java
index 5aba146..c572ee1 100644
--- a/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParser.java
+++ b/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorParser.java
@@ -24,10 +24,10 @@ import java.net.URL;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.ivy.core.IvyContext;
 import org.apache.ivy.core.cache.ArtifactOrigin;
@@ -131,7 +131,7 @@ public final class PomModuleDescriptorParser implements ModuleDescriptorParser {
 
         try {
             final IvyContext ivyContext = IvyContext.pushNewCopyContext();
-            HashSet<ModuleRevisionId> parents = ivyContext.get(PARENT_MAP_KEY);
+            Set<ModuleRevisionId> parents = ivyContext.get(PARENT_MAP_KEY);
             if (parents == null) {
                 parents = new LinkedHashSet<>();
                 ivyContext.set(PARENT_MAP_KEY, parents);
@@ -185,7 +185,7 @@ public final class PomModuleDescriptorParser implements ModuleDescriptorParser {
                     parents.add(parentModRevID);
                 }
 
-                ResolvedModuleRevision parentModule = parseOtherPom(ivySettings, parentModRevID);
+                final ResolvedModuleRevision parentModule = parseOtherPom(ivySettings, parentModRevID, true);
                 if (parentModule == null) {
                     throw new IOException("Impossible to load parent for " + res.getName()
                             + ". Parent=" + parentModRevID);
@@ -225,7 +225,7 @@ public final class PomModuleDescriptorParser implements ModuleDescriptorParser {
                             + ". Please update your dependency to directly use the right version.");
                     Message.warn("Resolution will only pick dependencies of the relocated element."
                             + "  Artifact and other metadata will be ignored.");
-                    ResolvedModuleRevision relocatedModule = parseOtherPom(ivySettings, relocation);
+                    ResolvedModuleRevision relocatedModule = parseOtherPom(ivySettings, relocation, false);
                     if (relocatedModule == null) {
                         throw new ParseException(
                                 "impossible to load module " + relocation + " to which "
@@ -334,9 +334,13 @@ public final class PomModuleDescriptorParser implements ModuleDescriptorParser {
     private void addTo(PomModuleDescriptorBuilder mdBuilder, PomDependencyMgt dep,
             ParserSettings ivySettings) throws ParseException, IOException {
         if ("import".equals(dep.getScope())) {
+            // In Maven, "import" scope semantics are equivalent to getting (only) the
+            // dependency management section of the imported module, into the current
+            // module, so that those "managed dependency versions" are usable/applicable
+            // in the current module's dependencies
             ModuleRevisionId importModRevID = ModuleRevisionId.newInstance(dep.getGroupId(),
-                dep.getArtifactId(), dep.getVersion());
-            ResolvedModuleRevision importModule = parseOtherPom(ivySettings, importModRevID);
+                    dep.getArtifactId(), dep.getVersion());
+            ResolvedModuleRevision importModule = parseOtherPom(ivySettings, importModRevID, false);
             if (importModule == null) {
                 throw new IOException("Impossible to import module for "
                         + mdBuilder.getModuleDescriptor().getResource().getName() + ". Import="
@@ -424,24 +428,41 @@ public final class PomModuleDescriptorParser implements ModuleDescriptorParser {
         }
     }
 
-    private ResolvedModuleRevision parseOtherPom(ParserSettings ivySettings,
-            ModuleRevisionId parentModRevID) throws ParseException {
-        DependencyDescriptor dd = new DefaultDependencyDescriptor(parentModRevID, true);
-        ResolveData data = IvyContext.getContext().getResolveData();
-        if (data == null) {
-            ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
-            ResolveOptions options = new ResolveOptions();
-            options.setDownload(false);
-            data = new ResolveData(engine, options);
+    private ResolvedModuleRevision parseOtherPom(final ParserSettings ivySettings,
+            final ModuleRevisionId parentModRevID, final boolean isParentPom) throws ParseException {
+
+        Set<ModuleRevisionId> previousParents = null;
+        if (!isParentPom) {
+            // IVY-1588: we "reset" the parent tracking, since the parent tracking should only be
+            // non-null when we are parsing a parent pom.
+            previousParents = IvyContext.getContext().get(PARENT_MAP_KEY);
+            if (previousParents != null) {
+                IvyContext.getContext().set(PARENT_MAP_KEY, null);
+            }
         }
+        try {
+            DependencyDescriptor dd = new DefaultDependencyDescriptor(parentModRevID, true);
+            ResolveData data = IvyContext.getContext().getResolveData();
+            if (data == null) {
+                ResolveEngine engine = IvyContext.getContext().getIvy().getResolveEngine();
+                ResolveOptions options = new ResolveOptions();
+                options.setDownload(false);
+                data = new ResolveData(engine, options);
+            }
 
-        DependencyResolver resolver = ivySettings.getResolver(parentModRevID);
-        if (resolver == null) {
-            // TODO: Throw exception here?
-            return null;
+            DependencyResolver resolver = ivySettings.getResolver(parentModRevID);
+            if (resolver == null) {
+                // TODO: Throw exception here?
+                return null;
+            }
+            dd = toSystem(dd, ivySettings.getContextNamespace());
+            return resolver.getDependency(dd, data);
+        } finally {
+            if (!isParentPom) {
+                // switch back to the previous state of the parent tracking
+                IvyContext.getContext().set(PARENT_MAP_KEY, previousParents);
+            }
         }
-        dd = toSystem(dd, ivySettings.getContextNamespace());
-        return resolver.getDependency(dd, data);
     }
 
     private ParseException newParserException(Exception e) {

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/test/java/org/apache/ivy/core/resolve/ResolveTest.java
----------------------------------------------------------------------
diff --git a/test/java/org/apache/ivy/core/resolve/ResolveTest.java b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
index 5e58e32..2e03fc6 100644
--- a/test/java/org/apache/ivy/core/resolve/ResolveTest.java
+++ b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
@@ -52,6 +52,7 @@ import org.apache.ivy.util.CacheCleaner;
 import org.apache.ivy.util.FileUtil;
 import org.apache.ivy.util.MockMessageLogger;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -4996,6 +4997,29 @@ public class ResolveTest {
         }
     }
 
+    /**
+     * Tests that when a pom {@code A1} has a {@code dependencyManagement} section with a {@code import} scoped
+     * dependency and such a dependency has the same parent {@code P}, as {@code A1}, then a {@link CircularDependencyException}
+     * isn't thrown
+     *
+     * @throws Exception
+     * @see <a href="https://issues.apache.org/jira/browse/IVY-1588">IVY-1588</a> for more details
+     */
+    @Test
+    public void testDepMgmtImportWithSameParent() throws Exception {
+        // - sibling1 has parent "org.apache.dm:parent:1.0"
+        // - sibling1 further has dependencyManagement section with a dependency on sibling2 with scope=import
+        // - sibling2 has parent "org.apache.dm:parent:1.0" (same parent as sibling1)
+        // This should *not* trigger a CircularDependencyException for the parent
+        final Ivy ivy = new Ivy();
+        ivy.configure(new File("test/repositories/parentPom/ivysettings.xml"));
+        ivy.getSettings().setDefaultResolver("parentChain");
+        final File pom = new File("test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom");
+        final ResolveReport report = ivy.resolve(pom, getResolveOptions(new String[]{"*"}));
+        Assert.assertNotNull("Resolve report is null", report);
+        Assert.assertFalse("Resolve report has errors", report.hasError());
+    }
+
     @Test
     public void testErrorResolveMaven2SelfAsParent() throws Exception {
         // IVY-1545

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/test/repositories/parentPom/org/apache/dm/parent/1.0/parent-1.0.pom
----------------------------------------------------------------------
diff --git a/test/repositories/parentPom/org/apache/dm/parent/1.0/parent-1.0.pom b/test/repositories/parentPom/org/apache/dm/parent/1.0/parent-1.0.pom
new file mode 100644
index 0000000..88f3579
--- /dev/null
+++ b/test/repositories/parentPom/org/apache/dm/parent/1.0/parent-1.0.pom
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.dm</groupId>
+    <artifactId>parent</artifactId>
+    <version>1.0</version>
+    <packaging>pom</packaging>
+</project>

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom
----------------------------------------------------------------------
diff --git a/test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom b/test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom
new file mode 100644
index 0000000..0f796e0
--- /dev/null
+++ b/test/repositories/parentPom/org/apache/dm/sibling1/1.0/sibling1-1.0.pom
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project>
+    <parent>
+        <groupId>org.apache.dm</groupId>
+        <artifactId>parent</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.dm</groupId>
+    <artifactId>sibling1</artifactId>
+    <version>1.0</version>
+    <packaging>pom</packaging>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.dm</groupId>
+                <artifactId>sibling2</artifactId>
+                <version>1.0</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+</project>

http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/26b2de72/test/repositories/parentPom/org/apache/dm/sibling2/1.0/sibling2-1.0.pom
----------------------------------------------------------------------
diff --git a/test/repositories/parentPom/org/apache/dm/sibling2/1.0/sibling2-1.0.pom b/test/repositories/parentPom/org/apache/dm/sibling2/1.0/sibling2-1.0.pom
new file mode 100644
index 0000000..fc01560
--- /dev/null
+++ b/test/repositories/parentPom/org/apache/dm/sibling2/1.0/sibling2-1.0.pom
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project>
+    <parent>
+        <groupId>org.apache.dm</groupId>
+        <artifactId>parent</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.apache.dm</groupId>
+    <artifactId>sibling2</artifactId>
+    <packaging>pom</packaging>
+    <version>1.0</version>
+
+</project>