in src/java/org/apache/ivy/core/resolve/ResolveEngine.java [869:1026]
private boolean resolveConflict(VisitNode node, VisitNode ancestor, String conf,
Collection<IvyNode> toevict) {
if (ancestor == null || node == ancestor) {
return true;
}
// check if job is not already done
if (checkConflictSolvedEvicted(node, ancestor)) {
// job is done and node is evicted, nothing to do
return true;
}
boolean debugConflictResolution = settings.debugConflictResolution();
if (checkConflictSolvedSelected(node, ancestor)) {
// job is done and node is selected, nothing to do for this ancestor, but we still have
// to check higher levels, for which conflict resolution might have been impossible
// before
if (resolveConflict(node, ancestor.getParent(), conf, toevict)) {
// now that conflict resolution is ok in ancestors
// we just have to check if the node wasn't previously evicted in root ancestor
EvictionData evictionData = node.getEvictionDataInRoot(node.getRootModuleConf(),
ancestor);
if (evictionData != null) {
// node has been previously evicted in an ancestor: we mark it as evicted
if (debugConflictResolution) {
Message.debug(node + " was previously evicted in root module conf "
+ node.getRootModuleConf());
}
node.markEvicted(evictionData);
if (debugConflictResolution) {
Message.debug("evicting " + node + " by " + evictionData);
}
}
return true;
} else {
return false;
}
}
// compute conflicts
Set<IvyNode> resolvedNodes = ancestor.getNode().getResolvedNodes(node.getModuleId(),
node.getRootModuleConf());
resolvedNodes.addAll(ancestor.getNode().getPendingConflicts(node.getRootModuleConf(),
node.getModuleId()));
Collection<IvyNode> conflicts = computeConflicts(node, ancestor, conf, toevict,
resolvedNodes);
ConflictManager conflictManager = null;
for (VisitNode current : ancestor.getPath()) {
ModuleDescriptor descriptor = current.getNode().getDescriptor();
if (descriptor == null) {
throw new IllegalStateException(
"impossible to get conflict manager when data has not been loaded. IvyNode = "
+ current.getNode());
}
conflictManager = descriptor.getConflictManager(node.getModuleId());
if (conflictManager != null) {
break;
}
}
if (conflictManager == null) {
conflictManager = settings.getConflictManager(node.getModuleId());
}
Collection<IvyNode> resolved = resolveConflicts(node, ancestor, conflicts, conflictManager);
if (resolved == null) {
if (debugConflictResolution) {
Message.debug("impossible to resolve conflicts for " + node + " in " + ancestor
+ " yet");
Message.debug("setting all nodes as pending conflicts for later conflict"
+ " resolution: " + conflicts);
}
ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
conflicts);
return false;
}
if (debugConflictResolution) {
Message.debug("selected revisions for " + node + " in " + ancestor + ": " + resolved);
}
if (resolved.contains(node.getNode())) {
// node has been selected for the current parent
// handle previously selected nodes that are now evicted by this new node
toevict = resolvedNodes;
toevict.removeAll(resolved);
for (IvyNode te : toevict) {
te.markEvicted(node.getRootModuleConf(), ancestor.getNode(), conflictManager,
resolved);
if (debugConflictResolution) {
Message.debug("evicting " + te + " by "
+ te.getEvictedData(node.getRootModuleConf()));
}
}
// it's very important to update resolved and evicted nodes BEFORE recompute parent call
// to allow it to recompute its resolved collection with correct data
// if necessary
ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(),
resolved);
Collection<IvyNode> evicted = new HashSet<>(ancestor.getNode().getEvictedNodes(
node.getModuleId(), node.getRootModuleConf()));
evicted.removeAll(resolved);
evicted.addAll(toevict);
ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(),
evicted);
ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
Collections.<IvyNode> emptySet());
return resolveConflict(node, ancestor.getParent(), conf, toevict);
} else {
// node has been evicted for the current parent
if (resolved.isEmpty()) {
if (debugConflictResolution) {
Message.verbose("conflict manager '" + conflictManager
+ "' evicted all revisions among " + conflicts);
}
}
// it's time to update parent resolved and evicted with what was found
Collection<IvyNode> evicted = new HashSet<>(ancestor.getNode().getEvictedNodes(
node.getModuleId(), node.getRootModuleConf()));
toevict.removeAll(resolved);
evicted.removeAll(resolved);
evicted.addAll(toevict);
evicted.add(node.getNode());
ancestor.getNode().setEvictedNodes(node.getModuleId(), node.getRootModuleConf(),
evicted);
ancestor.getNode().setPendingConflicts(node.getModuleId(), node.getRootModuleConf(),
Collections.<IvyNode> emptySet());
node.markEvicted(ancestor, conflictManager, resolved);
if (debugConflictResolution) {
Message.debug("evicting " + node + " by " + node.getEvictedData());
}
// if resolved changed we have to go up in the graph
Collection<IvyNode> prevResolved = ancestor.getNode().getResolvedNodes(
node.getModuleId(), node.getRootModuleConf());
boolean solved = true;
if (!prevResolved.equals(resolved)) {
ancestor.getNode().setResolvedNodes(node.getModuleId(), node.getRootModuleConf(),
resolved);
for (IvyNode sel : resolved) {
if (!prevResolved.contains(sel)) {
solved &= resolveConflict(node.gotoNode(sel), ancestor.getParent(), conf,
toevict);
}
}
}
return solved;
}
}