diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs index f46af199399b..22a7c18d3b47 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs @@ -169,31 +169,28 @@ bool TryGetWorkloadSet(string workloadSetVersion, out WorkloadSet? workloadSet) } } + _installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkVersionBand, _sdkRootPath), "default.json"); + var installState = InstallStateContents.FromPath(_installStateFilePath); if (_workloadSet is null) { - var installStateFilePath = Path.Combine(WorkloadInstallType.GetInstallStateFolder(_sdkVersionBand, _sdkRootPath), "default.json"); - if (File.Exists(installStateFilePath)) + if (!string.IsNullOrEmpty(installState.WorkloadVersion)) { - var installState = InstallStateContents.FromPath(installStateFilePath); - if (!string.IsNullOrEmpty(installState.WorkloadVersion)) + if (!TryGetWorkloadSet(installState.WorkloadVersion!, out _workloadSet)) { - if (!TryGetWorkloadSet(installState.WorkloadVersion!, out _workloadSet)) - { - throw new FileNotFoundException(string.Format(Strings.WorkloadVersionFromInstallStateNotFound, installState.WorkloadVersion, installStateFilePath)); - } + throw new FileNotFoundException(string.Format(Strings.WorkloadVersionFromInstallStateNotFound, installState.WorkloadVersion, _installStateFilePath)); } - - // Note: It is possible here to have both a workload set and loose manifests listed in the install state. This might happen if there is a - // third-party workload manifest installed that's not part of the workload set - _manifestsFromInstallState = installState.Manifests is null ? null : WorkloadSet.FromDictionaryForJson(installState.Manifests, _sdkVersionBand); - _installStateFilePath = installStateFilePath; } + + // Note: It is possible here to have both a workload set and loose manifests listed in the install state. This might happen if there is a + // third-party workload manifest installed that's not part of the workload set + _manifestsFromInstallState = installState.Manifests is null ? null : WorkloadSet.FromDictionaryForJson(installState.Manifests, _sdkVersionBand); } - if (_workloadSet == null && availableWorkloadSets.Any()) + if (_workloadSet == null && installState.UseWorkloadSets == true && availableWorkloadSets.Any()) { var maxWorkloadSetVersion = availableWorkloadSets.Keys.Aggregate((s1, s2) => VersionCompare(s1, s2) >= 0 ? s1 : s2); _workloadSet = availableWorkloadSets[maxWorkloadSetVersion.ToString()]; + _useManifestsFromInstallState = false; } } diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs index 081d8c260a61..f3e02e55773c 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Workloads.Workload; using Microsoft.NET.Sdk.Localization; using Microsoft.NET.Sdk.WorkloadManifestReader; @@ -31,6 +32,40 @@ void Initialize(string featureBand = "5.0.100", [CallerMemberName] string? testN Directory.CreateDirectory(_manifestVersionBandDirectory); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ItShouldPrioritizeInstallStateOverWorkloadSetUnlessSpecified(bool preferWorkloadSet) + { + Initialize(); + + CreateMockManifest(_manifestRoot, "8.0.400", "ios", "11.0.2", true); + CreateMockManifest(_manifestRoot, "8.0.400", "ios", "11.0.6", true); + CreateMockWorkloadSet(_manifestRoot, "8.0.400", "8.0.400", @" + { + ""ios"": ""11.0.2/8.0.400"" + } + "); + + var installStateLocation = WorkloadInstallType.GetInstallStateFolder(new SdkFeatureBand("8.0.400"), Path.GetDirectoryName(_manifestRoot)!); + var installStateFilePath = Path.Combine(installStateLocation, "default.json"); + var installState = InstallStateContents.FromPath(installStateFilePath); + installState.UseWorkloadSets = preferWorkloadSet; + installState.Manifests = new Dictionary() + { + { "ios", "11.0.6/8.0.400" } + }; + Directory.CreateDirectory(installStateLocation); + File.WriteAllText(installStateFilePath, installState.ToString()); + + var sdkDirectoryWorkloadManifestProvider + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.400", userProfileDir: null, globalJsonPath: null); + + sdkDirectoryWorkloadManifestProvider.GetManifests().Single().ManifestVersion.Should().Be(preferWorkloadSet ? "11.0.2" : "11.0.6"); + + Directory.Delete(Path.Combine(_manifestRoot, "8.0.400"), recursive: true); + } + [Theory] [InlineData(true)] [InlineData(false)] @@ -418,6 +453,13 @@ public void WorkloadSetCanIncludeMultipleJsonFiles() CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2-rc.1", true); CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2", true); + // To prepare the resolver to work with workload sets, we need to specify 'workload sets' in the install state file. + var installStateLocation = WorkloadInstallType.GetInstallStateFolder(new SdkFeatureBand("8.0.200"), Path.GetDirectoryName(_manifestRoot)!); + var installStateFilePath = Path.Combine(installStateLocation, "default.json"); + var installState = InstallStateContents.FromPath(installStateFilePath); + installState.UseWorkloadSets = true; + Directory.CreateDirectory(installStateLocation); + File.WriteAllText(installStateFilePath, installState.ToString()); var workloadSetDirectory = Path.Combine(_manifestRoot, "8.0.200", "workloadsets", "8.0.200"); Directory.CreateDirectory(workloadSetDirectory); @@ -1254,6 +1296,14 @@ private void CreateMockManifest(string manifestRoot, string featureBand, string private void CreateMockWorkloadSet(string manifestRoot, string featureBand, string workloadSetVersion, string workloadSetContents) { + // To prepare the resolver to work with workload sets, we need to specify 'workload sets' in the install state file. + var installStateLocation = WorkloadInstallType.GetInstallStateFolder(new SdkFeatureBand(featureBand), Path.GetDirectoryName(manifestRoot)!); + var installStateFilePath = Path.Combine(installStateLocation, "default.json"); + var installState = InstallStateContents.FromPath(installStateFilePath); + installState.UseWorkloadSets = true; + Directory.CreateDirectory(installStateLocation); + File.WriteAllText(installStateFilePath, installState.ToString()); + var workloadSetDirectory = Path.Combine(manifestRoot, featureBand, "workloadsets", workloadSetVersion); if (!Directory.Exists(workloadSetDirectory)) {