private static bool TryResolveConflicts <TItem>(this GraphNode <TItem> root, List <VersionConflictResult <TItem> > versionConflicts) { // now we walk the tree as often as it takes to determine // which paths are accepted or rejected, based on conflicts occuring // between cousin packages var acceptedLibraries = Cache <TItem> .RentDictionary(); var patience = 1000; var incomplete = true; var tracker = Cache <TItem> .RentTracker(); Func <GraphNode <TItem>, bool> skipNode = null; var centralTransitiveNodes = root.InnerNodes.Where(n => n.Item.IsCentralTransitive).ToList(); var hasCentralTransitiveDependencies = centralTransitiveNodes.Count > 0; if (hasCentralTransitiveDependencies) { skipNode = (node) => { return(node.Item.IsCentralTransitive); }; } while (incomplete && --patience != 0) { // Create a picture of what has not been rejected yet root.ForEach(true, (node, state, context) => WalkTreeRejectNodesOfRejectedNodes(state, node, context), tracker, skipNode); if (hasCentralTransitiveDependencies) { // Some of the central transitive nodes may be rejected now because their parents were rejected // Reject them accordingly root.RejectCentralTransitiveBecauseOfRejectedParents(tracker, centralTransitiveNodes); } // Inform tracker of ambiguity beneath nodes that are not resolved yet root.ForEach(WalkState.Walking, (node, state, context) => WalkTreeMarkAmbiguousNodes(node, state, context), tracker); if (hasCentralTransitiveDependencies) { DetectAndMarkAmbiguousCentralTransitiveDependencies(tracker, centralTransitiveNodes); } root.ForEach(true, (node, state, context) => WalkTreeAcceptOrRejectNodes(context, state, node), CreateState(tracker, acceptedLibraries)); incomplete = root.ForEachGlobalState(false, (node, state) => state || node.Disposition == Disposition.Acceptable); tracker.Clear(); } Cache <TItem> .ReleaseTracker(tracker); root.ForEach((node, context) => WalkTreeDectectConflicts(node, context), CreateState(versionConflicts, acceptedLibraries)); Cache <TItem> .ReleaseDictionary(acceptedLibraries); return(!incomplete); }
private static bool TryResolveConflicts <TItem>(this GraphNode <TItem> root, List <VersionConflictResult <TItem> > versionConflicts) { // now we walk the tree as often as it takes to determine // which paths are accepted or rejected, based on conflicts occuring // between cousin packages var acceptedLibraries = Cache <TItem> .RentDictionary(); var patience = 1000; var incomplete = true; var tracker = Cache <TItem> .RentTracker(); while (incomplete && --patience != 0) { // Create a picture of what has not been rejected yet root.ForEach(true, (node, state, context) => WalkTreeRejectNodesOfRejectedNodes(state, node, context), tracker); // Inform tracker of ambiguity beneath nodes that are not resolved yet root.ForEach(WalkState.Walking, (node, state, context) => WalkTreeMarkAmbiguousNodes(node, state, context), tracker); // Now mark unambiguous nodes as accepted or rejected root.ForEach(true, (node, state, context) => WalkTreeAcceptOrRejectNodes(context, state, node), CreateState(tracker, acceptedLibraries)); incomplete = root.ForEachGlobalState(false, (node, state) => state || node.Disposition == Disposition.Acceptable); tracker.Clear(); } Cache <TItem> .ReleaseTracker(tracker); root.ForEach((node, context) => WalkTreeDectectConflicts(node, context), CreateState(versionConflicts, acceptedLibraries)); Cache <TItem> .ReleaseDictionary(acceptedLibraries); return(!incomplete); }