Exemple #1
0
        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));
            }
        }
Exemple #2
0
        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));
        }
Exemple #3
0
        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));
                }
            }
        }
Exemple #4
0
        /// <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);
        }