internal async Task PerformPackageInstallAsync()

in src/NuGet.Clients/NuGet.VisualStudio.Implementation/PreinstalledPackageInstaller.cs [173:317]


        internal async Task PerformPackageInstallAsync(
            EnvDTE.Project project,
            PreinstalledPackageConfiguration configuration,
            bool preferPackageReferenceFormat,
            Action<string> warningHandler,
            Action<string> errorHandler)
        {
            await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            var repositoryPath = configuration.RepositoryPath;
            var repositorySource = new Configuration.PackageSource(repositoryPath);
            var failedPackageErrors = new List<string>();

            // find the project
            var defaultProjectContext = new VSAPIProjectContext
            {
                PackageExtractionContext = new PackageExtractionContext(
                    PackageSaveMode.Defaultv2,
                    PackageExtractionBehavior.XmlDocFileSaveMode,
                    ClientPolicyContext.GetClientPolicy(_settings, NullLogger.Instance),
                    NullLogger.Instance)
            };

            var nuGetProject = await _solutionManager.GetOrCreateProjectAsync(project, defaultProjectContext);
            if (preferPackageReferenceFormat && await NuGetProjectUpgradeUtility.IsNuGetProjectUpgradeableAsync(nuGetProject, project, needsAPackagesConfig: false))
            {
                nuGetProject = await _solutionManager.UpgradeProjectToPackageReferenceAsync(nuGetProject);
            }

            // For BuildIntegratedNuGetProject, nuget will ignore preunzipped configuration.
            var buildIntegratedProject = nuGetProject as BuildIntegratedNuGetProject;

            var repository = (buildIntegratedProject == null && configuration.IsPreunzipped) ?
                _sourceProvider.CreateRepository(repositorySource, FeedType.FileSystemUnzipped) :
                _sourceProvider.CreateRepository(repositorySource);

            var repoProvider = new PreinstalledRepositoryProvider(errorHandler, _sourceProvider);
            repoProvider.AddFromSource(repository);

            var packageManager = _installer.CreatePackageManager(repoProvider);
            var gatherCache = new GatherCache();

            var sources = repoProvider.GetRepositories().ToList();

            // store expanded node state
            var expandedNodes = await VsHierarchyUtility.GetAllExpandedNodesAsync();

            try
            {
                foreach (var package in configuration.Packages)
                {
                    var packageIdentity = new PackageIdentity(package.Id, package.Version);

                    // Does the project already have this package installed?
#pragma warning disable CS0618 // Type or member is obsolete
                    if (_packageServices.IsPackageInstalled(project, package.Id))
                    {
                        // If so, is it the right version?
                        if (!_packageServices.IsPackageInstalledEx(project, package.Id, package.Version.ToNormalizedString()))
#pragma warning restore CS0618 // Type or member is obsolete
                        {
                            // No? Raise a warning (likely written to the Output window) and ignore this package.
                            warningHandler(string.Format(CultureInfo.CurrentCulture, VsResources.PreinstalledPackages_VersionConflict, package.Id, package.Version));
                        }
                        // Yes? Just silently ignore this package!
                    }
                    else
                    {
                        try
                        {
                            if (InfoHandler != null)
                            {
                                InfoHandler(string.Format(CultureInfo.CurrentCulture, VsResources.PreinstalledPackages_PackageInstallStatus, package.Id, package.Version));
                            }

                            // Skip assembly references and disable binding redirections should be done together
                            var disableBindingRedirects = package.SkipAssemblyReferences;

                            var projectContext = new VSAPIProjectContext(package.SkipAssemblyReferences, disableBindingRedirects);
                            var loggerAdapter = new LoggerAdapter(projectContext);
                            projectContext.PackageExtractionContext = new PackageExtractionContext(
                                PackageSaveMode.Defaultv2,
                                PackageExtractionBehavior.XmlDocFileSaveMode,
                                ClientPolicyContext.GetClientPolicy(_settings, loggerAdapter),
                                loggerAdapter);

                            // This runs from the UI thread
                            await _installer.InstallInternalCoreAsync(
                                packageManager,
                                gatherCache,
                                nuGetProject,
                                packageIdentity,
                                sources,
                                projectContext,
                                includePrerelease: false,
                                ignoreDependencies: package.IgnoreDependencies,
                                token: CancellationToken.None);
                        }
                        catch (InvalidOperationException exception)
                        {
                            failedPackageErrors.Add(package.Id + "." + package.Version + " : " + exception.Message);
                        }
                        catch (AggregateException aggregateEx)
                        {
                            var ex = aggregateEx.Flatten().InnerExceptions.FirstOrDefault();
                            if (ex is InvalidOperationException)
                            {
                                failedPackageErrors.Add(package.Id + "." + package.Version + " : " + ex.Message);
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                }

                if (failedPackageErrors.Any())
                {
                    var errorString = new StringBuilder();
                    errorString.AppendFormat(CultureInfo.CurrentCulture, VsResources.PreinstalledPackages_FailedToInstallPackage, repositoryPath);
                    errorString.AppendLine();
                    errorString.AppendLine();
                    errorString.Append(string.Join(Environment.NewLine, failedPackageErrors));

                    errorHandler(errorString.ToString());
                }

                // RepositorySettings = null in unit tests
                if (project.IsWebSite())
                {
                    CreateRefreshFilesInBin(
                        project,
                        repositoryPath,
                        configuration.Packages.Where(p => p.SkipAssemblyReferences));

                    CopyNativeBinariesToBin(project, repositoryPath, configuration.Packages);
                }
            }
            finally
            {
                // collapse nodes
                await VsHierarchyUtility.CollapseAllNodesAsync(expandedNodes);
            }
        }