Skip to content

Commit d545b91

Browse files
authored
Use the .NET SDK version to control the new assets file format (#7118)
1 parent 7ed3250 commit d545b91

8 files changed

Lines changed: 133 additions & 41 deletions

File tree

build/DotNetSdkTestVersions.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
# To make sure that the right version of dotnet.exe (and maybe other files) is used, always install from lowest version to highest version
33
-Channel 8.0 -Runtime dotnet
44
-Channel 9.0 -Runtime dotnet
5-
-Channel 10.0.2xx -Quality daily
5+
-Channel 10.0.3xx -Quality daily

src/NuGet.Core/NuGet.Build.Tasks.Console/MSBuildStaticGraphRestore.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using Microsoft.Build.Graph;
2626
using Microsoft.Build.Logging;
2727
using NuGet.Commands;
28+
using NuGet.Commands.Restore;
2829
using NuGet.Commands.Restore.Utility;
2930
using NuGet.Common;
3031
using NuGet.Configuration;
@@ -566,6 +567,23 @@ internal static NuGetVersion GetProjectVersion(IMSBuildItem project)
566567
return NuGetVersion.Parse(version);
567568
}
568569

570+
/// <summary>
571+
/// Gets the .NET SDK version. If not specified, it will return null.
572+
/// </summary>
573+
/// <param name="project">The <see cref="ITargetFramework" /> representing the project.</param>
574+
/// <returns>The <see cref="NuGetVersion" /> of the .NET SDK if one was found, otherwise <see langword="null">null</see>.</returns>
575+
internal static NuGetVersion GetSdkVersion(IMSBuildItem project)
576+
{
577+
string version = project.GetProperty("NETCoreSdkVersion");
578+
579+
if (version == null)
580+
{
581+
return null;
582+
}
583+
584+
return NuGetVersion.Parse(version);
585+
}
586+
569587
/// <summary>
570588
/// Gets the repository path for the specified project.
571589
/// </summary>
@@ -975,7 +993,11 @@ private PackageSpec GetPackageSpec(IMSBuildProject project, IReadOnlyDictionary<
975993
.Select(s => new CompatibilityProfile(s))
976994
.ToList()
977995
),
978-
Version = GetProjectVersion(project)
996+
Version = GetProjectVersion(project),
997+
RestoreSettings = new ProjectRestoreSettings()
998+
{
999+
SdkVersion = GetSdkVersion(project)
1000+
}
9791001
};
9801002

9811003
return packageSpec;

src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ Copyright (c) .NET Foundation. All rights reserved.
959959
<NuGetAuditMode>$(NuGetAuditMode)</NuGetAuditMode>
960960
<SdkAnalysisLevel>$(SdkAnalysisLevel)</SdkAnalysisLevel>
961961
<UsingMicrosoftNETSdk>$(UsingMicrosoftNETSdk)</UsingMicrosoftNETSdk>
962+
<NETCoreSdkVersion>$(NETCoreSdkVersion)</NETCoreSdkVersion>
962963
<RestoreUseLegacyDependencyResolver>$(RestoreUseLegacyDependencyResolver)</RestoreUseLegacyDependencyResolver>
963964
</_RestoreGraphEntry>
964965
</ItemGroup>

src/NuGet.Core/NuGet.Commands/RestoreCommand/RestoreCommand.cs

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,19 +1479,13 @@ private LockFile BuildAssetsFile(
14791479

14801480
int DetermineLockFileVersion()
14811481
{
1482-
int lockFileVersion = _request.LockFileVersion;
1483-
1484-
// We use the request provided version, unless we are using the Microsoft.NET.Sdk that does not support reading of aliased assets files.
1485-
if (_request.Project.RestoreMetadata.UsingMicrosoftNETSdk &&
1486-
!SdkAnalysisLevelMinimums.IsEnabled(
1487-
_request.Project.RestoreMetadata.SdkAnalysisLevel,
1488-
_request.Project.RestoreMetadata.UsingMicrosoftNETSdk,
1489-
SdkAnalysisLevelMinimums.V10_0_300))
1482+
// We use the request provided version, unless we are using the Microsoft.NET.Sdk version that does not support reading of aliased assets files.
1483+
if (DoesProjectToolsetSupportsDuplicateFrameworks(_request.Project))
14901484
{
1491-
lockFileVersion = LockFileFormat.LegacyVersion;
1485+
return _request.LockFileVersion;
14921486
}
14931487

1494-
return lockFileVersion;
1488+
return LockFileFormat.LegacyVersion;
14951489
}
14961490
}
14971491

@@ -1874,12 +1868,7 @@ private static async Task<IList<CompatibilityCheckResult>> VerifyCompatibilityAs
18741868

18751869
return (success, []);
18761870
}
1877-
1878-
bool shouldDoDuplicatesCheck = _request.Project.RestoreMetadata.UsingMicrosoftNETSdk &&
1879-
!SdkAnalysisLevelMinimums.IsEnabled(
1880-
_request.Project.RestoreMetadata.SdkAnalysisLevel,
1881-
_request.Project.RestoreMetadata.UsingMicrosoftNETSdk,
1882-
SdkAnalysisLevelMinimums.V10_0_300);
1871+
var shouldDoDuplicatesCheck = !DoesProjectToolsetSupportsDuplicateFrameworks(_request.Project);
18831872

18841873
if (shouldDoDuplicatesCheck)
18851874
{
@@ -1982,6 +1971,46 @@ private static async Task<IList<CompatibilityCheckResult>> VerifyCompatibilityAs
19821971
return (success, graphs);
19831972
}
19841973

1974+
private static bool DoesProjectToolsetSupportsDuplicateFrameworks(PackageSpec project)
1975+
{
1976+
if (project.RestoreMetadata.UsingMicrosoftNETSdk &&
1977+
!SdkAnalysisLevelMinimums.IsEnabled(
1978+
project.RestoreMetadata.SdkAnalysisLevel,
1979+
project.RestoreMetadata.UsingMicrosoftNETSdk,
1980+
SdkAnalysisLevelMinimums.V10_0_300))
1981+
{
1982+
return false;
1983+
}
1984+
else
1985+
{
1986+
// If the SDK version is a prerelease, we need to ensure it's a prerelease version that can handle the aliased assets file.
1987+
if (project.RestoreSettings.SdkVersion?.IsPrerelease == true)
1988+
{
1989+
if (project.RestoreSettings.SdkVersion.Major == 10
1990+
&& project.RestoreSettings.SdkVersion.Minor == 0
1991+
&& project.RestoreSettings.SdkVersion.Patch == 300)
1992+
{
1993+
if (project.RestoreSettings.SdkVersion < NuGetVersion.Parse("10.0.300-preview.1"))
1994+
{
1995+
return false;
1996+
}
1997+
}
1998+
if (project.RestoreSettings.SdkVersion.Major == 11
1999+
&& project.RestoreSettings.SdkVersion.Minor == 0
2000+
&& project.RestoreSettings.SdkVersion.Patch == 100)
2001+
{
2002+
if (project.RestoreSettings.SdkVersion < NuGetVersion.Parse("11.0.100-preview.1.26104"))
2003+
{
2004+
return false;
2005+
}
2006+
}
2007+
return true;
2008+
}
2009+
}
2010+
2011+
return true;
2012+
}
2013+
19852014
// Check for duplicate frameworks and log an error if found.
19862015
// Returns true if duplicates exist, false otherwise.
19872016
private static async ValueTask<bool> ErrorForDuplicateFrameworks(RestoreRequest request, ILogger logger)

src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/MSBuildRestoreUtility.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ public static PackageSpec GetPackageSpec(IEnumerable<IMSBuildItem> items)
293293
result.RestoreMetadata.UsingMicrosoftNETSdk = GetUsingMicrosoftNETSdk(specItem.GetProperty("UsingMicrosoftNETSdk"));
294294
result.RestoreMetadata.SdkAnalysisLevel = GetSdkAnalysisLevel(specItem.GetProperty("SdkAnalysisLevel"));
295295
result.RestoreMetadata.UseLegacyDependencyResolver = IsPropertyTrue(specItem, "RestoreUseLegacyDependencyResolver");
296+
result.RestoreSettings.SdkVersion = GetSdkAnalysisLevel(specItem.GetProperty("NETCoreSdkVersion"));
296297
}
297298

298299
return result;

src/NuGet.Core/NuGet.Commands/RestoreCommand/Utility/PackageSpecFactory.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ public static class PackageSpecFactory
6060
.Select(s => new CompatibilityProfile(s))
6161
.ToList()
6262
),
63-
Version = GetProjectVersion(project.OuterBuild)
63+
Version = GetProjectVersion(project.OuterBuild),
64+
RestoreSettings = new ProjectRestoreSettings()
65+
{
66+
SdkVersion = GetSdkVersion(project.OuterBuild)
67+
}
6468
};
6569

6670
return packageSpec;
@@ -83,6 +87,23 @@ internal static NuGetVersion GetProjectVersion(ITargetFramework project)
8387
return NuGetVersion.Parse(version);
8488
}
8589

90+
/// <summary>
91+
/// Gets the .NET SDK version. If not specified, it will return null.
92+
/// </summary>
93+
/// <param name="project">The <see cref="ITargetFramework" /> representing the project.</param>
94+
/// <returns>The <see cref="NuGetVersion" /> of the .NET SDK if one was found, otherwise <see langword="null">null</see>.</returns>
95+
internal static NuGetVersion? GetSdkVersion(ITargetFramework project)
96+
{
97+
string? version = project.GetProperty("NETCoreSdkVersion");
98+
99+
if (version == null)
100+
{
101+
return null;
102+
}
103+
104+
return NuGetVersion.Parse(version);
105+
}
106+
86107
/// <summary>
87108
/// Gets the restore metadata and target framework information for the specified project.
88109
/// </summary>

test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3413,7 +3413,7 @@ public void DotnetRestore_PackageReferenceWithNoVersion_OutputExpectedDiagnostic
34133413

34143414
// P1 (banana) -> X
34153415
// P1 (apple) -> Y
3416-
[PlatformFact(Platform.Windows)]
3416+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
34173417
public async Task DotnetRestore_WithAliasesOfTheSameFramework_UsesCorrectPackages()
34183418
{
34193419
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3433,7 +3433,6 @@ public async Task DotnetRestore_WithAliasesOfTheSameFramework_UsesCorrectPackage
34333433
{
34343434
var xml = XDocument.Load(stream);
34353435
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3436-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
34373436

34383437
var attributes = new Dictionary<string, string>() { { "Version", "1.0.0" } };
34393438

@@ -3486,7 +3485,7 @@ public async Task DotnetRestore_WithAliasesOfTheSameFramework_UsesCorrectPackage
34863485

34873486
// P (apple) -> Net472 package, with ATF, succeeds
34883487
// P (banana) -> Net472 package, with ATF, fails
3489-
[PlatformFact(Platform.Windows)]
3488+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
34903489
public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallback_OneSucceedsOneFails()
34913490
{
34923491
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3507,7 +3506,6 @@ public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallba
35073506
{
35083507
var xml = XDocument.Load(stream);
35093508
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3510-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
35113509

35123510
var attributes = new Dictionary<string, string>() { { "Version", "1.0.0" } };
35133511

@@ -3570,7 +3568,7 @@ public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallba
35703568

35713569
// P (apple) -> Net472 package -> Transitive Net472 package, with ATF, succeeds
35723570
// P (banana) -> Net472 package, with ATF, fails
3573-
[PlatformFact(Platform.Windows)]
3571+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
35743572
public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallback_TransitiveDependenciesFlowCorrectly()
35753573
{
35763574
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3597,7 +3595,6 @@ public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallba
35973595
{
35983596
var xml = XDocument.Load(stream);
35993597
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3600-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
36013598

36023599
var attributes = new Dictionary<string, string>() { { "Version", "1.0.0" } };
36033600

@@ -3665,7 +3662,7 @@ public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallba
36653662

36663663
// P (apple) -> Project2 (apple) -> Package A
36673664
// P (banana) -> Project2 (banana) -> Package B
3668-
[PlatformFact(Platform.Windows)]
3665+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
36693666
public async Task DotnetRestore_WithAliasesOfSameFrameworkAndProjectReferences_TransitivePackageDependenciesFlowCorrectly()
36703667
{
36713668
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3687,7 +3684,6 @@ public async Task DotnetRestore_WithAliasesOfSameFrameworkAndProjectReferences_T
36873684
{
36883685
var xml = XDocument.Load(stream);
36893686
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3690-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
36913687

36923688
var attributesA = new Dictionary<string, string>() { { "Version", "1.0.0" } };
36933689
var attributesB = new Dictionary<string, string>() { { "Version", "1.0.0" } };
@@ -3737,7 +3733,6 @@ public async Task DotnetRestore_WithAliasesOfSameFrameworkAndProjectReferences_T
37373733
{
37383734
var xml = XDocument.Load(stream);
37393735
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3740-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
37413736

37423737
// Add project reference to project2
37433738
ProjectFileUtils.AddItem(
@@ -3787,7 +3782,7 @@ public async Task DotnetRestore_WithAliasesOfSameFrameworkAndProjectReferences_T
37873782

37883783
// P (apple) -> Project2
37893784
// P (banana) -> Project3
3790-
[PlatformFact(Platform.Windows)]
3785+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
37913786
public async Task DotnetRestore_WithAliasesOfSameFramework_MultipleProjectReferencesFlowCorrectly()
37923787
{
37933788
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3813,7 +3808,6 @@ public async Task DotnetRestore_WithAliasesOfSameFramework_MultipleProjectRefere
38133808
{
38143809
var xml = XDocument.Load(stream);
38153810
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3816-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
38173811

38183812
// Add Project2 reference only for apple alias
38193813
ProjectFileUtils.AddItem(
@@ -3940,7 +3934,7 @@ public async Task DotnetRestore_WithAliasesOfTheSameFramework_AndSDKAnalysisLeve
39403934

39413935
// P (apple) -> Project2 with APPLE constant -> Uses Project2Type
39423936
// P (banana) -> Project3 with BANANA constant -> Uses Project3Type
3943-
[PlatformFact(Platform.Windows)]
3937+
[PlatformFact(Platform.Windows, Skip = "https://github.com/NuGet/Client.Engineering/issues/3632")]
39443938
public async Task DotnetRestore_WithAliasesOfSameFramework_MultipleProjectReferencesWithConditionalCompilation_BuildSucceeds()
39453939
{
39463940
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
@@ -3990,7 +3984,6 @@ public class Project3Type
39903984
{
39913985
var xml = XDocument.Load(stream);
39923986
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
3993-
ProjectFileUtils.AddProperty(xml, "SDKAnalysisLevel", "10.0.300");
39943987

39953988
// Add Project2 reference only for apple alias
39963989
ProjectFileUtils.AddItem(

test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommand_Aliases.cs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -409,13 +409,40 @@ public async Task RestoreCommand_WithAliasesOfSameFramework_MultipleProjectRefer
409409
bananaTarget.Libraries.Should().Contain(e => e.Name!.Equals("Project3"));
410410
}
411411

412-
// P1 (banana) -> X
413-
// P1 (apple) -> Y
414-
[Fact]
415-
public async Task RestoreCommand_WithAliasesOfSameFramework_And10_0_200_FailsWithNU1018()
412+
[Theory]
413+
[InlineData("10.0.200", "10.0.300")]
414+
[InlineData("10.0.300", "10.0.300-preview.0.12345")]
415+
[InlineData("11.0.100", "11.0.100-preview.1.26103")]
416+
public async Task RestoreCommand_WithAliasesOfSameFramework_AndIncompatibleSDKAnalysisLevelAndSDKVersionCombinations_FailsWithNU1018(string sdkAnalysisLevel, string sdkVersion)
416417
{
417418
using var pathContext = new SimpleTestPathContext();
418419

420+
RestoreResult result = await RunSimpleAliasedRestoreWithSDKAnalysisLevelAndSDKVersion(pathContext, sdkAnalysisLevel, sdkVersion);
421+
422+
result.Success.Should().BeFalse();
423+
result.LockFile.LogMessages.Should().HaveCount(1);
424+
result.LockFile.LogMessages[0].Code.Should().Be(NuGetLogCode.NU1018);
425+
}
426+
427+
[Theory]
428+
[InlineData("10.0.300", "10.0.300")]
429+
[InlineData("10.0.300", "10.0.400")]
430+
[InlineData("10.0.300", null)] // Null value means we let it be.
431+
[InlineData("10.0.300", "10.0.300-preview.1.12345")] // This is a dummy value that'll need to be updated once we have a real one.
432+
[InlineData("11.0.100", "11.0.100-preview.1.26104")]
433+
[InlineData("11.0.100", "11.0.100")]
434+
[InlineData("11.0.100", "11.0.101")]
435+
public async Task RestoreCommand_WithAliasesOfSameFramework_AndValidSDKAnalysisLevelAndSDKVersionCombinations_Succeeds(string sdkAnalysisLevel, string sdkVersion)
436+
{
437+
using var pathContext = new SimpleTestPathContext();
438+
439+
RestoreResult result = await RunSimpleAliasedRestoreWithSDKAnalysisLevelAndSDKVersion(pathContext, sdkAnalysisLevel, sdkVersion);
440+
441+
result.Success.Should().BeTrue();
442+
}
443+
444+
private static async Task<RestoreResult> RunSimpleAliasedRestoreWithSDKAnalysisLevelAndSDKVersion(SimpleTestPathContext pathContext, string sdkAnalysisLevel, string sdkVersion)
445+
{
419446
// Setup packages
420447
var packageA = new SimpleTestPackageContext("packageA", "1.0.0")
421448
{
@@ -461,14 +488,12 @@ await SimpleTestPackageUtility.CreatePackagesAsync(
461488
new SimpleTestPackageContext("x", "1.0.0"),
462489
new SimpleTestPackageContext("y", "1.0.0"));
463490

464-
projectSpec.RestoreMetadata.SdkAnalysisLevel = NuGetVersion.Parse("10.0.200");
491+
projectSpec.RestoreMetadata.SdkAnalysisLevel = NuGetVersion.Parse(sdkAnalysisLevel);
465492
projectSpec.RestoreMetadata.UsingMicrosoftNETSdk = true;
493+
projectSpec.RestoreSettings.SdkVersion = sdkVersion != null ? NuGetVersion.Parse(sdkVersion) : null;
466494

467495
// Act & Assert
468-
var result = await RunRestoreAsync(pathContext, projectSpec);
469-
result.Success.Should().BeFalse();
470-
result.LockFile.LogMessages.Should().HaveCount(1);
471-
result.LockFile.LogMessages[0].Code.Should().Be(NuGetLogCode.NU1018);
496+
return await RunRestoreAsync(pathContext, projectSpec);
472497
}
473498

474499
internal static Task<RestoreResult> RunRestoreAsync(SimpleTestPathContext pathContext, params PackageSpec[] projects)

0 commit comments

Comments
 (0)