File: RestoreRunnerEx.cs
Web Access
Project: src\src\nuget-client\src\NuGet.Core\Microsoft.Build.NuGetSdkResolver\Microsoft.Build.NuGetSdkResolver.csproj (Microsoft.Build.NuGetSdkResolver)
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Shared;
using NuGet.Versioning;
using ILogger = NuGet.Common.ILogger;

namespace NuGet.Commands
{
    /// <summary>
    /// An extension of the NuGet.Commands.RestoreRunner class that contains APIs we do not yet have.
    /// https://github.com/NuGet/Home/issues/5919
    /// </summary>
    internal static class RestoreRunnerEx
    {
        // NuGet requires at least one framework, we use .NET Standard here just to get the API to do work.  The framework is not actually used.
        private static readonly List<NuGetFramework> TargetFrameworks = new List<NuGetFramework>
        {
            FrameworkConstants.CommonFrameworks.NetStandard
        };

        /// <summary>
        /// Restores a package by querying, downloading, and unzipping it without generating any other files (like project.assets.json).
        /// </summary>
        /// <param name="libraryIdentity">The <see cref="LibraryIdentity"/> of the package.</param>
        /// <param name="settings">The NuGet settings to use.</param>
        /// <param name="logger">An <see cref="ILogger"/> to use for logging.</param>
        /// <returns></returns>
        public static Task<IReadOnlyList<RestoreResultPair>> RunWithoutCommit(LibraryIdentity libraryIdentity, ISettings settings, ILogger logger)
        {
            using (var sourceCacheContext = new SourceCacheContext
            {
                IgnoreFailedSources = true,
            })
            {
                var projectDirectory = Path.Combine(NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp), Guid.NewGuid().ToString("N", null));

                var projectName = Guid.NewGuid().ToString("N", null);

                var projectFullPath = Path.Combine(projectDirectory, $"{projectName}.proj");

                // Iterate through TargetFrameworks to generate Lists required for packageSpec
                var frameworks = new List<TargetFrameworkInformation>(TargetFrameworks.Count);
                var originalTargetFrameworks = new List<string>(TargetFrameworks.Count);
                foreach (var tf in TargetFrameworks)
                {
                    frameworks.Add(new TargetFrameworkInformation
                    {
                        FrameworkName = tf,
                        Dependencies = [new LibraryDependency()
                            {
                                LibraryRange = new LibraryRange(
                                    libraryIdentity.Name,
                                    new VersionRange(
                                        minVersion: libraryIdentity.Version,
                                        includeMinVersion: true,
                                        maxVersion: libraryIdentity.Version,
                                        includeMaxVersion: true),
                                    LibraryDependencyTarget.Package),
                                SuppressParent = LibraryIncludeFlags.All,
                                AutoReferenced = true,
                                IncludeType = LibraryIncludeFlags.None,
                            }
                        ]
                    });
                    originalTargetFrameworks.Add(tf.ToString());
                }

                // The package spec details what packages to restore
                var packageSpec = new PackageSpec(frameworks)
                {
                    RestoreMetadata = new ProjectRestoreMetadata
                    {
                        ProjectPath = projectFullPath,
                        ProjectName = projectName,
                        ProjectStyle = ProjectStyle.PackageReference,
                        ProjectUniqueName = projectFullPath,
                        OutputPath = projectDirectory,
                        OriginalTargetFrameworks = originalTargetFrameworks,
                        ConfigFilePaths = settings.GetConfigFilePaths(),
                        PackagesPath = SettingsUtility.GetGlobalPackagesFolder(settings),
                        Sources = SettingsUtility.GetEnabledSources(settings).AsList(),
                        FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList()
                    },
                    FilePath = projectFullPath,
                    Name = projectName,
                };

                var dependencyGraphSpec = new DependencyGraphSpec();

                dependencyGraphSpec.AddProject(packageSpec);

                dependencyGraphSpec.AddRestore(packageSpec.RestoreMetadata.ProjectUniqueName);

                IPreLoadedRestoreRequestProvider requestProvider = new DependencyGraphSpecRequestProvider(new RestoreCommandProvidersCache(), dependencyGraphSpec);

                var restoreArgs = new RestoreArgs
                {
                    AllowNoOp = false,
                    CacheContext = sourceCacheContext,
#pragma warning disable CS0618 // Type or member is obsolete
                    CachingSourceProvider = new CachingSourceProvider(new PackageSourceProvider(settings, enablePackageSourcesChangedEvent: false)),
#pragma warning restore CS0618 // Type or member is obsolete
                    Log = logger,
                };

                // Create requests from the arguments
                var requests = requestProvider.CreateRequests(restoreArgs).Result;

                // Restore the package without generating extra files
                return RestoreRunner.RunWithoutCommit(requests, restoreArgs);
            }
        }
    }
}