Esempio n. 1
0
        public async Task<GraphNode> CreateGraphNode(RestoreContext context, LibraryRange libraryRange, Func<string, bool> predicate)
        {
            var dependencies = new List<LibraryDependency>();

            if (context.RuntimeDependencies != null)
            {
                DependencySpec dependencyMapping;
                if (context.RuntimeDependencies.TryGetValue(libraryRange.Name, out dependencyMapping))
                {
                    foreach (var runtimeDependency in dependencyMapping.Implementations.Values)
                    {
                        var libraryDependency = new LibraryDependency
                        {
                            LibraryRange = new LibraryRange(runtimeDependency.Name, frameworkReference: false)
                            {
                                VersionRange = VersionUtility.ParseVersionRange(runtimeDependency.Version)
                            }
                        };

                        // HACK(davidfowl): This is making runtime.json support package redirects
                        if (libraryDependency.LibraryRange.Name == libraryRange.Name)
                        {
                            // It's replacing the current version, we need to override rather than adding a (potentially circular) dependency
                            if (libraryRange.VersionRange != null &&
                                libraryDependency.LibraryRange.VersionRange != null &&
                                libraryRange.VersionRange.MinVersion < libraryDependency.LibraryRange.VersionRange.MinVersion)
                            {
                                libraryRange = libraryDependency.LibraryRange;
                            }
                        }
                        else
                        {
                            // Otherwise it's a dependency of this node
                            dependencies.Add(libraryDependency);
                        }
                    }
                }
            }

            var node = new GraphNode
            {
                LibraryRange = libraryRange,
                Item = await FindLibraryCached(context, libraryRange),
            };

            if (node.Item != null)
            {
                if (node.LibraryRange.VersionRange != null &&
                    node.LibraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None)
                {
                    lock (context.GraphItemCache)
                    {
                        if (!context.GraphItemCache.ContainsKey(node.LibraryRange))
                        {
                            context.GraphItemCache[node.LibraryRange] = Task.FromResult(node.Item);
                        }
                    }
                }

                dependencies.AddRange(node.Item.Dependencies);

                var tasks = new List<Task<GraphNode>>();
                foreach (var dependency in dependencies)
                {
                    if (predicate(dependency.Name))
                    {
                        tasks.Add(CreateGraphNode(context, dependency.LibraryRange, ChainPredicate(predicate, node.Item, dependency)));
                    }
                }

                while (tasks.Any())
                {
                    var task = await Task.WhenAny(tasks);
                    tasks.Remove(task);
                    var dependency = await task;
                    node.Dependencies.Add(dependency);
                }
            }
            return node;
        }
Esempio n. 2
0
        public async Task<GraphNode> CreateGraphNode(RestoreContext context, LibraryRange libraryRange, Func<string, bool> predicate)
        {
            var sw = new Stopwatch();
            sw.Start();

            var node = new GraphNode
            {
                LibraryRange = libraryRange,
                Item = await FindLibraryCached(context, libraryRange),
            };

            if (node.Item != null)
            {
                if (node.LibraryRange.VersionRange != null &&
                    node.LibraryRange.VersionRange.VersionFloatBehavior != SemanticVersionFloatBehavior.None)
                {
                    lock (context.GraphItemCache)
                    {
                        if (!context.GraphItemCache.ContainsKey(node.LibraryRange))
                        {
                            context.GraphItemCache[node.LibraryRange] = Task.FromResult(node.Item);
                        }
                    }
                }

                var tasks = new List<Task<GraphNode>>();
                var dependencies = node.Item.Dependencies ?? Enumerable.Empty<LibraryDependency>();
                foreach (var dependency in dependencies)
                {
                    if (predicate(dependency.Name))
                    {
                        tasks.Add(CreateGraphNode(context, dependency.LibraryRange, ChainPredicate(predicate, node.Item, dependency)));

                        if (context.RuntimeSpecs != null)
                        {
                            foreach (var runtimeSpec in context.RuntimeSpecs)
                            {
                                DependencySpec dependencyMapping;
                                if (runtimeSpec.Dependencies.TryGetValue(dependency.Name, out dependencyMapping))
                                {
                                    foreach (var dependencyImplementation in dependencyMapping.Implementations.Values)
                                    {
                                        tasks.Add(CreateGraphNode(
                                            context,
                                            new LibraryRange(dependencyImplementation.Name, frameworkReference: false)
                                            {
                                                VersionRange = VersionUtility.ParseVersionRange(dependencyImplementation.Version)
                                            },
                                            ChainPredicate(predicate, node.Item, dependency)));
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }

                while (tasks.Any())
                {
                    var task = await Task.WhenAny(tasks);
                    tasks.Remove(task);
                    var dependency = await task;
                    node.Dependencies.Add(dependency);
                }
            }
            return node;
        }
Esempio n. 3
0
        void ForEach <TState>(GraphNode node, TState state, Func <GraphNode, TState, TState> callback)
        {
            var childState = callback(node, state);

            ForEach(node.Dependencies, childState, callback);
        }
Esempio n. 4
0
        private void Reduce(GraphNode root)
        {
            var patience   = 1000;
            var incomplete = true;

            while (incomplete && --patience != 0)
            {
                var tracker = new Tracker();

                // track non-rejected, apply rejection recursively
                ForEach(root, true, (node, state) =>
                {
                    if (!state || node.Disposition == GraphNode.DispositionType.Rejected)
                    {
                        node.Disposition = GraphNode.DispositionType.Rejected;
                    }
                    else
                    {
                        var lib = node?.Item?.Match?.Library;
                        if (lib != null)
                        {
                            tracker.Track(
                                lib.Name,
                                lib.Version);
                        }
                    }
                    return(node.Disposition != GraphNode.DispositionType.Rejected);
                });

                // mark items under disputed nodes as ambiguous
                ForEach(root, "Walking", (node, state) =>
                {
                    if (node.Disposition == GraphNode.DispositionType.Rejected)
                    {
                        return("Rejected");
                    }

                    var lib = node?.Item?.Match?.Library;
                    if (lib == null)
                    {
                        return(state);
                    }

                    if (state == "Walking" && tracker.IsDisputed(node.Item.Match.Library.Name))
                    {
                        return("Disputed");
                    }

                    if (state == "Disputed")
                    {
                        tracker.MarkAmbiguous(node.Item.Match.Library.Name);
                    }

                    return(state);
                });

                // accept or reject nodes that are acceptable and not ambiguous
                ForEach(root, true, (node, state) =>
                {
                    if (!state ||
                        node.Disposition == GraphNode.DispositionType.Rejected ||
                        tracker.IsAmbiguous(node?.Item?.Match?.Library?.Name))
                    {
                        return(false);
                    }

                    if (node.Disposition == GraphNode.DispositionType.Acceptable)
                    {
                        var isBestVersion = tracker.IsBestVersion(
                            node?.Item?.Match?.Library?.Name,
                            node?.Item?.Match?.Library?.Version);
                        node.Disposition = isBestVersion ? GraphNode.DispositionType.Accepted : GraphNode.DispositionType.Rejected;
                    }

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

                incomplete = false;

                ForEach(root, node => incomplete |= node.Disposition == GraphNode.DispositionType.Acceptable);
            }
        }
Esempio n. 5
0
 void ForEach(GraphNode node, Action <GraphNode> callback)
 {
     callback(node);
     ForEach(node.Dependencies, callback);
 }