private IReadOnlyList <RestoreSummaryRequest> GetRequestsFromItems(RestoreArgs restoreContext, DependencyGraphSpec dgFile) { if (restoreContext == null) { throw new ArgumentNullException(nameof(restoreContext)); } if (dgFile == null) { throw new ArgumentNullException(nameof(dgFile)); } // Validate the dg file input, this throws if errors are found. var projectsWithErrors = new HashSet <string>(); if (restoreContext.AdditionalMessages != null) { foreach (var projectPath in restoreContext.AdditionalMessages.Where(m => m.Level == Common.LogLevel.Error).Select(m => m.ProjectPath)) { projectsWithErrors.Add(projectPath); } } SpecValidationUtility.ValidateDependencySpec(dgFile, projectsWithErrors); // Create requests var requests = new ConcurrentBag <RestoreSummaryRequest>(); var toolRequests = new ConcurrentBag <RestoreSummaryRequest>(); var parallelOptions = new ParallelOptions { // By default, max degree of parallelism is -1 which means no upper bound. // Limiting to processor count reduces task context switching which is better MaxDegreeOfParallelism = Environment.ProcessorCount }; using (var settingsLoadingContext = new SettingsLoadingContext()) { // Parallel.Foreach has an optimization for Arrays, so calling .ToArray() is better and adds almost no overhead Parallel.ForEach(dgFile.Restore.ToArray(), parallelOptions, projectNameToRestore => { IReadOnlyList <PackageSpec> closure = dgFile.GetClosure(projectNameToRestore); DependencyGraphSpec projectDependencyGraphSpec = dgFile.CreateFromClosure(projectNameToRestore, closure); var externalClosure = new HashSet <ExternalProjectReference>(closure.Select(GetExternalProject)); ExternalProjectReference rootProject = externalClosure.Single(p => StringComparer.Ordinal.Equals(projectNameToRestore, p.UniqueName)); RestoreSummaryRequest request = Create( projectNameToRestore, rootProject, externalClosure, restoreContext, projectDependencyGraphSpec, settingsLoadingContext); if (request.Request.ProjectStyle == ProjectStyle.DotnetCliTool) { // Store tool requests to be filtered later toolRequests.Add(request); } else { requests.Add(request); } }); } // Filter out duplicate tool restore requests foreach (RestoreSummaryRequest subSetRequest in ToolRestoreUtility.GetSubSetRequests(toolRequests)) { requests.Add(subSetRequest); } return(requests.ToArray()); }
/// <summary> /// This method will resolve the cache/lock file paths for the tool if available in the cache /// This method will set the CacheFilePath and the LockFilePath in the RestoreMetadat if a matching tool is available /// </summary> public static void UpdateRequestBestMatchingToolPathsIfAvailable(RestoreRequest request) { if (request.ProjectStyle == ProjectStyle.DotnetCliTool) { // Resolve the lock file path if it exists var toolPathResolver = new ToolPathResolver(request.PackagesDirectory); var toolDirectory = toolPathResolver.GetBestToolDirectoryPath( ToolRestoreUtility.GetToolIdOrNullFromSpec(request.Project), request.Project.TargetFrameworks.First().Dependencies.First().LibraryRange.VersionRange, request.Project.TargetFrameworks.SingleOrDefault().FrameworkName); if (toolDirectory != null) // Only set the paths if a good enough match was found. { request.Project.RestoreMetadata.CacheFilePath = NoOpRestoreUtilities.GetToolCacheFilePath(toolDirectory, ToolRestoreUtility.GetToolIdOrNullFromSpec(request.Project)); request.LockFilePath = toolPathResolver.GetLockFilePath(toolDirectory); } } }