internal static async Task <string> DoUpgradeAsync(
            INuGetUIContext context,
            INuGetUI uiService,
            NuGetProject nuGetProject,
            IEnumerable <NuGetProjectUpgradeDependencyItem> upgradeDependencyItems,
            IEnumerable <PackageIdentity> notFoundPackages,
            IProgress <ProgressDialogData> progress,
            CancellationToken token)
        {
            var startTime     = DateTimeOffset.Now;
            var packagesCount = 0;
            var status        = NuGetOperationStatus.Succeeded;

            var upgradeInformationTelemetryEvent = new UpgradeInformationTelemetryEvent();

            using (var telemetry = TelemetryActivity.Create(upgradeInformationTelemetryEvent))
            {
                try
                {
                    // 0. Fail if any package was not found
                    if (notFoundPackages.Any())
                    {
                        status = NuGetOperationStatus.Failed;
                        var notFoundPackageIds = string.Join(",", notFoundPackages.Select(t => t.Id));
                        uiService.ProjectContext.Log(MessageLevel.Error, string.Format(CultureInfo.CurrentCulture, Resources.Migrator_PackageNotFound, notFoundPackageIds));
                        return(null);
                    }

                    // 1. Backup files (csproj and packages.config) that will change
                    var solutionManager           = context.SolutionManager;
                    var msBuildNuGetProject       = (MSBuildNuGetProject)nuGetProject;
                    var msBuildNuGetProjectSystem = msBuildNuGetProject.ProjectSystem;
                    var backupPath = string.Empty;
                    try
                    {
                        backupPath = CreateBackup(msBuildNuGetProject, solutionManager.SolutionDirectory);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;
                        // log error message
                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrader_BackupFailed));

                        return(null);
                    }


                    // 2. Uninstall all packages currently in packages.config
                    var progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Uninstalling);
                    progress.Report(progressData);

                    // Don't uninstall packages we couldn't find - that will just fail
                    var actions = upgradeDependencyItems.Select(d => d.Identity)
                                  .Where(p => !notFoundPackages.Contains(p))
                                  .Select(t => NuGetProjectAction.CreateUninstallProjectAction(t, nuGetProject));

                    try
                    {
                        await context.PackageManager.ExecuteNuGetProjectActionsAsync(nuGetProject, actions, uiService.ProjectContext, NullSourceCacheContext.Instance, CancellationToken.None);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;
                        // log error message
                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_UninstallFailed));

                        return(null);
                    }

                    // Reload the project, and get a reference to the reloaded project
                    var uniqueName = msBuildNuGetProjectSystem.ProjectUniqueName;
                    await msBuildNuGetProject.SaveAsync(token);

                    nuGetProject = await solutionManager.GetNuGetProjectAsync(uniqueName);

                    nuGetProject = await solutionManager.UpgradeProjectToPackageReferenceAsync(nuGetProject);

                    // Ensure we use the updated project for installing, and don't display preview or license acceptance windows.
                    context.Projects = new[] { nuGetProject };
                    var nuGetUI = (NuGetUI)uiService;
                    nuGetUI.Projects             = new[] { nuGetProject };
                    nuGetUI.DisplayPreviewWindow = false;

                    // 4. Install the requested packages
                    var ideExecutionContext = uiService.ProjectContext.ExecutionContext as IDEExecutionContext;
                    if (ideExecutionContext != null)
                    {
                        await ideExecutionContext.SaveExpandedNodeStates(solutionManager);
                    }

                    progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Installing);
                    progress.Report(progressData);
                    var activeSources = new List <SourceRepository>();
                    PackageSourceMoniker
                    .PopulateList(context.SourceProvider)
                    .ForEach(s => activeSources.AddRange(s.SourceRepositories));
                    var packagesToInstall = GetPackagesToInstall(upgradeDependencyItems).ToList();
                    packagesCount = packagesToInstall.Count;

                    // create low level NuGet actions based on number of packages being installed
                    var lowLevelActions = new List <NuGetProjectAction>();
                    foreach (var packageIdentity in packagesToInstall)
                    {
                        lowLevelActions.Add(NuGetProjectAction.CreateInstallProjectAction(packageIdentity, activeSources.FirstOrDefault(), nuGetProject));
                    }

                    try
                    {
                        var buildIntegratedProject = nuGetProject as BuildIntegratedNuGetProject;
                        await context.PackageManager.ExecuteBuildIntegratedProjectActionsAsync(
                            buildIntegratedProject,
                            lowLevelActions,
                            uiService.ProjectContext,
                            token);

                        if (ideExecutionContext != null)
                        {
                            await ideExecutionContext.CollapseAllNodes(solutionManager);
                        }

                        return(backupPath);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;

                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_InstallFailed, backupPath));
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_RevertSteps, "https://aka.ms/nugetupgraderevertv1"));

                        return(null);
                    }
                }
                catch (Exception ex)
                {
                    status = NuGetOperationStatus.Failed;
                    uiService.ShowError(ex);
                    return(null);
                }
                finally
                {
                    upgradeInformationTelemetryEvent.SetResult(uiService.Projects, status, packagesCount);
                }
            }
        }