mirror of https://github.com/apache/ant-ivy
FIX: now handle transitive eviction (IVY-51)
git-svn-id: https://svn.apache.org/repos/asf/incubator/ivy/trunk@484002 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f5a532d606
commit
8c02470fb0
|
|
@ -6,6 +6,7 @@
|
|||
- new type filtering in cachepath task
|
||||
- new cachefileset task: builds an ant fileset of artifacts in cache
|
||||
- publish task now uses srcivypattern for ivy files finding and for delivery
|
||||
- FIX: now handle transitive eviction (IVY-51)
|
||||
- FIX: resolve now store resolved file id in ivy variables, so that multiple resolve calls
|
||||
can be followed by multiple retrieve, each retrieve will use the last resolve info (IVY-49)
|
||||
- FIX: IllegalStateException on retrieve done from command line
|
||||
|
|
|
|||
|
|
@ -733,6 +733,7 @@ public class Ivy implements TransferListener {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// prune and reverse sort fectched dependencies
|
||||
Collection dependencies = new HashSet(dependenciesMap.size()); // use a Set to avoids duplicates
|
||||
for (Iterator iter = dependenciesMap.values().iterator(); iter.hasNext();) {
|
||||
|
|
@ -743,6 +744,39 @@ public class Ivy implements TransferListener {
|
|||
}
|
||||
List sortedDependencies = sortNodes(dependencies);
|
||||
Collections.reverse(sortedDependencies);
|
||||
|
||||
// handle transitive eviction now:
|
||||
// if a module has been evicted then all its dependencies required
|
||||
// only by it should be evicted too. Since nodes are now sorted from the more dependent to
|
||||
// the less one, we can traverse the list and check only the direct parent and not all
|
||||
// the ancestors
|
||||
for (ListIterator iter = sortedDependencies.listIterator(); iter.hasNext();) {
|
||||
IvyNode node = (IvyNode)iter.next();
|
||||
if (!node.isCompletelyEvicted()) {
|
||||
for (int i = 0; i < confs.length; i++) {
|
||||
IvyNode.Caller[] callers = node.getCallers(confs[i]);
|
||||
boolean allEvicted = callers.length > 0;
|
||||
for (int j = 0; j < callers.length; j++) {
|
||||
if (callers[j].getModuleRevisionId().equals(md.getModuleRevisionId())) {
|
||||
// the caller is the root module itself, it can't be evicted
|
||||
allEvicted = false;
|
||||
break;
|
||||
} else {
|
||||
IvyNode callerNode = (IvyNode)dependenciesMap.get(callers[j].getModuleRevisionId());
|
||||
if (callerNode != null && !callerNode.isEvicted(confs[i])) {
|
||||
allEvicted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allEvicted) {
|
||||
Message.verbose("all callers are evicted for "+node+": evicting too");
|
||||
node.markEvicted(confs[i], null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (IvyNode[])sortedDependencies.toArray(new IvyNode[sortedDependencies.size()]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ import fr.jayasoft.ivy.util.Message;
|
|||
|
||||
public class IvyNode {
|
||||
public static class EvictionData {
|
||||
private IvyNode _node;
|
||||
private ConflictManager _conflictManager;
|
||||
private Collection _selected;
|
||||
private IvyNode _node; // can be null in case of transitive eviction
|
||||
private ConflictManager _conflictManager; // can be null in case of transitive eviction
|
||||
private Collection _selected; // can be null in case of transitive eviction
|
||||
private String _rootModuleConf;
|
||||
|
||||
public EvictionData(String rootModuleConf, IvyNode node, ConflictManager conflictManager, Collection selected) {
|
||||
|
|
@ -35,7 +35,11 @@ public class IvyNode {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
return _selected + " in "+ _node+" ("+_conflictManager+") ["+_rootModuleConf+"]";
|
||||
if (_selected != null) {
|
||||
return _selected + " in "+ _node+" ("+_conflictManager+") ["+_rootModuleConf+"]";
|
||||
} else {
|
||||
return "transitively ["+_rootModuleConf+"]";
|
||||
}
|
||||
}
|
||||
|
||||
public ConflictManager getConflictManager() {
|
||||
|
|
@ -292,12 +296,14 @@ public class IvyNode {
|
|||
String rootModuleConf = (String)iter.next();
|
||||
EvictionData ed = (EvictionData)_evicted.get(rootModuleConf);
|
||||
Collection sel = ed.getSelected();
|
||||
for (Iterator iterator = sel.iterator(); iterator.hasNext();) {
|
||||
IvyNode n = (IvyNode)iterator.next();
|
||||
if (n.getRealNode().equals(this)) {
|
||||
// yes, we are the real node for a selected one !
|
||||
// we are no more evicted in this conf !
|
||||
iter.remove();
|
||||
if (sel != null) {
|
||||
for (Iterator iterator = sel.iterator(); iterator.hasNext();) {
|
||||
IvyNode n = (IvyNode)iterator.next();
|
||||
if (n.getRealNode().equals(this)) {
|
||||
// yes, we are the real node for a selected one !
|
||||
// we are no more evicted in this conf !
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,9 +320,11 @@ public class IvyNode {
|
|||
}
|
||||
|
||||
// bug 105: update selected data with evicted one
|
||||
for (Iterator iter = resolved.iterator(); iter.hasNext();) {
|
||||
IvyNode selected = (IvyNode)iter.next();
|
||||
selected.updateDataFrom(this, rootModuleConf);
|
||||
if (resolved != null) {
|
||||
for (Iterator iter = resolved.iterator(); iter.hasNext();) {
|
||||
IvyNode selected = (IvyNode)iter.next();
|
||||
selected.updateDataFrom(this, rootModuleConf);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void updateDataFrom(IvyNode node, String rootModuleConf) {
|
||||
|
|
@ -390,7 +398,10 @@ public class IvyNode {
|
|||
Collection allEvictingNodes = new HashSet();
|
||||
for (Iterator iter = _evicted.values().iterator(); iter.hasNext();) {
|
||||
EvictionData ed = (EvictionData)iter.next();
|
||||
allEvictingNodes.addAll(ed.getSelected());
|
||||
Collection selected = ed.getSelected();
|
||||
if (selected != null) {
|
||||
allEvictingNodes.addAll(selected);
|
||||
}
|
||||
}
|
||||
return allEvictingNodes;
|
||||
}
|
||||
|
|
@ -666,6 +677,15 @@ public class IvyNode {
|
|||
return (Caller[])callers.values().toArray(new Caller[callers.values().size()]);
|
||||
}
|
||||
|
||||
public Caller[] getAllCallers() {
|
||||
Set all = new HashSet();
|
||||
for (Iterator iter = _callersByRootConf.values().iterator(); iter.hasNext();) {
|
||||
Map callers = (Map)iter.next();
|
||||
all.addAll(callers.values());
|
||||
}
|
||||
return (Caller[])all.toArray(new Caller[all.size()]);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getResolvedId().toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package fr.jayasoft.ivy.report;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import fr.jayasoft.ivy.IvyNode;
|
||||
import fr.jayasoft.ivy.util.Message;
|
||||
|
|
@ -22,7 +23,12 @@ public class LogReportOutputter implements ReportOutputter {
|
|||
if (evicted.length > 0) {
|
||||
Message.info("\t:: evicted modules:");
|
||||
for (int i = 0; i < evicted.length; i++) {
|
||||
Message.info("\t"+evicted[i]+" by "+evicted[i].getAllEvictingNodes()+" in "+Arrays.asList(evicted[i].getEvictedConfs()));
|
||||
Collection allEvictingNodes = evicted[i].getAllEvictingNodes();
|
||||
if (allEvictingNodes.isEmpty()) {
|
||||
Message.info("\t"+evicted[i]+" transitively in "+Arrays.asList(evicted[i].getEvictedConfs()));
|
||||
} else {
|
||||
Message.info("\t"+evicted[i]+" by "+allEvictingNodes+" in "+Arrays.asList(evicted[i].getEvictedConfs()));
|
||||
}
|
||||
String[] confs = evicted[i].getEvictedConfs();
|
||||
for (int j = 0; j < confs.length; j++) {
|
||||
IvyNode.EvictionData evictedData = evicted[i].getEvictedData(confs[j]);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
|
@ -69,7 +70,11 @@ public class XmlReportOutputter implements ReportOutputter {
|
|||
}
|
||||
if (dep.isEvicted(report.getConfiguration())) {
|
||||
IvyNode.EvictionData ed = dep.getEvictedData(report.getConfiguration());
|
||||
details += " evicted=\""+ed.getConflictManager()+"\"";
|
||||
if (ed.getConflictManager() != null) {
|
||||
details += " evicted=\""+ed.getConflictManager()+"\"";
|
||||
} else {
|
||||
details += " evicted=\"transitive\"";
|
||||
}
|
||||
}
|
||||
if (dep.hasProblem()) {
|
||||
details += " error=\""+dep.getProblem().getMessage()+"\"";
|
||||
|
|
@ -96,9 +101,12 @@ public class XmlReportOutputter implements ReportOutputter {
|
|||
}
|
||||
if (dep.isEvicted(report.getConfiguration())) {
|
||||
IvyNode.EvictionData ed = dep.getEvictedData(report.getConfiguration());
|
||||
for (Iterator it3 = ed.getSelected().iterator(); it3.hasNext();) {
|
||||
IvyNode sel = (IvyNode)it3.next();
|
||||
out.println("\t\t\t\t<evicted-by rev=\""+sel.getResolvedId().getRevision()+"\"/>");
|
||||
Collection selected = ed.getSelected();
|
||||
if (selected != null) {
|
||||
for (Iterator it3 = selected.iterator(); it3.hasNext();) {
|
||||
IvyNode sel = (IvyNode)it3.next();
|
||||
out.println("\t\t\t\t<evicted-by rev=\""+sel.getResolvedId().getRevision()+"\"/>");
|
||||
}
|
||||
}
|
||||
}
|
||||
IvyNode.Caller[] callers = dep.getCallers(report.getConfiguration());
|
||||
|
|
|
|||
|
|
@ -352,6 +352,33 @@ public class ResolveTest extends TestCase {
|
|||
assertTrue(_ivy.getArchiveFileInCache(_cache, "org1", "mod1.2", "2.1", "mod1.2", "jar", "jar").exists());
|
||||
}
|
||||
|
||||
public void testTransitiveEviction() throws Exception {
|
||||
// mod7.3 depends on mod7.2 v1.0 and on mod7.1 v2.0
|
||||
// mod7.2 v1.0 depends on mod7.1 v1.0 (which then should be evicted)
|
||||
// mod7.1 v1.0 depends on mod 1.2 v1.0 (which should be evicted by transitivity)
|
||||
|
||||
ResolveReport report = _ivy.resolve(new File("test/repositories/2/mod7.3/ivy-1.0.xml").toURL(),
|
||||
null, new String[] {"*"}, _cache, null, true);
|
||||
assertNotNull(report);
|
||||
ModuleDescriptor md = report.getModuleDescriptor();
|
||||
assertNotNull(md);
|
||||
ModuleRevisionId mrid = ModuleRevisionId.newInstance("org7", "mod7.3", "1.0");
|
||||
assertEquals(mrid, md.getModuleRevisionId());
|
||||
|
||||
assertTrue(_ivy.getIvyFileInCache(_cache, mrid).exists());
|
||||
|
||||
// dependencies
|
||||
assertTrue(_ivy.getIvyFileInCache(_cache, ModuleRevisionId.newInstance("org7", "mod7.2", "1.0")).exists());
|
||||
assertTrue(_ivy.getArchiveFileInCache(_cache, "org7", "mod7.2", "1.0", "mod7.2", "jar", "jar").exists());
|
||||
|
||||
assertTrue(_ivy.getIvyFileInCache(_cache, ModuleRevisionId.newInstance("org7", "mod7.1", "2.0")).exists());
|
||||
assertTrue(_ivy.getArchiveFileInCache(_cache, "org7", "mod7.1", "2.0", "mod7.1", "jar", "jar").exists());
|
||||
|
||||
assertTrue(!_ivy.getArchiveFileInCache(_cache, "org7", "mod7.1", "1.0", "mod7.1", "jar", "jar").exists());
|
||||
|
||||
assertTrue(!_ivy.getArchiveFileInCache(_cache, "org1", "mod1.2", "2.0", "mod1.2", "jar", "jar").exists());
|
||||
}
|
||||
|
||||
public void testResolveConflictInConf() throws Exception {
|
||||
// conflicts in separate confs are not conflicts
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue