Esempio n. 1
0
        public static bool TryResolveConflicts <TItem>(this GraphNode <TItem> root)
        {
            // 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 patience   = 1000;
            var incomplete = true;

            while (incomplete && --patience != 0)
            {
                // Create a picture of what has not been rejected yet
                var tracker = new Tracker <TItem>();

                root.ForEach(true, (node, state) =>
                {
                    if (!state || node.Disposition == Disposition.Rejected)
                    {
                        // Mark all nodes as rejected if they aren't already marked
                        node.Disposition = Disposition.Rejected;
                        return(false);
                    }

                    tracker.Track(node.Item);
                    return(true);
                });

                // Inform tracker of ambiguity beneath nodes that are not resolved yet
                // between:
                // a1->b1->d1->x1
                // a1->c1->d2->z1
                // first attempt
                //  d1/d2 are considered disputed
                //  x1 and z1 are considered ambiguous
                //  d1 is rejected
                // second attempt
                //  d1 is rejected, d2 is accepted
                //  x1 is no longer seen, and z1 is not ambiguous
                //  z1 is accepted

                root.ForEach("Walking", (node, state) =>
                {
                    if (node.Disposition == Disposition.Rejected)
                    {
                        return("Rejected");
                    }

                    if (state == "Walking" && tracker.IsDisputed(node.Item))
                    {
                        return("Ambiguous");
                    }

                    if (state == "Ambiguous")
                    {
                        tracker.MarkAmbiguous(node.Item);
                    }

                    return(state);
                });

                // Now mark unambiguous nodes as accepted or rejected
                root.ForEach(true, (node, state) =>
                {
                    if (!state || node.Disposition == Disposition.Rejected)
                    {
                        return(false);
                    }

                    if (tracker.IsAmbiguous(node.Item))
                    {
                        return(false);
                    }

                    if (node.Disposition == Disposition.Acceptable)
                    {
                        node.Disposition = tracker.IsBestVersion(node.Item) ? Disposition.Accepted : Disposition.Rejected;
                    }

                    return(node.Disposition == Disposition.Accepted);
                });

                incomplete = false;

                root.ForEach(node => incomplete |= node.Disposition == Disposition.Acceptable);
            }

            return(!incomplete);
        }