public async Task <RestoreResult> ExecuteAsync(CancellationToken token) { using (var telemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: ParentId, eventName: ProjectRestoreInformation)) { _operationId = telemetry.OperationId; var restoreTime = Stopwatch.StartNew(); // Local package folders (non-sources) var localRepositories = new List <NuGetv3LocalRepository> { _request.DependencyProviders.GlobalPackages }; localRepositories.AddRange(_request.DependencyProviders.FallbackPackageFolders); var contextForProject = CreateRemoteWalkContext(_request, _logger); CacheFile cacheFile = null; using (var noOpTelemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: _operationId, eventName: RestoreNoOpInformation)) { if (NoOpRestoreUtilities.IsNoOpSupported(_request)) { noOpTelemetry.StartIntervalMeasure(); var cacheFileAndStatus = EvaluateCacheFile(); noOpTelemetry.EndIntervalMeasure(CacheFileEvaluateDuration); cacheFile = cacheFileAndStatus.Key; if (cacheFileAndStatus.Value) { noOpTelemetry.StartIntervalMeasure(); var noOpSuccess = NoOpRestoreUtilities.VerifyAssetsAndMSBuildFilesAndPackagesArePresent(_request); noOpTelemetry.EndIntervalMeasure(MsbuildAssetsVerificationDuration); noOpTelemetry.TelemetryEvent[MsbuildAssetsVerificationResult] = noOpSuccess; if (noOpSuccess) { noOpTelemetry.StartIntervalMeasure(); // Replay Warnings and Errors from an existing lock file in case of a no-op. await MSBuildRestoreUtility.ReplayWarningsAndErrorsAsync(_request.ExistingLockFile, _logger); noOpTelemetry.EndIntervalMeasure(ReplayLogsDuration); restoreTime.Stop(); return(new NoOpRestoreResult( _success, _request.ExistingLockFile, _request.ExistingLockFile, _request.ExistingLockFile.Path, cacheFile, _request.Project.RestoreMetadata.CacheFilePath, _request.ProjectStyle, restoreTime.Elapsed)); } } } } IEnumerable <RestoreTargetGraph> graphs = null; using (var restoreGraphTelemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: _operationId, eventName: GenerateRestoreGraph)) { // Restore graphs = await ExecuteRestoreAsync( _request.DependencyProviders.GlobalPackages, _request.DependencyProviders.FallbackPackageFolders, contextForProject, token, restoreGraphTelemetry); } LockFile assetsFile = null; using (TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: _operationId, eventName: GenerateAssetsFile)) { // Create assets file assetsFile = BuildAssetsFile( _request.ExistingLockFile, _request.Project, graphs, localRepositories, contextForProject); } IList <CompatibilityCheckResult> checkResults = null; using (TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: _operationId, eventName: ValidateRestoreGraphs)) { _success &= await ValidateRestoreGraphsAsync(graphs, _logger); // Check package compatibility checkResults = await VerifyCompatibilityAsync( _request.Project, _includeFlagGraphs, localRepositories, assetsFile, graphs, _request.ValidateRuntimeAssets, _logger); if (checkResults.Any(r => !r.Success)) { _success = false; } } // Generate Targets/Props files var msbuildOutputFiles = Enumerable.Empty <MSBuildOutputFile>(); string assetsFilePath = null; string cacheFilePath = null; using (TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(parentId: _operationId, eventName: CreateRestoreResult)) { // Determine the lock file output path assetsFilePath = GetAssetsFilePath(assetsFile); // Determine the cache file output path cacheFilePath = NoOpRestoreUtilities.GetCacheFilePath(_request, assetsFile); // Tool restores are unique since the output path is not known until after restore if (_request.LockFilePath == null && _request.ProjectStyle == ProjectStyle.DotnetCliTool) { _request.LockFilePath = assetsFilePath; } if (contextForProject.IsMsBuildBased) { msbuildOutputFiles = BuildAssetsUtils.GetMSBuildOutputFiles( _request.Project, assetsFile, graphs, localRepositories, _request, assetsFilePath, _success, _logger); } // If the request is for a lower lock file version, downgrade it appropriately DowngradeLockFileIfNeeded(assetsFile); // Revert to the original case if needed await FixCaseForLegacyReaders(graphs, assetsFile, token); // Write the logs into the assets file var logs = _logger.Errors .Select(l => AssetsLogMessage.Create(l)) .ToList(); _success &= !logs.Any(l => l.Level == LogLevel.Error); assetsFile.LogMessages = logs; if (cacheFile != null) { cacheFile.Success = _success; } var errorCodes = ConcatAsString(new HashSet <NuGetLogCode>(logs.Where(l => l.Level == LogLevel.Error).Select(l => l.Code))); var warningCodes = ConcatAsString(new HashSet <NuGetLogCode>(logs.Where(l => l.Level == LogLevel.Warning).Select(l => l.Code))); if (!string.IsNullOrEmpty(errorCodes)) { telemetry.TelemetryEvent[ErrorCodes] = errorCodes; } if (!string.IsNullOrEmpty(warningCodes)) { telemetry.TelemetryEvent[WarningCodes] = warningCodes; } telemetry.TelemetryEvent[RestoreSuccess] = _success; } restoreTime.Stop(); // Create result return(new RestoreResult( _success, graphs, checkResults, msbuildOutputFiles, assetsFile, _request.ExistingLockFile, assetsFilePath, cacheFile, cacheFilePath, _request.ProjectStyle, restoreTime.Elapsed)); } }
private async Task <IEnumerable <RestoreTargetGraph> > ExecuteRestoreAsync( NuGetv3LocalRepository userPackageFolder, IReadOnlyList <NuGetv3LocalRepository> fallbackPackageFolders, RemoteWalkContext context, CancellationToken token, TelemetryActivity telemetryActivity) { if (_request.Project.TargetFrameworks.Count == 0) { var message = string.Format(CultureInfo.CurrentCulture, Strings.Log_ProjectDoesNotSpecifyTargetFrameworks, _request.Project.Name, _request.Project.FilePath); await _logger.LogAsync(RestoreLogMessage.CreateError(NuGetLogCode.NU1001, message)); _success = false; return(Enumerable.Empty <RestoreTargetGraph>()); } _logger.LogMinimal(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, _request.Project.FilePath)); // Get external project references // If the top level project already exists, update the package spec provided // with the RestoreRequest spec. var updatedExternalProjects = GetProjectReferences(context); // Determine if the targets and props files should be written out. context.IsMsBuildBased = _request.ProjectStyle != ProjectStyle.DotnetCliTool; // Load repositories // the external project provider is specific to the current restore project context.ProjectLibraryProviders.Add( new PackageSpecReferenceDependencyProvider(updatedExternalProjects, _logger)); var remoteWalker = new RemoteDependencyWalker(context); var projectRange = new LibraryRange() { Name = _request.Project.Name, VersionRange = new VersionRange(_request.Project.Version), TypeConstraint = LibraryDependencyTarget.Project | LibraryDependencyTarget.ExternalProject }; // Resolve dependency graphs var allGraphs = new List <RestoreTargetGraph>(); var runtimeIds = RequestRuntimeUtility.GetRestoreRuntimes(_request); var projectFrameworkRuntimePairs = CreateFrameworkRuntimePairs(_request.Project, runtimeIds); var hasSupports = _request.Project.RuntimeGraph.Supports.Count > 0; var projectRestoreRequest = new ProjectRestoreRequest( _request, _request.Project, _request.ExistingLockFile, _logger) { ParentId = _operationId }; var projectRestoreCommand = new ProjectRestoreCommand(projectRestoreRequest); Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> result = null; using (var tryRestoreTelemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(telemetryActivity.OperationId, CreateRestoreTargetGraph)) { result = await projectRestoreCommand.TryRestoreAsync( projectRange, projectFrameworkRuntimePairs, userPackageFolder, fallbackPackageFolders, remoteWalker, context, forceRuntimeGraphCreation : hasSupports, token : token, telemetryActivity : tryRestoreTelemetry); } var success = result.Item1; allGraphs.AddRange(result.Item2); _success = success; // Calculate compatibility profiles to check by merging those defined in the project with any from the command line foreach (var profile in _request.Project.RuntimeGraph.Supports) { var runtimes = result.Item3; CompatibilityProfile compatProfile; if (profile.Value.RestoreContexts.Any()) { // Just use the contexts from the project definition compatProfile = profile.Value; } else if (!runtimes.Supports.TryGetValue(profile.Value.Name, out compatProfile)) { // No definition of this profile found, so just continue to the next one var message = string.Format(CultureInfo.CurrentCulture, Strings.Log_UnknownCompatibilityProfile, profile.Key); await _logger.LogAsync(RestoreLogMessage.CreateWarning(NuGetLogCode.NU1502, message)); continue; } foreach (var pair in compatProfile.RestoreContexts) { _logger.LogDebug($" {profile.Value.Name} -> +{pair}"); _request.CompatibilityProfiles.Add(pair); } } // Walk additional runtime graphs for supports checks if (_success && _request.CompatibilityProfiles.Any()) { Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> compatibilityResult = null; using (var runtimeTryRestoreTelemetry = TelemetryActivity.CreateTelemetryActivityWithNewOperationIdAndEvent(telemetryActivity.OperationId, RestoreAdditionalCompatCheck)) { compatibilityResult = await projectRestoreCommand.TryRestoreAsync( projectRange, _request.CompatibilityProfiles, userPackageFolder, fallbackPackageFolders, remoteWalker, context, forceRuntimeGraphCreation : true, token : token, telemetryActivity : runtimeTryRestoreTelemetry); } _success = compatibilityResult.Item1; // TryRestore may contain graphs that are already in allGraphs if the // supports section contains the same TxM as the project framework. var currentGraphs = new HashSet <KeyValuePair <NuGetFramework, string> >( allGraphs.Select(graph => new KeyValuePair <NuGetFramework, string>( graph.Framework, graph.RuntimeIdentifier)) ); foreach (var graph in compatibilityResult.Item2) { var key = new KeyValuePair <NuGetFramework, string>( graph.Framework, graph.RuntimeIdentifier); if (currentGraphs.Add(key)) { allGraphs.Add(graph); } } } return(allGraphs); }