private bool ShouldNoOpDueToRestore(SolutionRestoredEventArgs latestRestore) { return(latestRestore != null && _currentRestore != null && latestRestore.SolutionSpecHash == _currentRestore.SolutionSpecHash && latestRestore.IsSuccess == _currentRestore.IsSuccess); }
private bool ShouldNoOpDueToRestore(SolutionRestoredEventArgs latestRestore) { return (_currentRestore != null && latestRestore != null && ( latestRestore.RestoreStatus == NuGetOperationStatus.NoOp || object.ReferenceEquals(_currentRestore, latestRestore) )); }
private async Task ExecuteInitScriptsAsync() { // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads. using (await _initScriptsLock.EnterAsync()) { if (!await _solutionManager.Value.IsSolutionOpenAsync()) { return; } Debug.Assert(_settings != null); if (_settings == null) { return; } var latestRestore = _latestRestore; var latestSolutionDirectory = await _solutionManager.Value.GetSolutionDirectoryAsync(); if (ShouldNoOpDueToRestore(latestRestore) && ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory)) { _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; return; } // We may be enumerating packages from disk here. Always do it from a background thread. await TaskScheduler.Default; var packageManager = new NuGetPackageManager( _sourceRepositoryProvider, _settings.Value, _solutionManager.Value, _deleteOnRestartManager.Value, _restoreProgressReporter.Value); var enumerator = new InstalledPackageEnumerator(_solutionManager.Value, _settings.Value); var installedPackages = await enumerator.EnumeratePackagesAsync(packageManager, CancellationToken.None); foreach (var installedPackage in installedPackages) { await ExecuteInitPs1Async(installedPackage.InstallPath, installedPackage.Identity); } // We are done executing scripts, so record the restore and solution directory that we executed for. // This aids the no-op logic above. _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; } }
public void OnSolutionRestoreCompleted(SolutionRestoredEventArgs args) { Task.Run(() => { try { SolutionRestoreCompleted?.Invoke(args); } catch (Exception ex) { _logger.Value.LogError(ex.ToString()); } }); }
private void RestoreEvents_SolutionRestoreCompleted(SolutionRestoredEventArgs args) { _latestRestore = args; }
private async Task ExecuteInitScriptsAsync() { // Fix for Bug 1426 Disallow ExecuteInitScripts from being executed concurrently by multiple threads. using (await _initScriptsLock.EnterAsync()) { if (!_solutionManager.IsSolutionOpen) { return; } Debug.Assert(_settings != null); if (_settings == null) { return; } var latestRestore = _latestRestore; var latestSolutionDirectory = _solutionManager.SolutionDirectory; if (ShouldNoOpDueToRestore(latestRestore) && ShouldNoOpDueToSolutionDirectory(latestSolutionDirectory)) { _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; return; } // invoke init.ps1 files in the order of package dependency. // if A -> B, we invoke B's init.ps1 before A's. var projects = _solutionManager.GetNuGetProjects().ToList(); var packageManager = new NuGetPackageManager( _sourceRepositoryProvider, _settings, _solutionManager, _deleteOnRestartManager); var packagesByFramework = new Dictionary <NuGetFramework, HashSet <PackageIdentity> >(); var sortedGlobalPackages = new List <PackageIdentity>(); // Sort projects by type foreach (var project in projects) { // Skip project K projects. if (project is ProjectKNuGetProjectBase) { continue; } var buildIntegratedProject = project as BuildIntegratedNuGetProject; if (buildIntegratedProject != null) { var packages = await BuildIntegratedProjectUtility .GetOrderedProjectPackageDependencies(buildIntegratedProject); sortedGlobalPackages.AddRange(packages); } else { // Read packages.config var installedRefs = await project.GetInstalledPackagesAsync(CancellationToken.None); if (installedRefs?.Any() == true) { // Index packages.config references by target framework since this affects dependencies NuGetFramework targetFramework; if (!project.TryGetMetadata(NuGetProjectMetadataKeys.TargetFramework, out targetFramework)) { targetFramework = NuGetFramework.AnyFramework; } HashSet <PackageIdentity> fwPackages; if (!packagesByFramework.TryGetValue(targetFramework, out fwPackages)) { fwPackages = new HashSet <PackageIdentity>(); packagesByFramework.Add(targetFramework, fwPackages); } fwPackages.UnionWith(installedRefs.Select(reference => reference.PackageIdentity)); } } } // Each id/version should only be executed once var finishedPackages = new HashSet <PackageIdentity>(); // Packages.config projects if (packagesByFramework.Count > 0) { await ExecuteInitPs1ForPackagesConfig( packageManager, packagesByFramework, finishedPackages); } // build integrated projects if (sortedGlobalPackages.Count > 0) { await ExecuteInitPs1ForBuildIntegratedAsync( sortedGlobalPackages, finishedPackages); } // We are done executing scripts, so record the restore and solution directory that we executed for. // This aids the no-op logic above. _currentRestore = latestRestore; _currentSolutionDirectory = latestSolutionDirectory; } }
private async Task RestoreAsync(bool forceRestore, RestoreOperationSource restoreSource, CancellationToken token) { var startTime = DateTimeOffset.Now; _status = NuGetOperationStatus.NoOp; // start timer for telemetry event TelemetryUtility.StartorResumeTimer(); var projects = Enumerable.Empty <NuGetProject>(); _packageRestoreManager.PackageRestoredEvent += PackageRestoreManager_PackageRestored; _packageRestoreManager.PackageRestoreFailedEvent += PackageRestoreManager_PackageRestoreFailedEvent; try { var solutionDirectory = _solutionManager.SolutionDirectory; var isSolutionAvailable = _solutionManager.IsSolutionAvailable; if (solutionDirectory == null) { await _logger.DoAsync((l, _) => { _status = NuGetOperationStatus.Failed; l.ShowError(Resources.SolutionIsNotSaved); l.WriteLine(VerbosityLevel.Minimal, Resources.SolutionIsNotSaved); }); return; } // Get the projects from the SolutionManager // Note that projects that are not supported by NuGet, will not show up in this list projects = _solutionManager.GetNuGetProjects(); // Check if there are any projects that are not INuGetIntegratedProject, that is, // projects with packages.config. OR // any of the deferred project is type of packages.config, If so, perform package restore on them if (projects.Any(project => !(project is INuGetIntegratedProject))) { await RestorePackagesOrCheckForMissingPackagesAsync( solutionDirectory, isSolutionAvailable, token); } var dependencyGraphProjects = projects .OfType <IDependencyGraphProject>() .ToList(); await RestorePackageSpecProjectsAsync( dependencyGraphProjects, forceRestore, isSolutionAvailable, token); // TODO: To limit risk, we only publish the event when there is a cross-platform PackageReference // project in the solution. Extending this behavior to all solutions is tracked here: // NuGet/Home#4478 #if !VS14 if (projects.OfType <NetCorePackageReferenceProject>().Any() && !string.IsNullOrEmpty(_dependencyGraphProjectCacheHash)) { // A no-op restore is considered successful. A cancellation is considered unsuccessful. var args = new SolutionRestoredEventArgs( isSuccess: _status == NuGetOperationStatus.Succeeded || _status == NuGetOperationStatus.NoOp, solutionSpecHash: _dependencyGraphProjectCacheHash); _restoreEventsPublisher.OnSolutionRestoreCompleted(args); } #endif } finally { _packageRestoreManager.PackageRestoredEvent -= PackageRestoreManager_PackageRestored; _packageRestoreManager.PackageRestoreFailedEvent -= PackageRestoreManager_PackageRestoreFailedEvent; TelemetryUtility.StopTimer(); var duration = TelemetryUtility.GetTimerElapsedTime(); await _logger.WriteSummaryAsync(_status, duration); // Emit telemetry event for restore operation EmitRestoreTelemetryEvent( projects, restoreSource, startTime, _status, _packageCount, duration.TotalSeconds); } }
private async Task RestoreAsync(bool forceRestore, RestoreOperationSource restoreSource, CancellationToken token) { var startTime = DateTimeOffset.Now; _status = NuGetOperationStatus.NoOp; // start timer for telemetry event TelemetryUtility.StartorResumeTimer(); var projects = Enumerable.Empty <NuGetProject>(); _packageRestoreManager.PackageRestoredEvent += PackageRestoreManager_PackageRestored; _packageRestoreManager.PackageRestoreFailedEvent += PackageRestoreManager_PackageRestoreFailedEvent; try { var solutionDirectory = _solutionManager.SolutionDirectory; var isSolutionAvailable = _solutionManager.IsSolutionAvailable; // Check if solution has deferred projects var deferredProjectsData = new DeferredProjectRestoreData(new Dictionary <PackageReference, List <string> >(), new List <PackageSpec>()); if (await _solutionManager.SolutionHasDeferredProjectsAsync()) { var deferredProjectsPath = await _solutionManager.GetDeferredProjectsFilePathAsync(); deferredProjectsData = await DeferredProjectRestoreUtility.GetDeferredProjectsData(_deferredWorkspaceService, deferredProjectsPath, token); } // Get the projects from the SolutionManager // Note that projects that are not supported by NuGet, will not show up in this list projects = _solutionManager.GetNuGetProjects(); // Check if there are any projects that are not INuGetIntegratedProject, that is, // projects with packages.config. OR // any of the deferred project is type of packages.config, If so, perform package restore on them if (projects.Any(project => !(project is INuGetIntegratedProject)) || deferredProjectsData.PackageReferenceDict.Count > 0) { await RestorePackagesOrCheckForMissingPackagesAsync( solutionDirectory, isSolutionAvailable, deferredProjectsData.PackageReferenceDict, token); } var dependencyGraphProjects = projects .OfType <IDependencyGraphProject>() .ToList(); await RestorePackageSpecProjectsAsync( dependencyGraphProjects, forceRestore, isSolutionAvailable, deferredProjectsData.PackageSpecs, token); // TODO: To limit risk, we only publish the event when there is a cross-platform PackageReference // project in the solution. Extending this behavior to all solutions is tracked here: // https://github.com/NuGet/Home/issues/4478 #if !VS14 if (projects.OfType <CpsPackageReferenceProject>().Any() && !string.IsNullOrEmpty(_dependencyGraphProjectCacheHash)) { // A no-op restore is considered successful. A cancellation is considered unsuccessful. var args = new SolutionRestoredEventArgs( isSuccess: _status == NuGetOperationStatus.Succeeded || _status == NuGetOperationStatus.NoOp, solutionSpecHash: _dependencyGraphProjectCacheHash); _restoreEventsPublisher.OnSolutionRestoreCompleted(args); } #endif } finally { _packageRestoreManager.PackageRestoredEvent -= PackageRestoreManager_PackageRestored; _packageRestoreManager.PackageRestoreFailedEvent -= PackageRestoreManager_PackageRestoreFailedEvent; TelemetryUtility.StopTimer(); var duration = TelemetryUtility.GetTimerElapsedTime(); await _logger.WriteSummaryAsync(_status, duration); // Emit telemetry event for restore operation EmitRestoreTelemetryEvent( projects, restoreSource, startTime, _status, _packageCount, duration.TotalSeconds); } }