/// <summary> /// Executes the list of <param name="nuGetProjectActions"></param> on <param name="nuGetProject"></param>, which is likely obtained by calling into PreviewInstallPackageAsync /// <param name="nuGetProjectContext"></param> is used in the process /// </summary> public async Task ExecuteNuGetProjectActionsAsync(NuGetProject nuGetProject, IEnumerable<NuGetProjectAction> nuGetProjectActions, INuGetProjectContext nuGetProjectContext, CancellationToken token) { if (nuGetProject == null) { throw new ArgumentNullException("nuGetProject"); } if (nuGetProjectActions == null) { throw new ArgumentNullException("nuGetProjectActions"); } if (nuGetProjectContext == null) { throw new ArgumentNullException("nuGetProjectContext"); } Exception executeNuGetProjectActionsException = null; Stack<NuGetProjectAction> executedNuGetProjectActions = new Stack<NuGetProjectAction>(); HashSet<PackageIdentity> packageWithDirectoriesToBeDeleted = new HashSet<PackageIdentity>(PackageIdentity.Comparer); try { await nuGetProject.PreProcessAsync(nuGetProjectContext, token); foreach (NuGetProjectAction nuGetProjectAction in nuGetProjectActions) { executedNuGetProjectActions.Push(nuGetProjectAction); if (nuGetProjectAction.NuGetProjectActionType == NuGetProjectActionType.Uninstall) { await ExecuteUninstallAsync(nuGetProject, nuGetProjectAction.PackageIdentity, packageWithDirectoriesToBeDeleted, nuGetProjectContext, token); } else { using (var targetPackageStream = new MemoryStream()) { await PackageDownloader.GetPackageStream(nuGetProjectAction.SourceRepository, nuGetProjectAction.PackageIdentity, targetPackageStream, token); await ExecuteInstallAsync(nuGetProject, nuGetProjectAction.PackageIdentity, targetPackageStream, packageWithDirectoriesToBeDeleted, nuGetProjectContext, token); } } string toFromString = nuGetProjectAction.NuGetProjectActionType == NuGetProjectActionType.Install ? Strings.To : Strings.From; nuGetProjectContext.Log(MessageLevel.Info, Strings.SuccessfullyExecutedPackageAction, nuGetProjectAction.NuGetProjectActionType.ToString().ToLowerInvariant(), nuGetProjectAction.PackageIdentity.ToString(), toFromString + " " + nuGetProject.GetMetadata<string>(NuGetProjectMetadataKeys.Name)); } await nuGetProject.PostProcessAsync(nuGetProjectContext, token); await OpenReadmeFile(nuGetProjectContext, token); } catch (Exception ex) { executeNuGetProjectActionsException = ex; } if(executeNuGetProjectActionsException != null) { await Rollback(nuGetProject, executedNuGetProjectActions, packageWithDirectoriesToBeDeleted, nuGetProjectContext, token); } // Delete the package directories as the last step, so that, if an uninstall had to be rolled back, we can just use the package file on the directory // Also, always perform deletion of package directories, even in a rollback, so that there are no stale package directories foreach(var packageWithDirectoryToBeDeleted in packageWithDirectoriesToBeDeleted) { await DeletePackage(packageWithDirectoryToBeDeleted, nuGetProjectContext, token); } // Clear direct install SetDirectInstall(null, nuGetProjectContext); if(executeNuGetProjectActionsException != null) { throw executeNuGetProjectActionsException; } }