/// <summary>
        /// Runs GenerateRuntimeGraph task specifying AdditionalRuntimeIdentifiers then asserts that the
        /// generated runtime.json has the expected additions (and no more).
        /// </summary>
        /// <param name="additionalRIDs">additional RIDs</param>
        /// <param name="expectedAdditions">entries that are expected to be added to the RuntimeGraph</param>
        /// <param name="additionalRIDParent">parent to use when adding a new RID</param>
        /// <param name="runtimeFilePrefix">a unique prefix to use for the generated </param>
        private void AssertRuntimeGraphAdditions(string[] additionalRIDs, RuntimeDescription[] expectedAdditions, string additionalRIDParent = null, [CallerMemberName] string runtimeFilePrefix = null)
        {
            string runtimeFile = Path.Combine(defaultRootPath, runtimeFilePrefix + ".runtime.json");

            GenerateRuntimeGraph task = new GenerateRuntimeGraph()
            {
                BuildEngine   = _engine,
                RuntimeGroups = DefaultRuntimeGroupItems,
                RuntimeJson   = runtimeFile,
                AdditionalRuntimeIdentifiers      = additionalRIDs,
                AdditionalRuntimeIdentifierParent = additionalRIDParent,
                UpdateRuntimeFiles = true
            };

            _log.Reset();
            task.Execute();
            _log.AssertNoErrorsOrWarnings();

            RuntimeGraph expected = RuntimeGraph.Merge(
                JsonRuntimeFormat.ReadRuntimeGraph(defaultRuntimeFile),
                new RuntimeGraph(expectedAdditions));

            RuntimeGraph actual = JsonRuntimeFormat.ReadRuntimeGraph(runtimeFile);

            // Should this assert fail, it's helpful to diff defaultRuntimeFile and runtimeFile to see the additions.
            Assert.Equal(expected, actual);
        }
示例#2
0
        public void MergingCombinesDependencySetsInRuntimesDefinedInBoth()
        {
            var leftGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" }, new[]
                {
                    new RuntimeDependencySet("Foo"),
                })
            });
            var rightGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("win8", new[]
                {
                    new RuntimeDependencySet("Bar")
                })
            });
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            Assert.Equal(new RuntimeGraph(new[]
            {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" }, new[]
                {
                    new RuntimeDependencySet("Foo"),
                    new RuntimeDependencySet("Bar")
                }),
            }), graph);
        }
示例#3
0
        public void MergingCombinesDependenciesInDependencySetsDefinedInBoth()
        {
            var leftGraph = new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" }, new [] {
                    new RuntimeDependencySet("Foo", new [] {
                        new RuntimePackageDependency("Foo.win8", new VersionRange(new NuGetVersion(1, 2, 3)))
                    }),
                })
            });
            var rightGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("win8", new[] {
                    new RuntimeDependencySet("Foo", new [] {
                        new RuntimePackageDependency("Foo.more.win8", new VersionRange(new NuGetVersion(4, 5, 6)))
                    }),
                })
            });
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            Assert.Equal(new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" }, new [] {
                    new RuntimeDependencySet("Foo", new [] {
                        new RuntimePackageDependency("Foo.win8", new VersionRange(new NuGetVersion(1, 2, 3))),
                        new RuntimePackageDependency("Foo.more.win8", new VersionRange(new NuGetVersion(4, 5, 6)))
                    }),
                }),
            }), leftGraph);
        }
        /// <summary>
        /// Merge all runtime.json found in the flattened graph.
        /// </summary>
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories, RuntimeGraph projectRuntimeGraph)
        {
            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            var runtimeGraph = projectRuntimeGraph ?? RuntimeGraph.Empty;

            // Find runtime.json files using the flattened graph which is unique per id.
            // Using the flattened graph ensures that only accepted packages will be used.
            foreach (var node in graph.Flattened)
            {
                var match = node.Data?.Match;
                if (match == null || match.Library.Type != LibraryType.Package)
                {
                    // runtime.json can only exist in packages
                    continue;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                // Unresolved packages may not exist.
                if (info != null)
                {
                    var nextGraph = info.Package.RuntimeGraph;
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            }

            return(runtimeGraph);
        }
示例#5
0
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories)
        {
            // TODO: Caching!
            RuntimeGraph runtimeGraph;

            if (_request.RuntimeGraphCache.TryGetValue(graph.Framework, out runtimeGraph))
            {
                return(runtimeGraph);
            }

            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            runtimeGraph = RuntimeGraph.Empty;

            // maintain visited nodes to avoid duplicate runtime graph for the same node
            var visitedNodes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            graph.Graphs.ForEach(node =>
            {
                var match = node?.Item?.Data?.Match;
                if (match == null)
                {
                    return;
                }

                // Ignore runtime.json from rejected nodes
                if (node.Disposition == Disposition.Rejected)
                {
                    return;
                }

                // ignore the same node again
                if (!visitedNodes.Add(match.Library.Name))
                {
                    return;
                }

                // runtime.json can only exist in packages
                if (match.Library.Type != LibraryType.Package)
                {
                    return;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                if (info != null)
                {
                    var package   = info.Package;
                    var nextGraph = LoadRuntimeGraph(package);
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            });
            _request.RuntimeGraphCache[graph.Framework] = runtimeGraph;
            return(runtimeGraph);
        }
示例#6
0
        public void MergingInEmptyGraphHasNoEffect()
        {
            var graph = new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any" })
            });
            var newGraph = RuntimeGraph.Merge(graph, RuntimeGraph.Empty);

            Assert.Equal(new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any" })
            }), newGraph);
        }
示例#7
0
        public void MergeReplacesCompatibilityProfilesDefinedInRightIntoLeftIfLeftIsEmpty()
        {
            var leftGraph = new RuntimeGraph(new[]
            {
                new CompatibilityProfile("frob")
            });
            var rightGraph = new RuntimeGraph(new[]
            {
                new CompatibilityProfile("frob", new []
                {
                    new FrameworkRuntimePair(FrameworkConstants.CommonFrameworks.DnxCore50, "blob")
                })
            });
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            Assert.Equal(rightGraph, graph);
        }
示例#8
0
        public void MergingAddsCompletelyNewRuntimes()
        {
            var leftGraph = new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" })
            });
            var rightGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("win7")
            });
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            Assert.Equal(new RuntimeGraph(new[] {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any", "win7" }),
                new RuntimeDescription("win7")
            }), graph);
        }
示例#9
0
        public static RuntimeGraph Collect(IEnumerable <LibraryDescription> libraries)
        {
            var graph = RuntimeGraph.Empty;

            foreach (var library in libraries)
            {
                if (library.Identity.Type == LibraryType.Package)
                {
                    var runtimeJson = ((PackageDescription)library).PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
                    if (runtimeJson != null)
                    {
                        var runtimeJsonFullName = Path.Combine(library.Path, runtimeJson);
                        graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName));
                    }
                }
            }
            return(graph);
        }
示例#10
0
        public NuGet.RuntimeModel.RuntimeGraph Collect(IEnumerable <LibraryExport> exports)
        {
            var graph = RuntimeGraph.Empty;

            foreach (var export in exports)
            {
                if (export.Library.Identity.Type == LibraryType.Package)
                {
                    var runtimeJson = ((PackageDescription)export.Library).PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
                    if (runtimeJson != null)
                    {
                        var runtimeJsonFullName = Path.Combine(export.Library.Path, runtimeJson);
                        graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName));
                    }
                }
            }
            return(graph);
        }
示例#11
0
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories)
        {
            // TODO: Caching!
            RuntimeGraph runtimeGraph;

            if (_request.RuntimeGraphCache.TryGetValue(graph.Framework, out runtimeGraph))
            {
                return(runtimeGraph);
            }

            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            runtimeGraph = RuntimeGraph.Empty;
            graph.Graphs.ForEach(node =>
            {
                var match = node?.Item?.Data?.Match;
                if (match == null)
                {
                    return;
                }

                // Ignore runtime.json from rejected nodes
                if (node.Disposition == Disposition.Rejected)
                {
                    return;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                if (info != null)
                {
                    var package   = info.Package;
                    var nextGraph = LoadRuntimeGraph(package);
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            });
            _request.RuntimeGraphCache[graph.Framework] = runtimeGraph;
            return(runtimeGraph);
        }
        private static IEnumerable <RuntimeFallbacks> GetRuntimeFallbacks(string[] runtimeGraphFiles, string runtime)
        {
            RuntimeGraph runtimeGraph = RuntimeGraph.Empty;

            foreach (string runtimeGraphFile in runtimeGraphFiles)
            {
                runtimeGraph = RuntimeGraph.Merge(runtimeGraph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeGraphFile));
            }

            foreach (string rid in runtimeGraph.Runtimes.Select(p => p.Key))
            {
                IEnumerable <string> ridFallback = runtimeGraph.ExpandRuntime(rid);

                if (ridFallback.Contains(runtime))
                {
                    // ExpandRuntime return runtime itself as first item so we are skiping it
                    yield return(new RuntimeFallbacks(rid, ridFallback.Skip(1)));
                }
            }
        }
示例#13
0
        public void AreCompatible_VerifyCaseSensitiveCheck()
        {
            var leftGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("win7"),
                new RuntimeDescription("win8", new[] { "win7" })
            });

            var rightGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("WIN7"),
                new RuntimeDescription("WIN8", new[] { "WIN7" })
            });

            // Merge
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            graph.AreCompatible("WIN8", "win7").Should().BeFalse();
            graph.AreCompatible("win8", "WIN7").Should().BeFalse();
        }
示例#14
0
        private RuntimeGraph SafeMerge(RuntimeGraph existingGraph, RuntimeGroup runtimeGroup)
        {
            var runtimeGraph = runtimeGroup.GetRuntimeGraph();

            foreach (var existingRuntimeDescription in existingGraph.Runtimes.Values)
            {
                RuntimeDescription newRuntimeDescription;

                if (runtimeGraph.Runtimes.TryGetValue(existingRuntimeDescription.RuntimeIdentifier, out newRuntimeDescription))
                {
                    // overlapping RID, ensure that the imports match (same ordering and content)
                    if (!existingRuntimeDescription.InheritedRuntimes.SequenceEqual(newRuntimeDescription.InheritedRuntimes))
                    {
                        Log.LogError($"RuntimeGroup {runtimeGroup.BaseRID} defines RID {newRuntimeDescription.RuntimeIdentifier} with imports {String.Join(";", newRuntimeDescription.InheritedRuntimes)} which differ from existing imports {String.Join(";", existingRuntimeDescription.InheritedRuntimes)}.  You may avoid this by specifying {nameof(RuntimeGroup.OmitRIDDefinitions)} metadata with {newRuntimeDescription.RuntimeIdentifier}.");
                    }
                }
            }

            return(RuntimeGraph.Merge(existingGraph, runtimeGraph));
        }
示例#15
0
        public void GivenDifferentCasingsVerifyMergeKeepsBoth()
        {
            var leftGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("any"),
                new RuntimeDescription("win8", new[] { "any" })
            });

            var rightGraph = new RuntimeGraph(new[]
            {
                new RuntimeDescription("any"),
                new RuntimeDescription("WIN8", new[] { "any" })
            });

            // Merge
            var graph = RuntimeGraph.Merge(leftGraph, rightGraph);

            graph.Runtimes.Keys.Should().BeEquivalentTo(new List <string>()
            {
                "any", "win8", "WIN8"
            });
        }
        public RuntimeGraph Collect(LockFile lockFile)
        {
            string userPackageFolder = lockFile.PackageFolders.FirstOrDefault()?.Path;
            var    fallBackFolders   = lockFile.PackageFolders.Skip(1).Select(f => f.Path);
            var    packageResolver   = new FallbackPackagePathResolver(userPackageFolder, fallBackFolders);

            var graph = RuntimeGraph.Empty;

            foreach (var library in lockFile.Libraries)
            {
                if (string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
                {
                    var runtimeJson = library.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
                    if (runtimeJson != null)
                    {
                        var libraryPath         = packageResolver.GetPackageDirectory(library.Name, library.Version);
                        var runtimeJsonFullName = Path.Combine(libraryPath, runtimeJson);
                        graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName));
                    }
                }
            }
            return(graph);
        }
示例#17
0
        public NuGet.RuntimeModel.RuntimeGraph Collect(IEnumerable <LibraryExport> exports)
        {
            var graph = RuntimeGraph.Empty;

            foreach (var export in exports)
            {
                if (export.Library.Identity.Type == LibraryType.Package)
                {
                    PackageDescription description = (PackageDescription)export.Library;
                    var runtimeJson = description.PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName);
                    if (runtimeJson != null)
                    {
                        // Convert the package-name to lower-case in the path to lookup runtime.json
                        string lowercasedPackageName = description.Identity.Name.ToLower();
                        string pathToPackage         = export.Library.Path.Replace(description.Identity.Name, lowercasedPackageName);

                        var runtimeJsonFullName = Path.Combine(pathToPackage, runtimeJson);
                        graph = RuntimeGraph.Merge(graph, JsonRuntimeFormat.ReadRuntimeGraph(runtimeJsonFullName));
                    }
                }
            }
            return(graph);
        }
示例#18
0
        private Task <RestoreTargetGraph[]> WalkRuntimeDependencies(LibraryRange projectRange, RestoreTargetGraph graph, RuntimeGraph projectRuntimeGraph, RemoteDependencyWalker walker, RemoteWalkContext context, NuGetv3LocalRepository localRepository)
        {
            // Load runtime specs
            _log.LogVerbose("Scanning packages for runtime.json files...");
            var runtimeGraph = projectRuntimeGraph;

            graph.Graph.ForEach(node =>
            {
                var match = node?.Item?.Data?.Match;
                if (match == null)
                {
                    return;
                }

                // Locate the package in the local repository
                var package = localRepository.FindPackagesById(match.Library.Name).FirstOrDefault(p => p.Version == match.Library.Version);
                if (package != null)
                {
                    var nextGraph = LoadRuntimeGraph(package);
                    if (nextGraph != null)
                    {
                        _log.LogVerbose($"Merging in runtimes defined in {match.Library}");
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            });

            var resultGraphs = new List <Task <RestoreTargetGraph> >();

            foreach (var runtimeName in projectRuntimeGraph.Runtimes.Keys)
            {
                _log.LogInformation($"Restoring packages for {graph.Framework} on {runtimeName}");
                resultGraphs.Add(WalkDependencies(projectRange, graph.Framework, runtimeName, runtimeGraph, walker, context));
            }

            return(Task.WhenAll(resultGraphs));
        }
示例#19
0
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestore(LibraryRange projectRange,
                                                                                              IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                              HashSet <LibraryIdentity> allInstalledPackages,
                                                                                              NuGetv3LocalRepository userPackageFolder,
                                                                                              IReadOnlyList <NuGetv3LocalRepository> fallbackPackageFolders,
                                                                                              RemoteDependencyWalker remoteWalker,
                                                                                              RemoteWalkContext context,
                                                                                              bool forceRuntimeGraphCreation,
                                                                                              CancellationToken token)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            if (!ResolutionSucceeded(frameworkGraphs))
            {
                return(Tuple.Create(false, graphs, allRuntimes));
            }

            await InstallPackagesAsync(graphs,
                                       _request.PackagesDirectory,
                                       allInstalledPackages,
                                       _request.MaxDegreeOfConcurrency,
                                       token);

            // Clear the in-memory cache for newly installed packages
            userPackageFolder.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));

            var localRepositories = new List <NuGetv3LocalRepository>();

            localRepositories.Add(userPackageFolder);
            localRepositories.AddRange(fallbackPackageFolders);

            // Check if any non-empty RIDs exist before reading the runtime graph (runtime.json).
            // Searching all packages for runtime.json and building the graph can be expensive.
            var hasNonEmptyRIDs = frameworkRuntimePairs.Any(
                tfmRidPair => !string.IsNullOrEmpty(tfmRidPair.RuntimeIdentifier));

            // The runtime graph needs to be created for scenarios with supports, forceRuntimeGraphCreation allows this.
            // Resolve runtime dependencies
            if (hasNonEmptyRIDs || forceRuntimeGraphCreation)
            {
                var runtimeGraphs = new List <RestoreTargetGraph>();

                var runtimeTasks = new List <Task <RestoreTargetGraph[]> >();
                foreach (var graph in graphs)
                {
                    // Get the runtime graph for this specific tfm graph
                    var runtimeGraph = GetRuntimeGraph(graph, localRepositories);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  runtimeGraph,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                if (!ResolutionSucceeded(runtimeGraphs))
                {
                    return(Tuple.Create(false, graphs, allRuntimes));
                }

                // Install runtime-specific packages
                await InstallPackagesAsync(runtimeGraphs,
                                           _request.PackagesDirectory,
                                           allInstalledPackages,
                                           _request.MaxDegreeOfConcurrency,
                                           token);

                // Clear the in-memory cache for newly installed packages
                userPackageFolder.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));
            }

            return(Tuple.Create(true, graphs, allRuntimes));
        }
示例#20
0
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestore(LibraryRange projectRange,
                                                                                              IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                              HashSet <LibraryIdentity> allInstalledPackages,
                                                                                              NuGetv3LocalRepository localRepository,
                                                                                              RemoteDependencyWalker remoteWalker,
                                                                                              RemoteWalkContext context,
                                                                                              bool writeToLockFile,
                                                                                              CancellationToken token)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         writeToLockFile: writeToLockFile,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            if (!ResolutionSucceeded(frameworkGraphs))
            {
                return(Tuple.Create(false, graphs, allRuntimes));
            }

            await InstallPackagesAsync(graphs,
                                       _request.PackagesDirectory,
                                       allInstalledPackages,
                                       _request.MaxDegreeOfConcurrency,
                                       token);

            // Clear the in-memory cache for newly installed packages
            localRepository.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));

            // Resolve runtime dependencies
            var runtimeGraphs = new List <RestoreTargetGraph>();

            if (runtimesByFramework.Count > 0)
            {
                var runtimeTasks = new List <Task <RestoreTargetGraph[]> >();
                foreach (var graph in graphs)
                {
                    // Get the runtime graph for this specific tfm graph
                    var runtimeGraph = GetRuntimeGraph(graph, localRepository);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  localRepository,
                                                                  runtimeGraph,
                                                                  writeToLockFile: writeToLockFile,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                if (!ResolutionSucceeded(runtimeGraphs))
                {
                    return(Tuple.Create(false, graphs, allRuntimes));
                }

                // Install runtime-specific packages
                await InstallPackagesAsync(runtimeGraphs,
                                           _request.PackagesDirectory,
                                           allInstalledPackages,
                                           _request.MaxDegreeOfConcurrency,
                                           token);

                // Clear the in-memory cache for newly installed packages
                localRepository.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));
            }

            return(Tuple.Create(true, graphs, allRuntimes));
        }
示例#21
0
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestoreAsync(LibraryRange projectRange,
                                                                                                   IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                                   NuGetv3LocalRepository userPackageFolder,
                                                                                                   IReadOnlyList <NuGetv3LocalRepository> fallbackPackageFolders,
                                                                                                   RemoteDependencyWalker remoteWalker,
                                                                                                   RemoteWalkContext context,
                                                                                                   bool forceRuntimeGraphCreation,
                                                                                                   CancellationToken token)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            await InstallPackagesAsync(graphs,
                                       userPackageFolder,
                                       token);

            var localRepositories = new List <NuGetv3LocalRepository>();

            localRepositories.Add(userPackageFolder);
            localRepositories.AddRange(fallbackPackageFolders);

            // Check if any non-empty RIDs exist before reading the runtime graph (runtime.json).
            // Searching all packages for runtime.json and building the graph can be expensive.
            var hasNonEmptyRIDs = frameworkRuntimePairs.Any(
                tfmRidPair => !string.IsNullOrEmpty(tfmRidPair.RuntimeIdentifier));

            // The runtime graph needs to be created for scenarios with supports, forceRuntimeGraphCreation allows this.
            // Resolve runtime dependencies
            if (hasNonEmptyRIDs || forceRuntimeGraphCreation)
            {
                var runtimeGraphs = new List <RestoreTargetGraph>();

                var runtimeTasks = new List <Task <RestoreTargetGraph[]> >();
                foreach (var graph in graphs)
                {
                    // Get the runtime graph for this specific tfm graph
                    var runtimeGraph = GetRuntimeGraph(graph, localRepositories);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  runtimeGraph,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                // Install runtime-specific packages
                await InstallPackagesAsync(runtimeGraphs,
                                           userPackageFolder,
                                           token);
            }

            // Update the logger with the restore target graphs
            // This allows lazy initialization for the Transitive Warning Properties
            _logger.ApplyRestoreOutput(graphs);

            // Warn for all dependencies that do not have exact matches or
            // versions that have been bumped up unexpectedly.
            await UnexpectedDependencyMessages.LogAsync(graphs, _request.Project, _logger);

            var success = await ResolutionSucceeded(graphs, context, token);

            return(Tuple.Create(success, graphs, allRuntimes));
        }
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestoreAsync(LibraryRange projectRange,
                                                                                                   IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                                   NuGetv3LocalRepository userPackageFolder,
                                                                                                   IReadOnlyList <NuGetv3LocalRepository> fallbackPackageFolders,
                                                                                                   RemoteDependencyWalker remoteWalker,
                                                                                                   RemoteWalkContext context,
                                                                                                   bool forceRuntimeGraphCreation,
                                                                                                   CancellationToken token,
                                                                                                   TelemetryActivity telemetryActivity)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);
            var success             = true;

            telemetryActivity.StartIntervalMeasure();

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            telemetryActivity.EndIntervalMeasure(WalkFrameworkDependencyDuration);

            telemetryActivity.StartIntervalMeasure();

            var downloadDependencyResolutionTasks = new List <Task <DownloadDependencyResolutionResult> >();
            var ddLibraryRangeToRemoteMatchCache  = new ConcurrentDictionary <LibraryRange, Task <Tuple <LibraryRange, RemoteMatch> > >();

            foreach (var targetFrameworkInformation in _request.Project.TargetFrameworks)
            {
                downloadDependencyResolutionTasks.Add(ResolveDownloadDependencies(
                                                          context,
                                                          ddLibraryRangeToRemoteMatchCache,
                                                          targetFrameworkInformation,
                                                          token));
            }

            var downloadDependencyResolutionResults = await Task.WhenAll(downloadDependencyResolutionTasks);

            telemetryActivity.EndIntervalMeasure(EvaluateDownloadDependenciesDuration);

            var uniquePackages = new HashSet <LibraryIdentity>();

            success &= await InstallPackagesAsync(
                uniquePackages,
                graphs,
                downloadDependencyResolutionResults,
                userPackageFolder,
                token);

            // Check if any non-empty RIDs exist before reading the runtime graph (runtime.json).
            // Searching all packages for runtime.json and building the graph can be expensive.
            var hasNonEmptyRIDs = frameworkRuntimePairs.Any(
                tfmRidPair => !string.IsNullOrEmpty(tfmRidPair.RuntimeIdentifier));

            // The runtime graph needs to be created for scenarios with supports, forceRuntimeGraphCreation allows this.
            // Resolve runtime dependencies
            if (hasNonEmptyRIDs || forceRuntimeGraphCreation)
            {
                telemetryActivity.StartIntervalMeasure();

                var localRepositories = new List <NuGetv3LocalRepository>();
                localRepositories.Add(userPackageFolder);
                localRepositories.AddRange(fallbackPackageFolders);

                var runtimeGraphs = new List <RestoreTargetGraph>();
                var runtimeTasks  = new List <Task <RestoreTargetGraph[]> >();
                var projectProvidedRuntimeIdentifierGraphs = new SortedList <string, RuntimeGraph>();
                foreach (var graph in graphs)
                {
                    // PCL Projects with Supports have a runtime graph but no matching framework.
                    var runtimeGraphPath = _request.Project.TargetFrameworks.
                                           FirstOrDefault(e => NuGetFramework.Comparer.Equals(e.FrameworkName, graph.Framework))?.RuntimeIdentifierGraphPath;

                    RuntimeGraph projectProviderRuntimeGraph = null;
                    if (runtimeGraphPath != null &&
                        !projectProvidedRuntimeIdentifierGraphs.TryGetValue(runtimeGraphPath, out projectProviderRuntimeGraph))
                    {
                        projectProviderRuntimeGraph = GetRuntimeGraph(runtimeGraphPath);
                        success &= projectProviderRuntimeGraph != null;
                        projectProvidedRuntimeIdentifierGraphs.Add(runtimeGraphPath, projectProviderRuntimeGraph);
                    }


                    var runtimeGraph = GetRuntimeGraph(graph, localRepositories, projectRuntimeGraph: projectProviderRuntimeGraph);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  runtimeGraph,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                telemetryActivity.EndIntervalMeasure(WalkRuntimeDependencyDuration);

                // Install runtime-specific packages
                success &= await InstallPackagesAsync(
                    uniquePackages,
                    runtimeGraphs,
                    Array.Empty <DownloadDependencyResolutionResult>(),
                    userPackageFolder,
                    token);
            }

            // Update the logger with the restore target graphs
            // This allows lazy initialization for the Transitive Warning Properties
            _logger.ApplyRestoreOutput(graphs);

            // Warn for all dependencies that do not have exact matches or
            // versions that have been bumped up unexpectedly.
            // TODO https://github.com/NuGet/Home/issues/7709: When ranges are implemented for download dependencies the bumped up dependencies need to be handled.
            await UnexpectedDependencyMessages.LogAsync(graphs, _request.Project, _logger);

            success &= (await ResolutionSucceeded(graphs, downloadDependencyResolutionResults, context, token));

            return(Tuple.Create(success, graphs, allRuntimes));
        }
        public override bool Execute()
        {
            if (Dependencies == null || Dependencies.Length == 0)
            {
                Log.LogError("Dependencies argument must be specified");
                return(false);
            }

            if (String.IsNullOrEmpty(PackageId))
            {
                Log.LogError("PackageID argument must be specified");
                return(false);
            }

            if (RuntimeJson == null)
            {
                Log.LogError("RuntimeJson argument must be specified");
                return(false);
            }

            string sourceRuntimeFilePath = null;

            if (RuntimeJsonTemplate != null)
            {
                sourceRuntimeFilePath = RuntimeJsonTemplate.GetMetadata("FullPath");
            }
            string destRuntimeFilePath = RuntimeJson.GetMetadata("FullPath");


            Dictionary <string, string> packageAliases = new Dictionary <string, string>();

            foreach (var dependency in Dependencies)
            {
                string alias = dependency.GetMetadata("PackageAlias");

                if (String.IsNullOrEmpty(alias))
                {
                    continue;
                }

                Log.LogMessage(LogImportance.Low, "Aliasing {0} -> {1}", alias, dependency.ItemSpec);
                packageAliases[alias] = dependency.ItemSpec;
            }

            var runtimeGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetRuntime"));

            List <RuntimeDescription> runtimes = new List <RuntimeDescription>();

            foreach (var runtimeGroup in runtimeGroups)
            {
                string targetRuntimeId = runtimeGroup.Key;

                if (String.IsNullOrEmpty(targetRuntimeId))
                {
                    Log.LogMessage(LogImportance.Low, "Skipping dependencies {0} since they don't have a TargetRuntime.", String.Join(", ", runtimeGroup.Select(d => d.ItemSpec)));
                    continue;
                }

                if (runtimeGroup.Any(d => d.ItemSpec == c_emptyDependency))
                {
                    runtimes.Add(new RuntimeDescription(targetRuntimeId));
                    continue;
                }

                List <RuntimeDependencySet> runtimeDependencySets = new List <RuntimeDependencySet>();
                var targetPackageGroups = runtimeGroup.GroupBy(d => GetTargetPackageId(d, packageAliases));
                foreach (var targetPackageGroup in targetPackageGroups)
                {
                    string targetPackageId = targetPackageGroup.Key;

                    List <RuntimePackageDependency> runtimePackageDependencies = new List <RuntimePackageDependency>();
                    var dependencyGroups = targetPackageGroup.GroupBy(d => d.ItemSpec);
                    foreach (var dependencyGroup in dependencyGroups)
                    {
                        string dependencyId         = dependencyGroup.Key;
                        var    dependencyVersions   = dependencyGroup.Select(d => GetDependencyVersion(d));
                        var    maxDependencyVersion = dependencyVersions.Max();
                        runtimePackageDependencies.Add(new RuntimePackageDependency(dependencyId, new VersionRange(maxDependencyVersion)));
                    }
                    runtimeDependencySets.Add(new RuntimeDependencySet(targetPackageId, runtimePackageDependencies));
                }
                runtimes.Add(new RuntimeDescription(targetRuntimeId, runtimeDependencySets));
            }

            RuntimeGraph runtimeGraph = new RuntimeGraph(runtimes);

            // read in existing JSON, if it was provided so that we preserve any
            // hand authored #imports or dependencies
            if (!String.IsNullOrEmpty(sourceRuntimeFilePath))
            {
                RuntimeGraph existingGraph = JsonRuntimeFormat.ReadRuntimeGraph(sourceRuntimeFilePath);
                runtimeGraph = RuntimeGraph.Merge(existingGraph, runtimeGraph);
            }

            string destRuntimeFileDir = Path.GetDirectoryName(destRuntimeFilePath);

            if (!String.IsNullOrEmpty(destRuntimeFileDir) && !Directory.Exists(destRuntimeFileDir))
            {
                Directory.CreateDirectory(destRuntimeFileDir);
            }

            JsonRuntimeFormat.WriteRuntimeGraph(destRuntimeFilePath, runtimeGraph);

            return(true);
        }