mirror of
https://github.com/aphrody-labs/NuGet.Client.git
synced 2026-10-15 22:09:04 +00:00
402 lines
20 KiB
C#
402 lines
20 KiB
C#
// 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.
|
|
|
|
#nullable disable
|
|
|
|
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.Protocol.Test;
|
|
using NuGet.RuntimeModel;
|
|
using NuGet.Test.Utility;
|
|
|
|
namespace NuGet.Commands.Test
|
|
{
|
|
public static class ProjectTestHelpers
|
|
{
|
|
/// <summary>
|
|
/// Create a restore request for the specs. Restore only the first one.
|
|
/// </summary>
|
|
public static async Task<RestoreRequest> GetRequestAsync(
|
|
RestoreArgs restoreContext,
|
|
params PackageSpec[] projects)
|
|
{
|
|
var dgSpec = GetDGSpecForFirstProject(projects);
|
|
|
|
var dgProvider = new DependencyGraphSpecRequestProvider(
|
|
new RestoreCommandProvidersCache(),
|
|
dgSpec);
|
|
|
|
var requests = await dgProvider.CreateRequests(restoreContext);
|
|
return requests.Single().Request;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a dg file for the specs. Restore only the first one.
|
|
/// </summary>
|
|
public static DependencyGraphSpec GetDGSpecForFirstProject(params PackageSpec[] projects)
|
|
{
|
|
var dgSpec = new DependencyGraphSpec();
|
|
foreach (var project in projects)
|
|
{
|
|
dgSpec.AddProject(project);
|
|
}
|
|
dgSpec.AddRestore(projects[0].RestoreMetadata.ProjectUniqueName);
|
|
return dgSpec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a dg specs with all PackageReference and project.json projects to be restored.
|
|
/// </summary>
|
|
/// <param name="projects"></param>
|
|
/// <returns></returns>
|
|
public static DependencyGraphSpec GetDGSpecForAllProjects(params PackageSpec[] projects)
|
|
{
|
|
var dgSpec = new DependencyGraphSpec();
|
|
foreach (var project in projects)
|
|
{
|
|
dgSpec.AddProject(project);
|
|
if (project.RestoreMetadata.ProjectStyle == ProjectStyle.PackageReference ||
|
|
project.RestoreMetadata.ProjectStyle == ProjectStyle.ProjectJson)
|
|
{
|
|
dgSpec.AddRestore(project.RestoreMetadata.ProjectUniqueName);
|
|
}
|
|
}
|
|
return dgSpec;
|
|
}
|
|
|
|
public static PackageSpec WithTestProjectReference(this PackageSpec parent, PackageSpec child, params NuGetFramework[] frameworks)
|
|
{
|
|
return parent.WithTestProjectReference(child, privateAssets: LibraryIncludeFlagUtils.DefaultSuppressParent, frameworks);
|
|
}
|
|
|
|
public static PackageSpec WithTestProjectReference(this PackageSpec parent, PackageSpec child, LibraryIncludeFlags privateAssets, params NuGetFramework[] frameworks)
|
|
{
|
|
var spec = parent.Clone();
|
|
|
|
if (frameworks.Length == 0)
|
|
{
|
|
// Use all frameworks if none were given
|
|
frameworks = spec.TargetFrameworks.Select(e => e.FrameworkName).ToArray();
|
|
}
|
|
|
|
foreach (var framework in spec
|
|
.RestoreMetadata
|
|
.TargetFrameworks
|
|
.Where(e => frameworks.Contains(e.FrameworkName)))
|
|
{
|
|
framework.ProjectReferences.Add(new ProjectRestoreReference()
|
|
{
|
|
ProjectUniqueName = child.RestoreMetadata.ProjectUniqueName,
|
|
ProjectPath = child.RestoreMetadata.ProjectPath,
|
|
PrivateAssets = privateAssets,
|
|
});
|
|
}
|
|
|
|
return spec;
|
|
}
|
|
|
|
public static PackageSpec WithTestProjectReferenceByAlias(this PackageSpec parent, PackageSpec child, params string[] aliases)
|
|
{
|
|
return parent.WithTestProjectReferenceByAlias(child, privateAssets: LibraryIncludeFlagUtils.DefaultSuppressParent, aliases);
|
|
}
|
|
|
|
public static PackageSpec WithTestProjectReferenceByAlias(this PackageSpec parent, PackageSpec child, LibraryIncludeFlags privateAssets, params string[] aliases)
|
|
{
|
|
var spec = parent.Clone();
|
|
|
|
foreach (var framework in spec
|
|
.RestoreMetadata
|
|
.TargetFrameworks
|
|
.Where(e => aliases.Contains(e.TargetAlias)))
|
|
{
|
|
framework.ProjectReferences.Add(new ProjectRestoreReference()
|
|
{
|
|
ProjectUniqueName = child.RestoreMetadata.ProjectUniqueName,
|
|
ProjectPath = child.RestoreMetadata.ProjectPath,
|
|
PrivateAssets = privateAssets,
|
|
});
|
|
}
|
|
|
|
return spec;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add fake PackageReference restore metadata.
|
|
/// This resembles the .NET Core based projects (<see cref="ProjectRestoreSettings"/>.
|
|
/// </summary>
|
|
public static PackageSpec WithTestRestoreMetadata(this PackageSpec spec)
|
|
{
|
|
var updated = spec.Clone();
|
|
var packageSpecFile = new FileInfo(spec.FilePath);
|
|
|
|
var projectDir = (packageSpecFile.Attributes & FileAttributes.Directory) == FileAttributes.Directory && !spec.FilePath.EndsWith(".csproj") && !spec.FilePath.EndsWith(".json") ?
|
|
packageSpecFile.FullName :
|
|
packageSpecFile.Directory.FullName;
|
|
|
|
var projectPath = Path.Combine(projectDir, spec.Name + ".csproj");
|
|
updated.FilePath = projectPath;
|
|
|
|
updated.RestoreMetadata = new ProjectRestoreMetadata();
|
|
updated.RestoreMetadata.CrossTargeting = updated.TargetFrameworks.Count > 1;
|
|
updated.RestoreMetadata.OutputPath = projectDir;
|
|
updated.RestoreMetadata.ProjectStyle = ProjectStyle.PackageReference;
|
|
updated.RestoreMetadata.ProjectName = spec.Name;
|
|
updated.RestoreMetadata.ProjectUniqueName = projectPath;
|
|
updated.RestoreMetadata.ProjectPath = projectPath;
|
|
updated.RestoreMetadata.CentralPackageVersionsEnabled = spec.RestoreMetadata?.CentralPackageVersionsEnabled ?? false;
|
|
updated.RestoreMetadata.CentralPackageTransitivePinningEnabled = spec.RestoreMetadata?.CentralPackageTransitivePinningEnabled ?? false;
|
|
if (spec.RestoreMetadata != null)
|
|
{
|
|
updated.RestoreMetadata.ProjectWideWarningProperties = spec.RestoreMetadata.ProjectWideWarningProperties.Clone();
|
|
}
|
|
updated.RestoreMetadata.RestoreAuditProperties = new RestoreAuditProperties()
|
|
{
|
|
EnableAudit = bool.FalseString
|
|
};
|
|
|
|
// Update the Target Alias.
|
|
for (int i = 0; i < updated.TargetFrameworks.Count; i++)
|
|
{
|
|
var framework = updated.TargetFrameworks[i];
|
|
if (string.IsNullOrEmpty(framework.TargetAlias))
|
|
{
|
|
updated.TargetFrameworks[i] = new TargetFrameworkInformation(framework) { TargetAlias = framework.FrameworkName.GetShortFolderName() };
|
|
}
|
|
}
|
|
|
|
foreach (var framework in updated.TargetFrameworks)
|
|
{
|
|
updated.RestoreMetadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(framework.FrameworkName) { TargetAlias = framework.TargetAlias });
|
|
}
|
|
|
|
updated.RestoreMetadata.OriginalTargetFrameworks = updated.TargetFrameworks.Select(e => e.TargetAlias).ToList();
|
|
|
|
return updated;
|
|
}
|
|
|
|
public static PackageSpec WithDependency(this PackageSpec spec, LibraryDependency libraryDependency)
|
|
{
|
|
AddDependency(spec, libraryDependency);
|
|
|
|
return spec;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a restore request for the first project in the <paramref name="projects"/> list. If <see cref="ProjectRestoreMetadata.Sources"/> has any values, it is used for creating the providers, otherwise <see cref="SimpleTestPathContext.PackageSource"/> from <paramref name="pathContext"/> will be used.
|
|
/// </summary>
|
|
public static TestRestoreRequest CreateRestoreRequest(SimpleTestPathContext pathContext, ILogger logger, params PackageSpec[] projects)
|
|
{
|
|
return CreateRestoreRequest(pathContext, logger, auditSources: null, projects);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a restore request for the first project in the <paramref name="projects"/> list. If <see cref="ProjectRestoreMetadata.Sources"/> has any values, it is used for creating the providers, otherwise <see cref="SimpleTestPathContext.PackageSource"/> from <paramref name="pathContext"/> will be used.
|
|
/// When <paramref name="auditSources"/> is not null, it is used as the audit sources; otherwise the audit sources are loaded from the settings in <paramref name="pathContext"/>.
|
|
/// </summary>
|
|
public static TestRestoreRequest CreateRestoreRequest(SimpleTestPathContext pathContext, ILogger logger, IReadOnlyList<SourceRepository> auditSources, params PackageSpec[] projects)
|
|
{
|
|
DependencyGraphSpec dgSpec = GetDGSpecForFirstProject(projects);
|
|
var projectToRestore = projects[0];
|
|
var sources = projectToRestore.RestoreMetadata.Sources.Any() ?
|
|
projectToRestore.RestoreMetadata.Sources.ToList() :
|
|
[new PackageSource(pathContext.PackageSource)];
|
|
|
|
var externalClosure = DependencyGraphSpecRequestProvider.GetExternalClosure(dgSpec, projectToRestore.RestoreMetadata.ProjectUniqueName).ToList();
|
|
ISettings settings = Settings.LoadDefaultSettings(pathContext.SolutionRoot);
|
|
var packageSourceMapping = PackageSourceMapping.GetPackageSourceMapping(settings);
|
|
|
|
if (auditSources == null)
|
|
{
|
|
IReadOnlyList<PackageSource> auditPackageSources = new PackageSourceProvider(settings).LoadAuditSources();
|
|
auditSources = auditPackageSources.Count == 0
|
|
? Array.Empty<SourceRepository>()
|
|
: auditPackageSources.Select(Repository.Factory.GetCoreV3).ToList();
|
|
}
|
|
|
|
return new TestRestoreRequest(projectToRestore, sources, pathContext.UserPackagesFolder, new TestSourceCacheContext(), packageSourceMapping, logger, auditSources)
|
|
{
|
|
LockFilePath = Path.Combine(projectToRestore.RestoreMetadata.OutputPath, LockFileFormat.AssetsFileName),
|
|
DependencyGraphSpec = dgSpec,
|
|
ExternalProjects = externalClosure,
|
|
};
|
|
}
|
|
|
|
public static RuntimeGraph GetRuntimeGraph(IEnumerable<string> runtimeIdentifiers, IEnumerable<string> runtimeSupports)
|
|
{
|
|
var runtimes = runtimeIdentifiers?
|
|
.Distinct(StringComparer.Ordinal)
|
|
.Select(rid => new RuntimeDescription(rid))
|
|
.ToList()
|
|
?? Enumerable.Empty<RuntimeDescription>();
|
|
|
|
var supports = runtimeSupports?
|
|
.Distinct(StringComparer.Ordinal)
|
|
.Select(s => new CompatibilityProfile(s))
|
|
.ToList()
|
|
?? Enumerable.Empty<CompatibilityProfile>();
|
|
|
|
return new RuntimeGraph(runtimes, supports);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a PackageReference spec.
|
|
/// </summary>
|
|
/// <param name="projectName">Project name</param>
|
|
/// <param name="rootPath">Root path, normally solution root. The project is gonna be "located" at rootPath/projectName/projectName.csproj </param>
|
|
/// <param name="framework">framework</param>
|
|
/// <param name="useAssetTargetFallback">Whether to use ATF. Default is false.</param>
|
|
/// <param name="assetTargetFallbackFrameworks">ATF string.</param>
|
|
/// <returns>Returns a PackageReference spec with all details similar to what a spec from a nomination would contain.</returns>
|
|
public static PackageSpec GetPackageSpec(string projectName, string rootPath = @"C:\", string framework = "net5.0", bool useAssetTargetFallback = false, string assetTargetFallbackFrameworks = "")
|
|
{
|
|
var actualAssetTargetFallback = GetFallbackString(useAssetTargetFallback, assetTargetFallbackFrameworks);
|
|
|
|
const string referenceSpec = @"
|
|
{
|
|
""frameworks"": {
|
|
""TARGET_FRAMEWORK"": {
|
|
""dependencies"": {
|
|
}
|
|
ASSET_TARGET_FALLBACK
|
|
}
|
|
}
|
|
}";
|
|
|
|
var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework).Replace("ASSET_TARGET_FALLBACK", actualAssetTargetFallback);
|
|
return GetPackageSpecWithProjectNameAndSpec(projectName, rootPath, spec);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a PackageReference spec.
|
|
/// </summary>
|
|
/// <param name="settings">Settings to be used for the restore metadata.</param>
|
|
/// <param name="projectName">Project name</param>
|
|
/// <param name="rootPath">Root path, normally solution root. The project is gonna be "located" at rootPath/projectName/projectName.csproj </param>
|
|
/// <param name="framework">framework</param>
|
|
/// <returns>Returns a PackageReference spec with all details similar to what a spec after the post processing before restore would look like.
|
|
/// The RestoreMetadata has the settings, sources etc set based on the ISettings provided.
|
|
/// </returns>
|
|
public static PackageSpec GetPackageSpec(ISettings settings, string projectName, string rootPath = @"C:\", string framework = "net5.0")
|
|
{
|
|
var packageSpec = GetPackageSpec(projectName, rootPath, framework);
|
|
return packageSpec.WithSettingsBasedRestoreMetadata(settings);
|
|
}
|
|
|
|
public static PackageSpec GetPackageSpec(ISettings settings, string projectName, string rootPath, string framework, string dependencyName, bool useAssetTargetFallback = false, string assetTargetFallbackFrameworks = "", bool asAssetTargetFallback = true)
|
|
{
|
|
var packageSpec = GetPackageSpec(projectName, rootPath, framework, dependencyName, "1.0.0", useAssetTargetFallback, assetTargetFallbackFrameworks, asAssetTargetFallback);
|
|
return packageSpec.WithSettingsBasedRestoreMetadata(settings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update restore metadata based on configuration.
|
|
/// </summary>
|
|
public static PackageSpec WithSettingsBasedRestoreMetadata(this PackageSpec packageSpec, ISettings settings)
|
|
{
|
|
packageSpec.RestoreMetadata.ConfigFilePaths = settings.GetConfigFilePaths();
|
|
packageSpec.RestoreMetadata.Sources = SettingsUtility.GetEnabledSources(settings).ToList();
|
|
packageSpec.RestoreMetadata.FallbackFolders = SettingsUtility.GetFallbackPackageFolders(settings).ToList();
|
|
packageSpec.RestoreMetadata.PackagesPath = SettingsUtility.GetGlobalPackagesFolder(settings);
|
|
return packageSpec;
|
|
}
|
|
|
|
public static PackageSpec GetPackageSpec(string projectName, string rootPath, string framework, string dependencyName, string dependencyVersion = "1.0.0", bool useAssetTargetFallback = false, string assetTargetFallbackFrameworks = "", bool asAssetTargetFallback = true)
|
|
{
|
|
var actualAssetTargetFallback = GetFallbackString(useAssetTargetFallback, assetTargetFallbackFrameworks, asAssetTargetFallback);
|
|
|
|
const string referenceSpec = @"
|
|
{
|
|
""frameworks"": {
|
|
""TARGET_FRAMEWORK"": {
|
|
""dependencies"": {
|
|
""DEPENDENCY_NAME"" : ""VERSION""
|
|
}
|
|
ASSET_TARGET_FALLBACK
|
|
}
|
|
}
|
|
}";
|
|
|
|
var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework).Replace("DEPENDENCY_NAME", dependencyName).Replace("VERSION", dependencyVersion).Replace("ASSET_TARGET_FALLBACK", actualAssetTargetFallback);
|
|
return GetPackageSpecWithProjectNameAndSpec(projectName, rootPath, spec);
|
|
}
|
|
|
|
private static string GetFallbackString(bool useAssetTargetFallback, string assetTargetFallbackFrameworks, bool asAssetTargetFallback = true)
|
|
{
|
|
const string assetTargetFallback = @",
|
|
""assetTargetFallback"" : ATF_VALUE,
|
|
""imports"" : [ ""ASSET_TARGET_FALLBACK_FRAMEWORK_LIST"" ],
|
|
""warn"" : true
|
|
";
|
|
var actualAssetTargetFallback = useAssetTargetFallback ?
|
|
assetTargetFallback.Replace("ASSET_TARGET_FALLBACK_FRAMEWORK_LIST", assetTargetFallbackFrameworks)
|
|
.Replace("ATF_VALUE", asAssetTargetFallback.ToString().ToLowerInvariant()) :
|
|
string.Empty;
|
|
return actualAssetTargetFallback;
|
|
}
|
|
|
|
public static PackageSpec GetPackageSpecWithProjectNameAndSpec(string projectName, string rootPath, string spec)
|
|
{
|
|
return JsonPackageSpecReader.GetPackageSpec(spec, projectName, Path.Combine(rootPath, projectName, projectName)).WithTestRestoreMetadata();
|
|
}
|
|
|
|
public static PackageSpec GetPackagesConfigPackageSpec(string projectName, string rootPath = @"C:\", string framework = "net472")
|
|
{
|
|
const string referenceSpec = @"
|
|
{
|
|
""frameworks"": {
|
|
""TARGET_FRAMEWORK"": {
|
|
""dependencies"": {
|
|
}
|
|
}
|
|
}
|
|
}";
|
|
|
|
var spec = referenceSpec.Replace("TARGET_FRAMEWORK", framework);
|
|
var packageSpec = JsonPackageSpecReader.GetPackageSpec(spec, projectName, Path.Combine(rootPath, projectName, projectName));
|
|
|
|
var packageSpecFile = new FileInfo(packageSpec.FilePath);
|
|
var projectDir = packageSpecFile.Directory.FullName;
|
|
|
|
var projectPath = Path.Combine(projectDir, packageSpec.Name + ".csproj");
|
|
packageSpec.FilePath = projectPath;
|
|
|
|
packageSpec.RestoreMetadata = new PackagesConfigProjectRestoreMetadata();
|
|
packageSpec.RestoreMetadata.OutputPath = projectDir;
|
|
packageSpec.RestoreMetadata.ProjectStyle = ProjectStyle.PackagesConfig;
|
|
packageSpec.RestoreMetadata.ProjectName = packageSpec.Name;
|
|
packageSpec.RestoreMetadata.ProjectUniqueName = projectPath;
|
|
packageSpec.RestoreMetadata.ProjectPath = projectPath;
|
|
packageSpec.RestoreMetadata.ConfigFilePaths = new List<string>();
|
|
(packageSpec.RestoreMetadata as PackagesConfigProjectRestoreMetadata).PackagesConfigPath = Path.GetFullPath(Path.Combine(projectDir, "../packages"));
|
|
|
|
foreach (var targetFramework in packageSpec.TargetFrameworks)
|
|
{
|
|
packageSpec.RestoreMetadata.TargetFrameworks.Add(new ProjectRestoreMetadataFrameworkInfo(targetFramework.FrameworkName));
|
|
}
|
|
return packageSpec;
|
|
}
|
|
|
|
public static void AddDependency(PackageSpec spec, LibraryDependency libraryDependency)
|
|
{
|
|
for (int i = 0; i < spec.TargetFrameworks.Count; i++)
|
|
{
|
|
spec.TargetFrameworks[i] = new TargetFrameworkInformation(spec.TargetFrameworks[i])
|
|
{
|
|
Dependencies = [.. spec.TargetFrameworks[i].Dependencies, libraryDependency]
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|