示例#1
0
        public void FindRuntimeDependencies_VerifyCaching()
        {
            var graph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("a", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("y", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("b", new[] { "a" }),
                new RuntimeDescription("c", new[] { "b" }),
                new RuntimeDescription("d", new[] { "c" }),
            });

            var dependenciesA = graph.FindRuntimeDependencies("d", "x");
            var dependenciesB = graph.FindRuntimeDependencies("d", "x");

            ReferenceEquals(dependenciesA, dependenciesB).Should().BeTrue();
        }
示例#2
0
        public void FindRuntimeDependencies_VerifyPackageIdIsCaseInsensitive()
        {
            var graph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("a", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("y", VersionRange.Parse("1.0.0")) }) })
            });

            var dependencies = graph.FindRuntimeDependencies("a", "X").ToList();

            dependencies.Count.Should().Be(1);
            dependencies[0].Id.Should().Be("y");
            dependencies[0].VersionRange.ToShortString().Should().Be("1.0.0");
        }
示例#3
0
        public void FindRuntimeDependencies_VerifyDependencyOnCompatibleRID()
        {
            var graph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("a", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("y", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("b", new[] { "a" }),
                new RuntimeDescription("c", new[] { "b" }),
                new RuntimeDescription("d", new[] { "c" }),
            });

            var dependencies = graph.FindRuntimeDependencies("d", "x").ToList();

            dependencies.Count.Should().Be(1);
            dependencies[0].Id.Should().Be("y");
            dependencies[0].VersionRange.ToShortString().Should().Be("1.0.0");
        }
示例#4
0
        public void FindRuntimeDependencies_MultipleDependenciesWithTieVerifyResult()
        {
            // A -> B and A -> C where both have dependencies
            var graph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("a", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("y", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("b", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("z", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("c", new[] { "a", "b" }),
            });

            var dependencies = graph.FindRuntimeDependencies("c", "x").ToList();

            dependencies.Count.Should().Be(1);
            dependencies[0].Id.Should().Be("y");
            dependencies[0].VersionRange.ToShortString().Should().Be("1.0.0");
        }
示例#5
0
        public void FindRuntimeDependencies_MultipleDependenciesWithTieInTreeVerifyResult2()
        {
            // C
            // - B
            // --- A
            // ----- AA -> Y 1.0.0
            // - F
            // --- E -> Z 1.0.0
            var graph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("aa", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("y", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("e", new[] { new RuntimeDependencySet("x", new[] { new RuntimePackageDependency("z", VersionRange.Parse("1.0.0")) }) }),
                new RuntimeDescription("a", new[] { "aa" }),
                new RuntimeDescription("b", new[] { "a" }),
                new RuntimeDescription("f", new[] { "e" }),
                new RuntimeDescription("c", new[] { "b", "f" }),
            });

            var dependencies = graph.FindRuntimeDependencies("c", "x").ToList();

            dependencies.Count.Should().Be(1);
            dependencies[0].Id.Should().Be("z");
            dependencies[0].VersionRange.ToShortString().Should().Be("1.0.0");
        }
        private async Task <GraphNode <RemoteResolveResult> > CreateGraphNode(
            LibraryRange libraryRange,
            NuGetFramework framework,
            string runtimeName,
            RuntimeGraph runtimeGraph,
            Func <LibraryRange, DependencyResult> predicate,
            GraphEdge <RemoteResolveResult> outerEdge)
        {
            var dependencies        = new List <LibraryDependency>();
            var runtimeDependencies = new HashSet <string>();

            if (!string.IsNullOrEmpty(runtimeName) && runtimeGraph != null)
            {
                // HACK(davidfowl): This is making runtime.json support package redirects

                // Look up any additional dependencies for this package
                foreach (var runtimeDependency in runtimeGraph.FindRuntimeDependencies(runtimeName, libraryRange.Name))
                {
                    var libraryDependency = new LibraryDependency
                    {
                        LibraryRange = new LibraryRange()
                        {
                            Name           = runtimeDependency.Id,
                            VersionRange   = runtimeDependency.VersionRange,
                            TypeConstraint = LibraryDependencyTarget.PackageProjectExternal
                        }
                    };

                    if (StringComparer.OrdinalIgnoreCase.Equals(runtimeDependency.Id, libraryRange.Name))
                    {
                        if (libraryRange.VersionRange != null &&
                            runtimeDependency.VersionRange != null &&
                            libraryRange.VersionRange.MinVersion < runtimeDependency.VersionRange.MinVersion)
                        {
                            libraryRange = libraryDependency.LibraryRange;
                        }
                    }
                    else
                    {
                        // Otherwise it's a dependency of this node
                        dependencies.Add(libraryDependency);
                        runtimeDependencies.Add(libraryDependency.Name);
                    }
                }
            }

            var node = new GraphNode <RemoteResolveResult>(libraryRange)
            {
                // Resolve the dependency from the cache or sources
                Item = await FindLibraryCached(
                    _context.FindLibraryEntryCache,
                    libraryRange,
                    framework,
                    outerEdge,
                    CancellationToken.None)
            };

            Debug.Assert(node.Item != null, "FindLibraryCached should return an unresolved item instead of null");
            if (node.Key.VersionRange != null &&
                node.Key.VersionRange.IsFloating)
            {
                var cacheKey = new LibraryRangeCacheKey(node.Key, framework);

                _context.FindLibraryEntryCache.TryAdd(cacheKey, Task.FromResult(node.Item));
            }

            var tasks = new List <Task <GraphNode <RemoteResolveResult> > >();

            if (dependencies.Count > 0)
            {
                // Create a new item on this node so that we can update it with the new dependencies from
                // runtime.json files
                // We need to clone the item since they can be shared across multiple nodes
                node.Item = new GraphItem <RemoteResolveResult>(node.Item.Key)
                {
                    Data = new RemoteResolveResult()
                    {
                        Dependencies = dependencies.Concat(node.Item.Data.Dependencies.Where(d => !runtimeDependencies.Contains(d.Name))).ToList(),
                        Match        = node.Item.Data.Match
                    }
                };
            }

            foreach (var dependency in node.Item.Data.Dependencies)
            {
                // Skip dependencies if the dependency edge has 'all' excluded and
                // the node is not a direct dependency.
                if (outerEdge == null ||
                    dependency.SuppressParent != LibraryIncludeFlags.All)
                {
                    var result = predicate(dependency.LibraryRange);

                    if (result == DependencyResult.Acceptable)
                    {
                        // Dependency edge from the current node to the dependency
                        var innerEdge = new GraphEdge <RemoteResolveResult>(outerEdge, node.Item, dependency);

                        tasks.Add(CreateGraphNode(
                                      dependency.LibraryRange,
                                      framework,
                                      runtimeName,
                                      runtimeGraph,
                                      ChainPredicate(predicate, node, dependency),
                                      innerEdge));
                    }
                    else
                    {
                        // Keep the node in the tree if we need to look at it later
                        if (result == DependencyResult.PotentiallyDowngraded ||
                            result == DependencyResult.Cycle)
                        {
                            var dependencyNode = new GraphNode <RemoteResolveResult>(dependency.LibraryRange)
                            {
                                Disposition = result == DependencyResult.Cycle ? Disposition.Cycle : Disposition.PotentiallyDowngraded
                            };

                            dependencyNode.OuterNode = node;
                            node.InnerNodes.Add(dependencyNode);
                        }
                    }
                }
            }

            while (tasks.Any())
            {
                // Wait for any node to finish resolving
                var task = await Task.WhenAny(tasks);

                // Extract the resolved node
                tasks.Remove(task);
                var dependencyNode = await task;
                dependencyNode.OuterNode = node;

                node.InnerNodes.Add(dependencyNode);
            }

            return(node);
        }
示例#7
0
        private async Task <GraphNode <RemoteResolveResult> > CreateGraphNode(Dictionary <LibraryRange, Task <GraphItem <RemoteResolveResult> > > cache, LibraryRange libraryRange, NuGetFramework framework, string runtimeName, RuntimeGraph runtimeGraph, Func <string, bool> predicate)
        {
            var node = new GraphNode <RemoteResolveResult>(libraryRange)
            {
                Item = await FindLibraryCached(cache, libraryRange, framework),
            };

            if (node.Item == null)
            {
                // Reject null items
                node.Disposition = Disposition.Rejected;
            }
            else
            {
                if (node.Key.VersionRange != null &&
                    node.Key.VersionRange.IsFloating)
                {
                    lock (cache)
                    {
                        if (!cache.ContainsKey(node.Key))
                        {
                            cache[node.Key] = Task.FromResult(node.Item);
                        }
                    }
                }

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

                        if (!string.IsNullOrEmpty(runtimeName) && runtimeGraph != null)
                        {
                            // Look up any additional dependencies for this package
                            foreach (var runtimeDependency in runtimeGraph.FindRuntimeDependencies(runtimeName, dependency.Name))
                            {
                                // Add the dependency to the tasks
                                var runtimeLibraryRange = new LibraryRange()
                                {
                                    Name         = runtimeDependency.Id,
                                    VersionRange = runtimeDependency.VersionRange
                                };
                                tasks.Add(CreateGraphNode(
                                              cache,
                                              runtimeLibraryRange,
                                              framework,
                                              runtimeName,
                                              runtimeGraph,
                                              ChainPredicate(predicate, node.Item, dependency)));
                            }
                        }
                    }
                }

                while (tasks.Any())
                {
                    var task = await Task.WhenAny(tasks);

                    tasks.Remove(task);
                    var dependencyNode = await task;
                    // Not required for anything
                    dependencyNode.OuterNode = node;
                    node.InnerNodes.Add(dependencyNode);
                }
            }

            return(node);
        }
示例#8
0
        private async Task<GraphNode<RemoteResolveResult>> CreateGraphNode(Dictionary<LibraryRange, Task<GraphItem<RemoteResolveResult>>> cache, LibraryRange libraryRange, NuGetFramework framework, string runtimeName, RuntimeGraph runtimeGraph, Func<string, bool> predicate)
        {
            var node = new GraphNode<RemoteResolveResult>(libraryRange)
            {
                Item = await FindLibraryCached(cache, libraryRange, framework),
            };

            if (node.Item == null)
            {
                // Reject null items
                node.Disposition = Disposition.Rejected;
            }
            else
            {
                if (node.Key.VersionRange != null
                    &&
                    node.Key.VersionRange.IsFloating)
                {
                    lock (cache)
                    {
                        if (!cache.ContainsKey(node.Key))
                        {
                            cache[node.Key] = Task.FromResult(node.Item);
                        }
                    }
                }

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

                        if (!string.IsNullOrEmpty(runtimeName)
                            && runtimeGraph != null)
                        {
                            // Look up any additional dependencies for this package
                            foreach (var runtimeDependency in runtimeGraph.FindRuntimeDependencies(runtimeName, dependency.Name))
                            {
                                // Add the dependency to the tasks
                                var runtimeLibraryRange = new LibraryRange()
                                {
                                    Name = runtimeDependency.Id,
                                    VersionRange = runtimeDependency.VersionRange
                                };
                                tasks.Add(CreateGraphNode(
                                    cache,
                                    runtimeLibraryRange,
                                    framework,
                                    runtimeName,
                                    runtimeGraph,
                                    ChainPredicate(predicate, node.Item, dependency)));
                            }
                        }
                    }
                }

                while (tasks.Any())
                {
                    var task = await Task.WhenAny(tasks);
                    tasks.Remove(task);
                    var dependencyNode = await task;
                    // Not required for anything
                    dependencyNode.OuterNode = node;
                    node.InnerNodes.Add(dependencyNode);
                }
            }

            return node;
        }