From 9bf52b7e15b033463dfe7dfb90787a2d435de890 Mon Sep 17 00:00:00 2001
From: David Turner <dturner@twitter.com>
Date: Sun, 7 Sep 2014 13:40:19 -0400
Subject: [PATCH] Make doesCallersExclude check only callers of this version

Fix IVY-1486.
---
 CHANGES.txt                                        |  1 +
 .../apache/ivy/core/resolve/IvyNodeCallers.java    | 21 +++++++++++--
 .../conflict/LatestCompatibleConflictManager.java  |  2 +-
 .../apache/ivy/plugins/report/XmlReportWriter.java |  2 +-
 .../org/apache/ivy/core/resolve/ResolveTest.java   | 20 +++++++++++++
 test/repositories/IVY-1486/ivysettings.xml         | 29 ++++++++++++++++++
 test/repositories/IVY-1486/org/a/ivy-1.xml         | 31 ++++++++++++++++++++
 test/repositories/IVY-1486/org/root/ivy-1.xml      | 34 ++++++++++++++++++++++
 test/repositories/IVY-1486/org/x/ivy-1.xml         | 31 ++++++++++++++++++++
 test/repositories/IVY-1486/org/x/ivy-2.xml         | 31 ++++++++++++++++++++
 test/repositories/IVY-1486/org/y/ivy-1.xml         | 28 ++++++++++++++++++
 test/repositories/IVY-1486/org/y/ivy-2.xml         | 28 ++++++++++++++++++
 12 files changed, 254 insertions(+), 4 deletions(-)
 create mode 100644 test/repositories/IVY-1486/ivysettings.xml
 create mode 100644 test/repositories/IVY-1486/org/a/ivy-1.xml
 create mode 100644 test/repositories/IVY-1486/org/root/ivy-1.xml
 create mode 100644 test/repositories/IVY-1486/org/x/ivy-1.xml
 create mode 100644 test/repositories/IVY-1486/org/x/ivy-2.xml
 create mode 100644 test/repositories/IVY-1486/org/y/ivy-1.xml
 create mode 100644 test/repositories/IVY-1486/org/y/ivy-2.xml

diff --git a/CHANGES.txt b/CHANGES.txt
index ddf8591..dc4a0c8 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -150,6 +150,7 @@ for detailed view of each issue, please consult http://issues.apache.org/jira/br
 - FIX: regression introduced by IVY-1457, dependency management wasn't properly handled introducing lots of resolution failures
 - FIX: The SSH resolvers fails if the un-required jsch jar is missing (IVY-1471)
 - FIX: failed to resolve dynamic revisions in some cases for URL repositories (IVY-1472)
+- FIX: some excludes ignored (IVY-1486)
 
    2.4.0-rc1
 =====================================
diff --git a/src/java/org/apache/ivy/core/resolve/IvyNodeCallers.java b/src/java/org/apache/ivy/core/resolve/IvyNodeCallers.java
index 399a60a..af213f9 100644
--- a/src/java/org/apache/ivy/core/resolve/IvyNodeCallers.java
+++ b/src/java/org/apache/ivy/core/resolve/IvyNodeCallers.java
@@ -17,11 +17,13 @@
  */
 package org.apache.ivy.core.resolve;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
@@ -108,7 +110,7 @@ public class IvyNodeCallers {
             return mrid.toString();
         }
 
-        public ModuleRevisionId getAskedDependencyId(ResolveData resolveData) {
+        public ModuleRevisionId getAskedDependencyId() {
             return dd.getDependencyRevisionId();
         }
 
@@ -202,6 +204,21 @@ public class IvyNodeCallers {
         return (Caller[]) callers.values().toArray(new Caller[callers.values().size()]);
     }
 
+    private Caller[] getCallersByMrid(String rootModuleConf, ModuleRevisionId mrid) {
+        Map<ModuleRevisionId, Caller> callers = (Map) callersByRootConf.get(rootModuleConf);
+        if (callers == null) {
+            return new Caller[0];
+        }
+
+        List mridCallers = new ArrayList();
+        for (Caller caller : callers.values()) {
+            if (caller.getAskedDependencyId().equals(mrid)) {
+                mridCallers.add(caller);
+            }
+        }
+        return (Caller[]) mridCallers.toArray(new Caller[mridCallers.size()]);
+    }
+
     public Caller[] getAllCallers() {
         Set all = new HashSet();
         for (Iterator iter = callersByRootConf.values().iterator(); iter.hasNext();) {
@@ -267,7 +284,7 @@ public class IvyNodeCallers {
     boolean doesCallersExclude(String rootModuleConf, Artifact artifact, Stack callersStack) {
         callersStack.push(node.getId());
         try {
-            Caller[] callers = getCallers(rootModuleConf);
+            Caller[] callers = getCallersByMrid(rootModuleConf, node.getId());
             if (callers.length == 0) {
                 return false;
             }
diff --git a/src/java/org/apache/ivy/plugins/conflict/LatestCompatibleConflictManager.java b/src/java/org/apache/ivy/plugins/conflict/LatestCompatibleConflictManager.java
index f4e775c..ab9f281 100644
--- a/src/java/org/apache/ivy/plugins/conflict/LatestCompatibleConflictManager.java
+++ b/src/java/org/apache/ivy/plugins/conflict/LatestCompatibleConflictManager.java
@@ -263,7 +263,7 @@ public class LatestCompatibleConflictManager extends LatestConflictManager {
             if (callerNode.isBlacklisted(rootModuleConf)) {
                 continue;
             }
-            if (versionMatcher.isDynamic(callers[i].getAskedDependencyId(node.getData()))) {
+            if (versionMatcher.isDynamic(callers[i].getAskedDependencyId())) {
                 blacklisted.add(new IvyNodeBlacklist(conflictParent, selectedNode, evictedNode,
                         node, rootModuleConf));
                 if (node.isEvicted(rootModuleConf)
diff --git a/src/java/org/apache/ivy/plugins/report/XmlReportWriter.java b/src/java/org/apache/ivy/plugins/report/XmlReportWriter.java
index 080c658..535fbb3 100644
--- a/src/java/org/apache/ivy/plugins/report/XmlReportWriter.java
+++ b/src/java/org/apache/ivy/plugins/report/XmlReportWriter.java
@@ -250,7 +250,7 @@ public class XmlReportWriter {
                     + XMLHelper.escape(toString(callers[i].getCallerConfigurations()))
                     + "\""
                     + " rev=\""
-                    + XMLHelper.escape(callers[i].getAskedDependencyId(dep.getData()).getRevision())
+                    + XMLHelper.escape(callers[i].getAskedDependencyId().getRevision())
                     + "\""
                     + " rev-constraint-default=\""
                     + XMLHelper.escape(callers[i].getDependencyDescriptor()
diff --git a/test/java/org/apache/ivy/core/resolve/ResolveTest.java b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
index bb1e7c8..2da0abf 100644
--- a/test/java/org/apache/ivy/core/resolve/ResolveTest.java
+++ b/test/java/org/apache/ivy/core/resolve/ResolveTest.java
@@ -3842,6 +3842,26 @@ public class ResolveTest extends TestCase {
         assertFalse(getArchiveFileInCache("org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
     }
 
+    public void testResolveExcludesModule2() throws Exception {
+        // root depends on a and (x 2 excluding y)
+        // a depends on x 1
+        // x 1 depends on y 1
+        // x 2 depends on y 2
+        ivy.configure(new File("test/repositories/IVY-1486/ivysettings.xml"));
+        ResolveReport report = ivy.resolve(new File(
+                "test/repositories/IVY-1486/org/root/ivy-1.xml"),
+            getResolveOptions(new String[] {"*"}));
+        ModuleDescriptor md = report.getModuleDescriptor();
+        assertEquals(ModuleRevisionId.newInstance("org", "root", "1"),
+            md.getModuleRevisionId());
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "x", "2"))
+                .exists());
+        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "y", "2"))
+                .exists());
+        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "y", "1"))
+                .exists());
+    }
+
     public void testResolveExcludesModuleWide() throws Exception {
         // mod2.6 depends on mod2.1 and excludes mod1.1 module wide
         // mod2.1 depends on mod1.1 which depends on mod1.2
diff --git a/test/repositories/IVY-1486/ivysettings.xml b/test/repositories/IVY-1486/ivysettings.xml
new file mode 100644
index 0000000..e4160d7
--- /dev/null
+++ b/test/repositories/IVY-1486/ivysettings.xml
@@ -0,0 +1,29 @@
+<!--
+   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.
+-->
+<ivysettings>
+    <settings defaultCache="${ivy.basedir}/build/cache" defaultResolver="test" defaultConflictManager="latest-revision" />
+
+    <resolvers>
+       <filesystem name="test" latest="latest-revision" checkmodified="true">
+	<artifact pattern="${ivy.basedir}/test/repositories/IVY-1486/[organisation]/[module]/[type]/[artifact]-[revision].[ext]" />
+	<ivy pattern="${ivy.basedir}/test/repositories/IVY-1486/[organisation]/[module]/ivy-[revision].xml" />
+      </filesystem>
+   </resolvers>
+
+</ivysettings>
diff --git a/test/repositories/IVY-1486/org/a/ivy-1.xml b/test/repositories/IVY-1486/org/a/ivy-1.xml
new file mode 100644
index 0000000..a1d3dd5
--- /dev/null
+++ b/test/repositories/IVY-1486/org/a/ivy-1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="a" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="a" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="x" rev="1" force="true" />
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/root/ivy-1.xml b/test/repositories/IVY-1486/org/root/ivy-1.xml
new file mode 100644
index 0000000..9b2fe2d
--- /dev/null
+++ b/test/repositories/IVY-1486/org/root/ivy-1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="root" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="root" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="a" rev="1" />
+    <dependency org="org" name="x" rev="2">
+      <exclude matcher="exactOrRegexp" org="org" module="y"/>
+    </dependency>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/x/ivy-1.xml b/test/repositories/IVY-1486/org/x/ivy-1.xml
new file mode 100644
index 0000000..af52ef1
--- /dev/null
+++ b/test/repositories/IVY-1486/org/x/ivy-1.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="x" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="x" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="y" rev="1" force="true" />
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/x/ivy-2.xml b/test/repositories/IVY-1486/org/x/ivy-2.xml
new file mode 100644
index 0000000..adc9043
--- /dev/null
+++ b/test/repositories/IVY-1486/org/x/ivy-2.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="x" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="x" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="y" rev="2" force="true" />
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/y/ivy-1.xml b/test/repositories/IVY-1486/org/y/ivy-1.xml
new file mode 100644
index 0000000..98155ad
--- /dev/null
+++ b/test/repositories/IVY-1486/org/y/ivy-1.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="y" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="y" ext="jar" type="lib" conf="all"/>
+  </publications>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/y/ivy-2.xml b/test/repositories/IVY-1486/org/y/ivy-2.xml
new file mode 100644
index 0000000..d42f1ca
--- /dev/null
+++ b/test/repositories/IVY-1486/org/y/ivy-2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+-->
+<ivy-module version="1.0">
+  <info organisation="org" module="y" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="y" ext="jar" type="lib" conf="all"/>
+  </publications>
+</ivy-module>
-- 
2.0.1

