use of org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData in project ant-ivy by apache.
the class XmlReportWriter method outputEvictionInformation.
private void outputEvictionInformation(ConfigurationResolveReport report, PrintWriter out, IvyNode dep) {
if (dep.isEvicted(report.getConfiguration())) {
EvictionData ed = dep.getEvictedData(report.getConfiguration());
Collection<IvyNode> selected = ed.getSelected();
if (selected != null) {
for (IvyNode sel : selected) {
out.println("\t\t\t\t<evicted-by rev=\"" + XMLHelper.escape(sel.getResolvedId().getRevision()) + "\"/>");
}
}
}
}
use of org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData in project ant-ivy by apache.
the class IvyDependencyTree method printDependencies.
private void printDependencies(final ModuleRevisionId mrid, final List<IvyNode> dependencyList, final int indent, final Set<ModuleRevisionId> ancestors) {
for (IvyNode dependency : dependencyList) {
final Set<ModuleRevisionId> ancestorsForCurrentDep = new HashSet<>(ancestors);
// previous ancestors plus the module to whom these dependencies belong to
ancestorsForCurrentDep.add(mrid);
final boolean evicted = dependency.isEvicted(getConf());
if (evicted && !showEvicted) {
continue;
}
final boolean isLastDependency = dependencyList.indexOf(dependency) == dependencyList.size() - 1;
final StringBuilder sb = new StringBuilder();
final ModuleRevisionId dependencyMrid = dependency.getId();
final boolean circular = ancestorsForCurrentDep.contains(dependencyMrid);
if (indent > 0) {
for (int i = 0; i < indent; i++) {
if (i == indent - 1 && isLastDependency && !hasDependencies(dependency)) {
sb.append(" ");
} else {
sb.append("| ");
}
}
}
sb.append(isLastDependency ? "\\- " : "+- ");
if (!evicted && circular) {
// log and skip processing the (transitive) dependencies of this dependency
sb.append("(circularly depends on) ").append(dependencyMrid);
log(sb.toString());
continue;
} else {
sb.append(dependencyMrid.toString());
}
if (evicted && showEvicted) {
EvictionData evictedData = dependency.getEvictedData(getConf());
if (evictedData.isTransitivelyEvicted()) {
sb.append(" transitively");
} else {
sb.append(" evicted by ");
sb.append(evictedData.getSelected());
sb.append(" in ").append(evictedData.getParent());
if (evictedData.getDetail() != null) {
sb.append(" ").append(evictedData.getDetail());
}
}
}
log(sb.toString());
printDependencies(dependencyMrid, dependencies.get(dependencyMrid), indent + 1, ancestorsForCurrentDep);
}
}
use of org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData in project ant-ivy by apache.
the class LatestCompatibleConflictManager method blackListIncompatibleCallerAndRestartResolveIfPossible.
private void blackListIncompatibleCallerAndRestartResolveIfPossible(IvySettings settings, IvyNode parent, IvyNode selected, IvyNode evicted) {
Stack<IvyNode> callerStack = new Stack<>();
callerStack.push(evicted);
Collection<IvyNodeBlacklist> toBlacklist = blackListIncompatibleCaller(settings.getVersionMatcher(), parent, selected, evicted, callerStack);
if (toBlacklist != null) {
final StringBuilder blacklisted = new StringBuilder();
for (IvyNodeBlacklist blacklist : toBlacklist) {
if (blacklisted.length() > 0) {
blacklisted.append(" ");
}
IvyNode blacklistedNode = blacklist.getBlacklistedNode();
blacklistedNode.blacklist(blacklist);
blacklisted.append(blacklistedNode);
}
String rootModuleConf = parent.getData().getReport().getConfiguration();
evicted.markEvicted(new EvictionData(rootModuleConf, parent, this, Collections.singleton(selected), "with blacklisting of " + blacklisted));
if (settings.debugConflictResolution()) {
Message.debug("evicting " + evicted + " by " + evicted.getEvictedData(rootModuleConf));
}
throw new RestartResolveProcess("trying to handle incompatibilities between " + selected + " and " + evicted);
}
}
use of org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData in project ant-ivy by apache.
the class ResolveEngine method resolveConflict.
/**
* Resolves conflict for the given node in the given ancestor. This method do conflict
* resolution in ancestor parents recursively, unless not necessary.
*
* @param node
* the node for which conflict resolution should be done
* @param ancestor
* the ancestor in which the conflict resolution should be done
* @param conf String
* @param toevict
* a collection of IvyNode to evict (as computed by conflict resolution in
* descendants of ancestor)
* @return true if conflict resolution has been done, false it can't be done yet
*/
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)) {
// 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;
}
}
use of org.apache.ivy.core.resolve.IvyNodeEviction.EvictionData in project ant-ivy by apache.
the class ResolveEngine method fetchDependencies.
private void fetchDependencies(VisitNode node, String conf, boolean shouldBePublic) {
checkInterrupted();
long start = System.currentTimeMillis();
if (node.getParent() != null) {
Message.verbose("== resolving dependencies " + node.getParent().getId() + "->" + node.getId() + " [" + node.getParentConf() + "->" + conf + "]");
} else {
Message.verbose("== resolving dependencies for " + node.getId() + " [" + conf + "]");
}
ResolveData data = node.getNode().getData();
VisitNode parentVisitNode = data.getCurrentVisitNode();
data.setCurrentVisitNode(node);
DependencyDescriptor dd = node.getDependencyDescriptor();
VersionMatcher versionMatcher = node.getNode().getData().getSettings().getVersionMatcher();
if (dd != null && !(node.getRoot() == node.getParent() && versionMatcher.isDynamic(dd.getDependencyRevisionId()))) {
/*
* we don't resolve conflicts before loading data for direct dependencies on dynamic
* revisions, so that direct dynamic revisions are always resolved, which is mandatory
* for proper replacement of dynamic revisions during 'deliver'
*/
resolveConflict(node, conf);
}
if (node.loadData(conf, shouldBePublic)) {
// we resolve conflict again now that we have all information loaded
// indeed in some cases conflict manager need more information than just asked
// dependency to take the decision
resolveConflict(node, conf);
if (!node.isEvicted() && !node.isCircular()) {
for (String rconf : node.getRealConfs(conf)) {
doFetchDependencies(node, rconf);
}
}
} else if (!node.hasProblem()) {
// => we just have to update its dependencies data
if (!node.isEvicted() && !node.isCircular()) {
for (String rconf : node.getRealConfs(conf)) {
doFetchDependencies(node, rconf);
}
}
}
if (node.isEvicted()) {
// update selected nodes with confs asked in evicted one
EvictionData ed = node.getEvictedData();
if (ed.getSelected() != null) {
for (IvyNode selected : ed.getSelected()) {
if (!selected.isLoaded()) {
// the node is not yet loaded, we can simply update its set of
// configurations to fetch
selected.updateConfsToFetch(Collections.singleton(conf));
} else {
// the node has already been loaded, we must fetch its dependencies in the
// required conf
fetchDependencies(node.gotoNode(selected), conf, true);
}
}
}
}
if (settings.debugConflictResolution()) {
Message.debug(node.getId() + " => dependencies resolved in " + conf + " (" + (System.currentTimeMillis() - start) + "ms)");
}
data.setCurrentVisitNode(parentVisitNode);
}
Aggregations