Skip to content

Commit 63b3654

Browse files
authored
Merge pull request #28627 from dsplaisted/workload-manifest-targets-import-order
Return workload manifests in defined, controllable order
2 parents 141ab83 + 5548480 commit 63b3654

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.ComponentModel.DataAnnotations;
67
using System.IO;
78
using System.Linq;
89
using Microsoft.DotNet.Cli;
@@ -17,7 +18,7 @@ public class SdkDirectoryWorkloadManifestProvider : IWorkloadManifestProvider
1718
private readonly string [] _manifestDirectories;
1819
private static HashSet<string> _outdatedManifestIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "microsoft.net.workload.android", "microsoft.net.workload.blazorwebassembly", "microsoft.net.workload.ios",
1920
"microsoft.net.workload.maccatalyst", "microsoft.net.workload.macos", "microsoft.net.workload.tvos" };
20-
private readonly HashSet<string>? _knownManifestIds;
21+
private readonly Dictionary<string, int>? _knownManifestIdsAndOrder;
2122

2223
public SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, string? userProfileDir)
2324
: this(sdkRootPath, sdkVersion, Environment.GetEnvironmentVariable, userProfileDir)
@@ -44,7 +45,12 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers
4445
var knownManifestIdsFilePath = Path.Combine(_sdkRootPath, "sdk", sdkVersion, "IncludedWorkloadManifests.txt");
4546
if (File.Exists(knownManifestIdsFilePath))
4647
{
47-
_knownManifestIds = File.ReadAllLines(knownManifestIdsFilePath).Where(l => !string.IsNullOrEmpty(l)).ToHashSet();
48+
_knownManifestIdsAndOrder = new Dictionary<string, int>();
49+
int lineNumber = 0;
50+
foreach (var manifestId in File.ReadAllLines(knownManifestIdsFilePath).Where(l => !string.IsNullOrEmpty(l)))
51+
{
52+
_knownManifestIdsAndOrder[manifestId] = lineNumber++;
53+
}
4854
}
4955

5056
string? userManifestsDir = userProfileDir is null ? null : Path.Combine(userProfileDir, "sdk-manifests", _sdkVersionBand.ToString());
@@ -126,9 +132,9 @@ public IEnumerable<string> GetManifestDirectories()
126132
}
127133
}
128134

129-
if (_knownManifestIds != null && _knownManifestIds.Any(id => !manifestIdsToDirectories.ContainsKey(id)))
135+
if (_knownManifestIdsAndOrder != null && _knownManifestIdsAndOrder.Keys.Any(id => !manifestIdsToDirectories.ContainsKey(id)))
130136
{
131-
var missingManifestIds = _knownManifestIds.Where(id => !manifestIdsToDirectories.ContainsKey(id));
137+
var missingManifestIds = _knownManifestIdsAndOrder.Keys.Where(id => !manifestIdsToDirectories.ContainsKey(id));
132138
foreach (var missingManifestId in missingManifestIds)
133139
{
134140
var manifestDir = FallbackForMissingManifest(missingManifestId);
@@ -139,7 +145,21 @@ public IEnumerable<string> GetManifestDirectories()
139145
}
140146
}
141147

142-
return manifestIdsToDirectories.Values;
148+
// Return manifests in a stable order. Manifests in the IncludedWorkloadManifests.txt file will be first, and in the same order they appear in that file.
149+
// Then the rest of the manifests (if any) will be returned in (ordinal case-insensitive) alphabetical order.
150+
return manifestIdsToDirectories
151+
.OrderBy(kvp =>
152+
{
153+
if (_knownManifestIdsAndOrder != null &&
154+
_knownManifestIdsAndOrder.TryGetValue(kvp.Key, out var order))
155+
{
156+
return order;
157+
}
158+
return int.MaxValue;
159+
})
160+
.ThenBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
161+
.Select(kvp => kvp.Value)
162+
.ToList();
143163
}
144164

145165
private string FallbackForMissingManifest(string manifestId)

src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,43 @@ var sdkDirectoryWorkloadManifestProvider
343343
.BeEquivalentTo("6.0.100-preview.4/iOS", "6.0.100/Android");
344344
}
345345

346+
[Fact]
347+
public void ItReturnsManifestsInOrderFromIncludedWorkloadManifestsFile()
348+
{
349+
var testDirectory = _testAssetsManager.CreateTestDirectory().Path;
350+
var fakeDotnetRootDirectory = Path.Combine(testDirectory, "dotnet");
351+
352+
// microsoft.net.workload.mono.toolchain.net6, microsoft.net.workload.mono.toolchain.net7, microsoft.net.workload.emscripten.net6, microsoft.net.workload.emscripten.net7
353+
354+
var currentSdkVersion = "7.0.100";
355+
var fallbackWorkloadBand = "7.0.100-rc.2";
356+
357+
CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "NotInIncudedWorkloadsFile");
358+
CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "Microsoft.Net.Workload.Mono.Toolchain.net6");
359+
CreateMockManifest(fakeDotnetRootDirectory, fallbackWorkloadBand, "Microsoft.Net.Workload.Mono.Toolchain.net7");
360+
CreateMockManifest(fakeDotnetRootDirectory, fallbackWorkloadBand, "Microsoft.Net.Workload.Emscripten.net6");
361+
CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "Microsoft.Net.Workload.Emscripten.net7");
362+
363+
var knownWorkloadsFilePath = Path.Combine(fakeDotnetRootDirectory, "sdk", currentSdkVersion, "IncludedWorkloadManifests.txt");
364+
Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!);
365+
File.WriteAllText(knownWorkloadsFilePath, @"
366+
Microsoft.Net.Workload.Mono.Toolchain.net6
367+
Microsoft.Net.Workload.Mono.Toolchain.net7
368+
Microsoft.Net.Workload.Emscripten.net6
369+
Microsoft.Net.Workload.Emscripten.net7"
370+
.Trim());
371+
372+
var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: fakeDotnetRootDirectory, sdkVersion: currentSdkVersion, userProfileDir: null);
373+
374+
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
375+
.Should()
376+
.Equal($"{currentSdkVersion}/Microsoft.Net.Workload.Mono.Toolchain.net6",
377+
$"{fallbackWorkloadBand}/Microsoft.Net.Workload.Mono.Toolchain.net7",
378+
$"{fallbackWorkloadBand}/Microsoft.Net.Workload.Emscripten.net6",
379+
$"{currentSdkVersion}/Microsoft.Net.Workload.Emscripten.net7",
380+
$"{currentSdkVersion}/NotInIncudedWorkloadsFile");
381+
}
382+
346383
private void CreateMockManifest(string rootDir, string version, string manifestId)
347384
{
348385
var manifestDirectory = Path.Combine(rootDir, "sdk-manifests", version);

0 commit comments

Comments
 (0)