IVY-1486 Respect exclude regardless of resolution order 63/head
authorGintas Grigelionis <gintas@apache.org>
Tue, 14 Aug 2018 17:33:26 +0000 (19:33 +0200)
committerGintas Grigelionis <gintas@apache.org>
Tue, 14 Aug 2018 17:33:31 +0000 (19:33 +0200)
38 files changed:
asciidoc/release-notes.adoc
src/java/org/apache/ivy/core/resolve/IvyNode.java
src/java/org/apache/ivy/core/resolve/IvyNodeCallers.java
test/java/org/apache/ivy/TestHelper.java
test/java/org/apache/ivy/core/resolve/ResolveTest.java
test/repositories/IVY-1486/ivysettings.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/a/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/a/lib/a-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/h/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/h/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/h/lib/h-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/h/lib/h-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/i/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/i/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/i/lib/i-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/i/lib/i-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/j/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/j/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/j/lib/j-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/j/lib/j-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/k/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/k/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/k/lib/k-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/k/lib/k-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/l/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/l/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/l/lib/l-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/l/lib/l-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/root/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/root/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/x/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/x/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/x/lib/x-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/x/lib/x-2.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/y/ivy-1.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/y/ivy-2.xml [new file with mode: 0644]
test/repositories/IVY-1486/org/y/lib/y-1.jar [new file with mode: 0644]
test/repositories/IVY-1486/org/y/lib/y-2.jar [new file with mode: 0644]

index 00d2124..ecfc530 100644 (file)
@@ -67,13 +67,13 @@ For details about the following changes, check our JIRA install at link:https://
 - FIX: Makepom ignores dependency classifiers (jira:IVY-1528[]) (Thanks to Jaikiran Pai)
 - FIX: Infinite loop in dependency tree (jira:IVY-1540[]) (Thanks to Jaikiran Pai)
 - FIX: HTTP issue: Basic authentication is stuck in 401 loop (jira:IVY-1336[])
-- FIX: command line: -types seems to not accept comma [jira:IVY-1355[]]
-- FIX: Mixed use of symlinks leads to cache corruption [jira:IVY-1498[]] (Thanks to Stephen Haberman)
-- FIX: Some cached locations are stored incorrectly resulting in MalformedURLException [jira:IVY-1566[]] (Thanks to Aur&eacute;lien Pupier)
-- FIX: defaultconf/mapping attributes ignored when extended/included from parent file [jira:IVY-1315[]] [jira:IVY-1419[]] [jira:IVY-1420[]] [jira:IVY-1437[]] (Thanks to Willem Verstraeten)
-- FIX: ApacheURLLister skips versions with URL encoded characters [jira:IVY-1442[]] [jira:IVY-1573[]]
-- FIX: Configuration lists are sensitive to whitespace; multiple split/merge methods [jira:IVY-309[]] [jira:IVY-1282[]]
-- FIX: Warnings about illegal reflection access due to lack of methods to retrieve default authenticator in Java 5 to 8 [jira:IVY-1569[]]
+- FIX: command line: -types seems to not accept comma (jira:IVY-1355[])
+- FIX: Mixed use of symlinks leads to cache corruption (jira:IVY-1498[]) (Thanks to Stephen Haberman)
+- FIX: Some cached locations are stored incorrectly resulting in MalformedURLException (jira:IVY-1566[]) (Thanks to Aur&eacute;lien Pupier)
+- FIX: defaultconf/mapping attributes ignored when extended/included from parent file (jira:IVY-1315[] jira:IVY-1419[] jira:IVY-1420[] jira:IVY-1437[]) (Thanks to Willem Verstraeten)
+- FIX: ApacheURLLister skips versions with URL encoded characters (jira:IVY-1442[] jira:IVY-1573[])
+- FIX: Configuration lists are sensitive to whitespace; multiple split/merge methods (jira:IVY-309[] jira:IVY-1282[])
+- FIX: Warnings about illegal reflection access due to lack of methods to retrieve default authenticator in Java 5 to 8 (jira:IVY-1569[])
 - FIX: Cycle in parent POM ancestry yields StackOverflowError in PomModuleDescriptorParser (jira:IVY-1545[]) (Thanks to Brett Randall)
 - FIX: The method hasIvyListener in org.apache.ivy.core.event.EventManager always returned false
 - FIX: Allow conditionally activated properties through Maven profiles, to be referenced in the `pom.xml` (jira:IVY-1577[])
@@ -83,16 +83,17 @@ For details about the following changes, check our JIRA install at link:https://
 - 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[])
+- FIX: Respect exclude regardless of resolution order (jira:IVY-1486[]) (thanks to David Turner)
 
 - 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)
 - IMPROVEMENT: Update BouncyCastle to 1.59 (jira:IVY-1521[]) (Thanks to Michal Srb)
 - IMPROVEMENT: `symlinkmass` option of retrieve task has been deprecated in this release and will no longer be supported since, starting this version of Ivy, Ivy uses Java standard API(s) for symlink management and as such doesn't spawn a process to execute symlink creation shell commands, like it used to do earlier. The `symlinkmass` option was previously there to launch just one single process instead of multiple processes for symlink creation. Now with the usage of the Java standard API(s), this option no longer is relevant.
 - IMPROVEMENT: Ivy command line now supports passing `overwriteMode` option to `retrieve` task (jira:IVY-1447[])
-- IMPROVEMENT: Support timestamped SNAPSHOT versions from Maven repository (jira:IVY-1153[]) and (jira:IVY-1476[])
+- IMPROVEMENT: Support timestamped SNAPSHOT versions from Maven repository (jira:IVY-1153[] jira:IVY-1476[])
 - IMPROVEMENT: Update Commons VFS to 2.2
-- IMPROVEMENT: Ivy now supports activating of Maven profiles, in `pom.xml`, by `jdk`, `os`, `property` and `file` (jira:IVY-1558[]) and (jira:IVY-1577[])
-- FIX: Improved thread-safety of the resolve process
+- IMPROVEMENT: Ivy now supports activating of Maven profiles, in `pom.xml`, by `jdk`, `os`, `property` and `file` (jira:IVY-1558[] jira:IVY-1577[])
+- IMPROVEMENT: Better thread safety of the resolve process
 
 - NEW: Lets SSH-based resolvers use an `~/.ssh/config` file to find username/hostname/keyfile options (Thanks to Colin Stanfill)
 - NEW: Add ivy.maven.lookup.sources and ivy.maven.lookup.javadoc variables to control the lookup of the additional artifacts. Defaults to true, for backward compatibility (jira:IVY-1529[])
index 8211021..9d23db5 100644 (file)
  */
 package org.apache.ivy.core.resolve;
 
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -401,27 +403,22 @@ public class IvyNode implements Comparable<IvyNode> {
         if (isRoot()) {
             // no callers, but maybe some exclude
             Boolean exclude = doesExclude(md, rootModuleConf, new String[] {rootModuleConf}, dd, a,
-                new Stack<ModuleRevisionId>());
+                new ArrayDeque<IvyNode>());
             return exclude != null && exclude;
         }
         return callers.doesCallersExclude(rootModuleConf, a);
     }
 
     Boolean doesExclude(ModuleDescriptor md, String rootModuleConf, String[] moduleConfs,
-            DependencyDescriptor dd, Artifact artifact, Stack<ModuleRevisionId> callersStack) {
+            DependencyDescriptor dd, Artifact artifact, Deque<IvyNode> callersStack) {
         // artifact is excluded if it match any of the exclude pattern for this dependency...
-        if (dd != null) {
-            if (dd.doesExclude(moduleConfs, artifact.getId().getArtifactId())) {
-                return Boolean.TRUE;
-            }
-        }
-        if (md.doesExclude(moduleConfs, artifact.getId().getArtifactId())) {
+        if (directlyExcludes(md, moduleConfs, dd, artifact)) {
             return Boolean.TRUE;
         }
         // ... or if it is excluded by all its callers
         IvyNode c = getData().getNode(md.getModuleRevisionId());
         if (c != null) {
-            if (callersStack.contains(c.getId())) {
+            if (callersStack.contains(c)) {
                 // a circular dependency, we cannot be conclusive here
                 return null;
             }
@@ -430,6 +427,12 @@ public class IvyNode implements Comparable<IvyNode> {
         return Boolean.FALSE;
     }
 
+    public boolean directlyExcludes(ModuleDescriptor md, String[] moduleConfs,
+            DependencyDescriptor dd, Artifact artifact) {
+        return dd != null && dd.doesExclude(moduleConfs, artifact.getId().getArtifactId())
+                || md.doesExclude(moduleConfs, artifact.getId().getArtifactId());
+    }
+
     public boolean hasConfigurationsToLoad() {
         return !confsToFetch.isEmpty();
     }
@@ -1073,10 +1076,24 @@ public class IvyNode implements Comparable<IvyNode> {
     }
 
     public boolean doesCallersExclude(String rootModuleConf, Artifact artifact,
-            Stack<ModuleRevisionId> callersStack) {
+            Deque<IvyNode> callersStack) {
         return callers.doesCallersExclude(rootModuleConf, artifact, callersStack);
     }
 
+    @Deprecated
+    public boolean doesCallersExclude(String rootModuleConf, Artifact artifact,
+            Stack<ModuleRevisionId> callersStack) {
+        Deque<IvyNode> callersDeque = new ArrayDeque<>();
+        for (ModuleRevisionId mrid : callersStack) {
+            for (Caller caller : getCallers(rootModuleConf)) {
+                if (caller.getModuleRevisionId().equals(mrid)) {
+                    callersDeque.add(data.getNode(mrid));
+                }
+            }
+        }
+        return callers.doesCallersExclude(rootModuleConf, artifact, callersDeque);
+    }
+
     private ModuleRevisionId[] toMrids(Collection<IvyNode> path, IvyNode depNode) {
         ModuleRevisionId[] ret = new ModuleRevisionId[path.size() + 1];
         int i = 0;
index 9356281..3c0d78c 100644 (file)
  */
 package org.apache.ivy.core.resolve;
 
+import java.util.ArrayDeque;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.Stack;
 
 import org.apache.ivy.core.module.descriptor.Artifact;
 import org.apache.ivy.core.module.descriptor.Configuration;
+import org.apache.ivy.core.module.descriptor.DefaultArtifact;
 import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
 import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
 import org.apache.ivy.core.module.id.ModuleId;
@@ -208,6 +211,21 @@ public class IvyNodeCallers {
         return callers.values().toArray(new Caller[callers.values().size()]);
     }
 
+    private Set<Caller> getCallersByMrid(String rootModuleConf, ModuleRevisionId mrid) {
+        Map<ModuleRevisionId, Caller> callers = callersByRootConf.get(rootModuleConf);
+        if (callers == null) {
+            return Collections.emptySet();
+        }
+
+        Set<Caller> mridCallers = new HashSet<>();
+        for (Caller caller : callers.values()) {
+            if (caller.getAskedDependencyId().equals(mrid)) {
+                mridCallers.add(caller);
+            }
+        }
+        return mridCallers;
+    }
+
     public Caller[] getAllCallers() {
         Set<Caller> all = new HashSet<>();
         for (Map<ModuleRevisionId, Caller> callers : callersByRootConf.values()) {
@@ -263,19 +281,35 @@ public class IvyNodeCallers {
      * @return boolean
      */
     boolean doesCallersExclude(String rootModuleConf, Artifact artifact) {
-        return doesCallersExclude(rootModuleConf, artifact, new Stack<ModuleRevisionId>());
+        return doesCallersExclude(rootModuleConf, artifact, new ArrayDeque<IvyNode>());
     }
 
     boolean doesCallersExclude(String rootModuleConf, Artifact artifact,
-            Stack<ModuleRevisionId> callersStack) {
-        callersStack.push(node.getId());
+            Deque<IvyNode> callersStack) {
+        /* The caller stack is, from bottom to top, the path from the
+           artifact we're considering excluding up towards the
+           root. */
+        callersStack.push(node);
         try {
-            Caller[] callers = getCallers(rootModuleConf);
-            if (callers.length == 0) {
+            Set<Caller> callers = getCallersByMrid(rootModuleConf, node.getId());
+            if (callers.isEmpty()) {
                 return false;
             }
             boolean allInconclusive = true;
-            for (Caller caller : callers) {
+            String[] moduleConfs = new String[] {rootModuleConf};
+            callers: for (Caller caller : callers) {
+                /* Each ancestor of this artifact (called "descendant", here, since it's
+                   a descendant relative to this.node) might itself have been excluded by
+                   an older ancestor (this.node); if it is, then it is as if artifact
+                   itself were excluded in this path. */
+                for (IvyNode descendant : callersStack) {
+                    if (node.directlyExcludes(node.getDescriptor(), moduleConfs,
+                            caller.getDependencyDescriptor(),
+                            DefaultArtifact.newIvyArtifact(descendant.getId(), null))) {
+                        allInconclusive = false;
+                        continue callers;
+                    }
+                }
                 if (!caller.canExclude()) {
                     return false;
                 }
index 066e419..2aca947 100644 (file)
@@ -499,13 +499,7 @@ public class TestHelper {
     public static int getMaybeAvailablePort() {
         try (ServerSocket s = new ServerSocket(0)) {
             s.setReuseAddress(true);
-            int port = s.getLocalPort();
-            try {
-                s.close();
-            } catch (IOException e) {
-                // ignore
-            }
-            return port;
+            return s.getLocalPort();
         } catch (IOException e) {
             // ignore
         }
index 2e03fc6..6da15dd 100644 (file)
@@ -4265,6 +4265,53 @@ public class ResolveTest {
     }
 
     @Test
+    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());
+    }
+
+    @Test
+    public void testResolveExcludesModule3() throws Exception {
+        // Ensure that search for unexcluded paths doesn't get confused by the exclusion
+        // of parents.
+        ivy.configure(new File("test/repositories/IVY-1486/ivysettings.xml"));
+        ResolveReport report = ivy.resolve(new File(
+                        "test/repositories/IVY-1486/org/root/ivy-2.xml"),
+                getResolveOptions(new String[] {"*"}));
+        ModuleDescriptor md = report.getModuleDescriptor();
+        assertEquals(ModuleRevisionId.newInstance("org", "root", "2"),
+                md.getModuleRevisionId());
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "l", "1"))
+                .exists());
+        assertFalse(getIvyFileInCache(ModuleRevisionId.newInstance("org", "l", "2"))
+                .exists());
+
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "h", "2"))
+                .exists());
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "i", "2"))
+                .exists());
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "j", "2"))
+                .exists());
+        assertTrue(getIvyFileInCache(ModuleRevisionId.newInstance("org", "k", "2"))
+                .exists());
+    }
+
+    @Test
     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 (file)
index 0000000..919c4eb
--- /dev/null
@@ -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 (file)
index 0000000..31e4b20
--- /dev/null
@@ -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/a/lib/a-1.jar b/test/repositories/IVY-1486/org/a/lib/a-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/h/ivy-1.xml b/test/repositories/IVY-1486/org/h/ivy-1.xml
new file mode 100644 (file)
index 0000000..ea96745
--- /dev/null
@@ -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="h" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="h" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="i" rev="1" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/h/ivy-2.xml b/test/repositories/IVY-1486/org/h/ivy-2.xml
new file mode 100644 (file)
index 0000000..0b69af5
--- /dev/null
@@ -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="h" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="h" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="i" rev="2" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/h/lib/h-1.jar b/test/repositories/IVY-1486/org/h/lib/h-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/h/lib/h-2.jar b/test/repositories/IVY-1486/org/h/lib/h-2.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/i/ivy-1.xml b/test/repositories/IVY-1486/org/i/ivy-1.xml
new file mode 100644 (file)
index 0000000..d1fdcc5
--- /dev/null
@@ -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="i" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="i" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="j" rev="1" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/i/ivy-2.xml b/test/repositories/IVY-1486/org/i/ivy-2.xml
new file mode 100644 (file)
index 0000000..c0a9976
--- /dev/null
@@ -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="i" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="i" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="j" rev="2" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/i/lib/i-1.jar b/test/repositories/IVY-1486/org/i/lib/i-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/i/lib/i-2.jar b/test/repositories/IVY-1486/org/i/lib/i-2.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/j/ivy-1.xml b/test/repositories/IVY-1486/org/j/ivy-1.xml
new file mode 100644 (file)
index 0000000..9193cff
--- /dev/null
@@ -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="j" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="j" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="k" rev="1" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/j/ivy-2.xml b/test/repositories/IVY-1486/org/j/ivy-2.xml
new file mode 100644 (file)
index 0000000..e355ad2
--- /dev/null
@@ -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="j" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="j" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="k" rev="2" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/j/lib/j-1.jar b/test/repositories/IVY-1486/org/j/lib/j-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/j/lib/j-2.jar b/test/repositories/IVY-1486/org/j/lib/j-2.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/k/ivy-1.xml b/test/repositories/IVY-1486/org/k/ivy-1.xml
new file mode 100644 (file)
index 0000000..e4895de
--- /dev/null
@@ -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="k" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="k" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="l" rev="1" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/k/ivy-2.xml b/test/repositories/IVY-1486/org/k/ivy-2.xml
new file mode 100644 (file)
index 0000000..091ee2f
--- /dev/null
@@ -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="k" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="k" ext="jar" type="lib" conf="all"/>
+  </publications>
+  <dependencies>
+    <dependency org="org" name="l" rev="2" force="true"/>
+  </dependencies>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/k/lib/k-1.jar b/test/repositories/IVY-1486/org/k/lib/k-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/k/lib/k-2.jar b/test/repositories/IVY-1486/org/k/lib/k-2.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/l/ivy-1.xml b/test/repositories/IVY-1486/org/l/ivy-1.xml
new file mode 100644 (file)
index 0000000..8f6d346
--- /dev/null
@@ -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="l" revision="1" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="l" ext="jar" type="lib" conf="all"/>
+  </publications>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/l/ivy-2.xml b/test/repositories/IVY-1486/org/l/ivy-2.xml
new file mode 100644 (file)
index 0000000..d14aa4e
--- /dev/null
@@ -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="l" revision="2" status="integration" publication="20140905010101"/>
+  <configurations>
+   <conf name="all"/>
+  </configurations>
+  <publications>
+    <artifact name="l" ext="jar" type="lib" conf="all"/>
+  </publications>
+</ivy-module>
diff --git a/test/repositories/IVY-1486/org/l/lib/l-1.jar b/test/repositories/IVY-1486/org/l/lib/l-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/l/lib/l-2.jar b/test/repositories/IVY-1486/org/l/lib/l-2.jar
new file mode 100644 (file)
index 0000000..e69de29
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 (file)
index 0000000..e20fd2e
--- /dev/null
@@ -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/root/ivy-2.xml b/test/repositories/IVY-1486/org/root/ivy-2.xml
new file mode 100644 (file)
index 0000000..f349776
--- /dev/null
@@ -0,0 +1,40 @@
+<?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="2" 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="l" rev="1"/>
+    <dependency org="org" name="h" rev="2">
+      <exclude matcher="exactOrRegexp" org="org" module="l"/>
+    </dependency>
+    <dependency org="org" name="k" rev="2">
+      <exclude matcher="exactOrRegexp" org="org" module="l"/>
+    </dependency>
+    <dependency org="org" name="j" rev="2">
+      <exclude matcher="exactOrRegexp" org="org" module="k"/>
+    </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 (file)
index 0000000..08801cd
--- /dev/null
@@ -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 (file)
index 0000000..38ae447
--- /dev/null
@@ -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/x/lib/x-1.jar b/test/repositories/IVY-1486/org/x/lib/x-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/x/lib/x-2.jar b/test/repositories/IVY-1486/org/x/lib/x-2.jar
new file mode 100644 (file)
index 0000000..e69de29
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 (file)
index 0000000..98155ad
--- /dev/null
@@ -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 (file)
index 0000000..d42f1ca
--- /dev/null
@@ -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>
diff --git a/test/repositories/IVY-1486/org/y/lib/y-1.jar b/test/repositories/IVY-1486/org/y/lib/y-1.jar
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/repositories/IVY-1486/org/y/lib/y-2.jar b/test/repositories/IVY-1486/org/y/lib/y-2.jar
new file mode 100644 (file)
index 0000000..e69de29