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(logs.Where(l => l.Level == LogLevel.Error).Select(l => l.Code)); var errorMessages = ConcatAsString(logs.Where(l => l.Level == LogLevel.Error).Select(l => l.Message)); var warningCodes = ConcatAsString(logs.Where(l => l.Level == LogLevel.Warning).Select(l => l.Code)); var warningMessages = ConcatAsString(logs.Where(l => l.Level == LogLevel.Warning).Select(l => l.Message)); if (!string.IsNullOrEmpty(errorCodes)) { telemetry.TelemetryEvent[ErrorCodes] = errorCodes; telemetry.TelemetryEvent.AddPiiData(ErrorMessages, errorMessages); } if (!string.IsNullOrEmpty(warningCodes)) { telemetry.TelemetryEvent[WarningCodes] = warningCodes; telemetry.TelemetryEvent.AddPiiData(WarningMessages, warningMessages); } 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)); } }
public async Task <RestoreResult> ExecuteAsync(CancellationToken token) { 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; if (NoOpRestoreUtilities.IsNoOpSupported(_request)) { var cacheFileAndStatus = EvaluateCacheFile(); cacheFile = cacheFileAndStatus.Key; if (cacheFileAndStatus.Value) { if (NoOpRestoreUtilities.VerifyAssetsAndMSBuildFilesAndPackagesArePresent(_request)) { // Replay Warnings and Errors from an existing lock file in case of a no-op. ReplayWarningsAndErrors(); restoreTime.Stop(); return(new NoOpRestoreResult( _success, _request.ExistingLockFile, _request.ExistingLockFile, _request.ExistingLockFile.Path, cacheFile, _request.Project.RestoreMetadata.CacheFilePath, _request.ProjectStyle, restoreTime.Elapsed)); } } } // Restore var graphs = await ExecuteRestoreAsync( _request.DependencyProviders.GlobalPackages, _request.DependencyProviders.FallbackPackageFolders, contextForProject, token); // Create assets file var assetsFile = BuildAssetsFile( _request.ExistingLockFile, _request.Project, graphs, localRepositories, contextForProject); _success &= await ValidateRestoreGraphsAsync(graphs, _logger); // Check package compatibility var checkResults = await VerifyCompatibilityAsync( _request.Project, _includeFlagGraphs, localRepositories, assetsFile, graphs, _request.ValidateRuntimeAssets, _logger); if (checkResults.Any(r => !r.Success)) { _success = false; } // Determine the lock file output path var assetsFilePath = GetAssetsFilePath(assetsFile); // Determine the cache file output path var 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; } // Generate Targets/Props files var msbuildOutputFiles = Enumerable.Empty <MSBuildOutputFile>(); 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; } restoreTime.Stop(); // Create result return(new RestoreResult( _success, graphs, checkResults, msbuildOutputFiles, assetsFile, _request.ExistingLockFile, assetsFilePath, cacheFile, cacheFilePath, _request.ProjectStyle, restoreTime.Elapsed)); }
private async Task CommitAssetsFileAsync( LockFileFormat lockFileFormat, IRestoreResult result, ILogger log, bool toolCommit, CancellationToken token) { // Commit targets/props to disk before the assets file. // Visual Studio typically watches the assets file for changes // and begins a reload when that file changes. var buildFilesToWrite = result.MSBuildOutputFiles .Where(e => BuildAssetsUtils.HasChanges(e.Content, e.Path, log)); BuildAssetsUtils.WriteFiles(buildFilesToWrite, log); if (result.LockFile == null || result.LockFilePath == null) { // there is no assets file to be written so just return return; } // Avoid writing out the lock file if it is the same to avoid triggering an intellisense // update on a restore with no actual changes. if (result.PreviousLockFile == null || !result.PreviousLockFile.Equals(result.LockFile)) { if (toolCommit) { log.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.Log_ToolWritingAssetsFile, result.LockFilePath)); await FileUtility.ReplaceWithLock( (outputPath) => lockFileFormat.Write(outputPath, result.LockFile), result.LockFilePath); } else { log.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.Log_WritingAssetsFile, result.LockFilePath)); FileUtility.Replace( (outputPath) => lockFileFormat.Write(outputPath, result.LockFile), result.LockFilePath); } } else { if (toolCommit) { log.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.Log_ToolSkippingAssetsFile, result.LockFilePath)); } else { log.LogInformation(string.Format(CultureInfo.CurrentCulture, Strings.Log_SkippingAssetsFile, result.LockFilePath)); } } }
/// <summary> /// This method verifies that the assets files, props/targets files and all the packages written out in the assets file are present on disk /// When the project has opted into packages lock file, it also verified that the lock file is present on disk. /// This does not account if the files were manually modified since the last restore /// </summary> internal static bool VerifyRestoreOutput(RestoreRequest request, CacheFile cacheFile) { if (!string.IsNullOrWhiteSpace(request.LockFilePath) && !File.Exists(request.LockFilePath)) { request.Log.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_AssetsFileNotOnDisk, request.Project.Name)); return(false); } if (request.ProjectStyle == ProjectStyle.PackageReference || request.ProjectStyle == ProjectStyle.Standalone) { var targetsFilePath = BuildAssetsUtils.GetMSBuildFilePath(request.Project, BuildAssetsUtils.TargetsExtension); if (!File.Exists(targetsFilePath)) { request.Log.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_TargetsFileNotOnDisk, request.Project.Name, targetsFilePath)); return(false); } var propsFilePath = BuildAssetsUtils.GetMSBuildFilePath(request.Project, BuildAssetsUtils.PropsExtension); if (!File.Exists(propsFilePath)) { request.Log.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_PropsFileNotOnDisk, request.Project.Name, propsFilePath)); return(false); } if (PackagesLockFileUtilities.IsNuGetLockFileEnabled(request.Project)) { var packageLockFilePath = PackagesLockFileUtilities.GetNuGetLockFilePath(request.Project); if (!File.Exists(packageLockFilePath)) { request.Log.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_LockFileNotOnDisk, request.Project.Name, packageLockFilePath)); return(false); } } } if (cacheFile.HasAnyMissingPackageFiles) { request.Log.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MissingPackagesOnDisk, request.Project.Name)); return(false); } if (request.UpdatePackageLastAccessTime) { foreach (var package in cacheFile.ExpectedPackageFilePaths) { if (!package.StartsWith(request.PackagesDirectory, StringComparison.OrdinalIgnoreCase)) { continue; } var packageDirectory = Path.GetDirectoryName(package); var metadataFile = Path.Combine(packageDirectory, PackagingCoreConstants.NupkgMetadataFileExtension); try { request.DependencyProviders.PackageFileCache.UpdateLastAccessTime(metadataFile); } catch (Exception ex) { request.Log.Log(RestoreLogMessage.CreateWarning(NuGetLogCode.NU1802, string.Format(CultureInfo.InvariantCulture, Strings.Error_CouldNotUpdateMetadataLastAccessTime, metadataFile, ex.Message))); } } } return(true); }