diff --git a/src/Common/EnvironmentVariableNames.cs b/src/Common/EnvironmentVariableNames.cs index 86f5ac61a081..795f6d63db10 100644 --- a/src/Common/EnvironmentVariableNames.cs +++ b/src/Common/EnvironmentVariableNames.cs @@ -14,6 +14,7 @@ static class EnvironmentVariableNames public static readonly string ALLOW_TARGETING_PACK_CACHING = "DOTNETSDK_ALLOW_TARGETING_PACK_CACHING"; public static readonly string WORKLOAD_PACK_ROOTS = "DOTNETSDK_WORKLOAD_PACK_ROOTS"; public static readonly string WORKLOAD_MANIFEST_ROOTS = "DOTNETSDK_WORKLOAD_MANIFEST_ROOTS"; + public static readonly string WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS = "DOTNETSDK_WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS"; public static readonly string WORKLOAD_UPDATE_NOTIFY_DISABLE = "DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE"; public static readonly string WORKLOAD_UPDATE_NOTIFY_INTERVAL_HOURS = "DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_INTERVAL_HOURS"; public static readonly string WORKLOAD_DISABLE_PACK_GROUPS = "DOTNET_CLI_WORKLOAD_DISABLE_PACK_GROUPS"; diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs index 75ce81b42cd6..7192615b7c15 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs @@ -215,12 +215,3 @@ public ResolutionResult Resolve(string sdkReferenceName, string dotnetRootPath, } } } - - -// Add attribute to support init-only properties on .NET Framework -#if !NET -namespace System.Runtime.CompilerServices -{ - public class IsExternalInit { } -} -#endif diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestSpecifier.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestSpecifier.cs new file mode 100644 index 000000000000..08f3b9d78ecd --- /dev/null +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/ManifestSpecifier.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.NET.Sdk.WorkloadManifestReader +{ + public record class ManifestSpecifier(ManifestId Id, ManifestVersion Version, SdkFeatureBand FeatureBand) + { + public override string ToString() => $"{Id}: {Version}/{FeatureBand}"; + } +} + + + +// Add attribute to support init-only properties on .NET Framework +#if !NET +namespace System.Runtime.CompilerServices +{ + public class IsExternalInit { } +} +#endif diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs index 801f63f8f90d..220057e3db0e 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs @@ -6,8 +6,10 @@ using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; +using Microsoft.Deployment.DotNet.Releases; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Workloads.Workload; +using Microsoft.NET.Sdk.Localization; namespace Microsoft.NET.Sdk.WorkloadManifestReader { @@ -15,18 +17,20 @@ public class SdkDirectoryWorkloadManifestProvider : IWorkloadManifestProvider { private readonly string _sdkRootPath; private readonly SdkFeatureBand _sdkVersionBand; - private readonly string [] _manifestDirectories; + private readonly string[] _manifestRoots; private static HashSet _outdatedManifestIds = new HashSet(StringComparer.OrdinalIgnoreCase) { "microsoft.net.workload.android", "microsoft.net.workload.blazorwebassembly", "microsoft.net.workload.ios", "microsoft.net.workload.maccatalyst", "microsoft.net.workload.macos", "microsoft.net.workload.tvos", "microsoft.net.workload.mono.toolchain" }; private readonly Dictionary? _knownManifestIdsAndOrder; - public SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, string? userProfileDir) - : this(sdkRootPath, sdkVersion, Environment.GetEnvironmentVariable, userProfileDir) + private readonly Dictionary _requestedManifestVersions; + + public SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, string? userProfileDir, IEnumerable? requestedManifestVersions = null) + : this(sdkRootPath, sdkVersion, Environment.GetEnvironmentVariable, userProfileDir, requestedManifestVersions) { } - internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, Func getEnvironmentVariable, string? userProfileDir) + internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, Func getEnvironmentVariable, string? userProfileDir, IEnumerable? requestedManifestVersions = null) { if (string.IsNullOrWhiteSpace(sdkVersion)) { @@ -58,15 +62,18 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers } } - string? userManifestsDir = userProfileDir is null ? null : Path.Combine(userProfileDir, "sdk-manifests", _sdkVersionBand.ToString()); - string dotnetManifestDir = Path.Combine(_sdkRootPath, "sdk-manifests", _sdkVersionBand.ToString()); - if (userManifestsDir != null && WorkloadFileBasedInstall.IsUserLocal(_sdkRootPath, _sdkVersionBand.ToString()) && Directory.Exists(userManifestsDir)) - { - _manifestDirectories = new[] { userManifestsDir, dotnetManifestDir }; - } - else + if (getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_IGNORE_DEFAULT_ROOTS) == null) { - _manifestDirectories = new[] { dotnetManifestDir }; + string? userManifestsRoot = userProfileDir is null ? null : Path.Combine(userProfileDir, "sdk-manifests"); + string dotnetManifestRoot = Path.Combine(_sdkRootPath, "sdk-manifests"); + if (userManifestsRoot != null && WorkloadFileBasedInstall.IsUserLocal(_sdkRootPath, _sdkVersionBand.ToString()) && Directory.Exists(userManifestsRoot)) + { + _manifestRoots = new[] { userManifestsRoot, dotnetManifestRoot }; + } + else + { + _manifestRoots = new[] { dotnetManifestRoot }; + } } var manifestDirectoryEnvironmentVariable = getEnvironmentVariable(EnvironmentVariableNames.WORKLOAD_MANIFEST_ROOTS); @@ -74,9 +81,21 @@ internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVers { // Append the SDK version band to each manifest root specified via the environment variable. This allows the same // environment variable settings to be shared by multiple SDKs. - _manifestDirectories = manifestDirectoryEnvironmentVariable.Split(Path.PathSeparator) - .Select(p => Path.Combine(p, _sdkVersionBand.ToString())) - .Concat(_manifestDirectories).ToArray(); + _manifestRoots = manifestDirectoryEnvironmentVariable.Split(Path.PathSeparator) + .Concat(_manifestRoots ?? Array.Empty()).ToArray(); + + } + + _manifestRoots = _manifestRoots ?? Array.Empty(); + + _requestedManifestVersions = new Dictionary(StringComparer.OrdinalIgnoreCase); + + if (requestedManifestVersions != null) + { + foreach (var manifestVersion in requestedManifestVersions) + { + _requestedManifestVersions[manifestVersion.Id.ToString()] = manifestVersion; + } } } @@ -98,18 +117,27 @@ public IEnumerable GetManifests() public IEnumerable GetManifestDirectories() { + // Scan manifest directories var manifestIdsToDirectories = new Dictionary(); - if (_manifestDirectories.Length == 1) + + void ProbeDirectory(string manifestDirectory) + { + (string? id, string? finalManifestDirectory) = ResolveManifestDirectory(manifestDirectory); + if (id != null && finalManifestDirectory != null) + { + manifestIdsToDirectories.Add(id, finalManifestDirectory); + } + } + + if (_manifestRoots.Length == 1) { // Optimization for common case where test hook to add additional directories isn't being used - if (Directory.Exists(_manifestDirectories[0])) + var manifestVersionBandDirectory = Path.Combine(_manifestRoots[0], _sdkVersionBand.ToString()); + if (Directory.Exists(manifestVersionBandDirectory)) { - foreach (var workloadManifestDirectory in Directory.EnumerateDirectories(_manifestDirectories[0])) + foreach (var workloadManifestDirectory in Directory.EnumerateDirectories(manifestVersionBandDirectory)) { - if (!IsManifestIdOutdated(workloadManifestDirectory)) - { - manifestIdsToDirectories.Add(Path.GetFileName(workloadManifestDirectory), workloadManifestDirectory); - } + ProbeDirectory(workloadManifestDirectory); } } } @@ -117,11 +145,12 @@ public IEnumerable GetManifestDirectories() { // If the same folder name is in multiple of the workload manifest directories, take the first one Dictionary directoriesWithManifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var manifestDirectory in _manifestDirectories.Reverse()) + foreach (var manifestRoot in _manifestRoots.Reverse()) { - if (Directory.Exists(manifestDirectory)) + var manifestVersionBandDirectory = Path.Combine(manifestRoot, _sdkVersionBand.ToString()); + if (Directory.Exists(manifestVersionBandDirectory)) { - foreach (var workloadManifestDirectory in Directory.EnumerateDirectories(manifestDirectory)) + foreach (var workloadManifestDirectory in Directory.EnumerateDirectories(manifestVersionBandDirectory)) { directoriesWithManifests[Path.GetFileName(workloadManifestDirectory)] = workloadManifestDirectory; } @@ -130,13 +159,16 @@ public IEnumerable GetManifestDirectories() foreach (var workloadManifestDirectory in directoriesWithManifests.Values) { - if (!IsManifestIdOutdated(workloadManifestDirectory)) - { - manifestIdsToDirectories.Add(Path.GetFileName(workloadManifestDirectory), workloadManifestDirectory); - } + ProbeDirectory(workloadManifestDirectory); } } + // Load manifests that were explicitly specified + foreach (var kvp in _requestedManifestVersions) + { + manifestIdsToDirectories.Add(kvp.Key, GetManifestDirectoryFromSpecifier(kvp.Value)); + } + if (_knownManifestIdsAndOrder != null && _knownManifestIdsAndOrder.Keys.Any(id => !manifestIdsToDirectories.ContainsKey(id))) { var missingManifestIds = _knownManifestIdsAndOrder.Keys.Where(id => !manifestIdsToDirectories.ContainsKey(id)); @@ -167,9 +199,46 @@ public IEnumerable GetManifestDirectories() .ToList(); } + /// + /// Given a folder that may directly include a WorkloadManifest.json file, or may have the workload manifests in version subfolders, choose the directory + /// with the latest workload manifest. + /// + private (string? id, string? manifestDirectory) ResolveManifestDirectory(string manifestDirectory) + { + string manifestId = Path.GetFileName(manifestDirectory); + if (_outdatedManifestIds.Contains(manifestId)) + { + return (null, null); + } + + var manifestVersionDirectories = Directory.GetDirectories(manifestDirectory) + .Where(dir => File.Exists(Path.Combine(dir, "WorkloadManifest.json"))) + .Select(dir => + { + ReleaseVersion? releaseVersion = null; + ReleaseVersion.TryParse(Path.GetFileName(dir), out releaseVersion); + return (directory: dir, version: releaseVersion); + }) + .Where(t => t.version != null) + .OrderByDescending(t => t.version) + .ToList(); + + // Assume that if there are any versioned subfolders, they are higher manifest versions than a workload manifest directly in the specified folder, if it exists + if (manifestVersionDirectories.Any()) + { + return (manifestId, manifestVersionDirectories.First().directory); + } + else if (File.Exists(Path.Combine(manifestDirectory, "WorkloadManifest.json"))) + { + return (manifestId, manifestDirectory); + } + return (null, null); + } + private string FallbackForMissingManifest(string manifestId) { - var sdkManifestPath = Path.Combine(_sdkRootPath, "sdk-manifests"); + // Only use the last manifest root (usually the dotnet folder itself) for fallback + var sdkManifestPath = _manifestRoots.Last(); if (!Directory.Exists(sdkManifestPath)) { return string.Empty; @@ -179,11 +248,21 @@ private string FallbackForMissingManifest(string manifestId) .Select(dir => Path.GetFileName(dir)) .Select(featureBand => new SdkFeatureBand(featureBand)) .Where(featureBand => featureBand < _sdkVersionBand || _sdkVersionBand.ToStringWithoutPrerelease().Equals(featureBand.ToString(), StringComparison.Ordinal)); - var matchingManifestFatureBands = candidateFeatureBands - .Where(featureBand => Directory.Exists(Path.Combine(sdkManifestPath, featureBand.ToString(), manifestId))); - if (matchingManifestFatureBands.Any()) + + var matchingManifestFatureBandsAndResolvedManifestDirectories = candidateFeatureBands + // Calculate path to \ + .Select(featureBand => (featureBand, manifestDirectory: Path.Combine(sdkManifestPath, featureBand.ToString(), manifestId))) + // Filter out directories that don't exist + .Where(t => Directory.Exists(t.manifestDirectory)) + // Inside directory, resolve where to find WorkloadManifest.json + .Select(t => (t.featureBand, res: ResolveManifestDirectory(t.manifestDirectory))) + // Filter out directories where no WorkloadManifest.json was resolved + .Where(t => t.res.id != null && t.res.manifestDirectory != null) + .ToList(); + + if (matchingManifestFatureBandsAndResolvedManifestDirectories.Any()) { - return Path.Combine(sdkManifestPath, matchingManifestFatureBands.Max()!.ToString(), manifestId); + return matchingManifestFatureBandsAndResolvedManifestDirectories.OrderByDescending(t => t.featureBand).First().res.manifestDirectory!; } else { @@ -192,6 +271,21 @@ private string FallbackForMissingManifest(string manifestId) } } + private string GetManifestDirectoryFromSpecifier(ManifestSpecifier manifestSpecifier) + { + foreach (var manifestDirectory in _manifestRoots) + { + var specifiedManifestDirectory = Path.Combine(manifestDirectory, manifestSpecifier.FeatureBand.ToString(), manifestSpecifier.Id.ToString(), + manifestSpecifier.Version.ToString()); + if (File.Exists(Path.Combine(specifiedManifestDirectory, "WorkloadManifest.json"))) + { + return specifiedManifestDirectory; + } + } + + throw new FileNotFoundException(string.Format(Strings.SpecifiedManifestNotFound, manifestSpecifier.ToString())); + } + private bool IsManifestIdOutdated(string workloadManifestDir) { var manifestId = Path.GetFileName(workloadManifestDir); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx index 3d9781526e21..7cc12b214c97 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx @@ -189,4 +189,7 @@ Invalid version: {0} + + Specified workload manifest was not found: {0} + diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf index 00160d2f9f71..672b80088fff 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf @@ -97,6 +97,11 @@ Přesměrování úlohy {0} má jiné klíče než redirect-to. + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Neočekávaný token {0} u posunu {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf index 57f11e933d14..e28faffebedc 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf @@ -97,6 +97,11 @@ Die Umleitungsworkload „{0}“ hat andere Schlüssel als „redirect-to“. + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Unerwartetes Token "{0}" bei Offset {1}. diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf index e52f638e7600..af60d628ca18 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf @@ -97,6 +97,11 @@ La carga de trabajo de redireccionamiento '{0}' tiene claves distintas que las de 'redirect-to' + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Token "{0}" inesperado en el desplazamiento {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf index 6a07713b64c8..371246291c75 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf @@ -97,6 +97,11 @@ La charge de travail de redirection « {0} » a des clés autres que « redirection vers ». + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Jeton '{0}' inattendu à l'offset {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf index b63ef47d89fb..62bfe6d1764a 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf @@ -97,6 +97,11 @@ Il carico di lavoro '{0}' di reindirizzamento ha chiavi diverse da ' Redirect-to ' + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Token '{0}' imprevisto alla posizione di offset {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf index 08338481dd9f..c86a3c43ef21 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf @@ -97,6 +97,11 @@ リダイレクト ワークロード '{0}' に 'redirect-to' 以外のキーがあります + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} オフセット {1} に予期しないトークン '{0}' があります diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf index 262ac3cd32de..9af606a9cc8f 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf @@ -97,6 +97,11 @@ 리디렉션 워크로드 '{0}'에 'redirect-to' 이외의 다른 키가 있습니다 + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} 오프셋 {1}에 예기치 않은 토큰 '{0}'이(가) 있습니다. diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf index bc2fe0556155..954ca073e15c 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf @@ -97,6 +97,11 @@ Obciążenie przekierowania „{0}” ma klucze inne niż „redirect-to” + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Nieoczekiwany token „{0}” pod przesunięciem {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf index adaf5d4e61ba..8c2b817fe5e3 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pt-BR.xlf @@ -97,6 +97,11 @@ A carga de trabalho de redirecionamento '{0}' tem chaves diferentes além de 'redirecionar-para' + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Token inesperado '{0}' no deslocamento {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf index d698d78d2637..29122a0ea4ef 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf @@ -97,6 +97,11 @@ Перенаправление рабочей нагрузки "{0}" содержит ключи, отличные от "redirect-to" + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} Непредвиденный токен "{0}" в смещении {1} diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf index e4b94477eb7b..8d034d4d0ee9 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf @@ -97,6 +97,11 @@ '{0}' yeniden yönlendirme iş yükünde 'redirect-to' dışında anahtarlar var + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} {1} uzaklığında beklenmeyen '{0}' belirteci diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf index 8cb5a6f17f4d..ddcc21a185d3 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hans.xlf @@ -97,6 +97,11 @@ 重定向工作负荷“{0}”具有“重定向到”以外的键 + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} 偏移为 {1} 时意外出现的标记“{0}” diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf index 1eda9a04a44c..6df153395f25 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.zh-Hant.xlf @@ -97,6 +97,11 @@ 重新導向工作負載 '{0}' 具有 'redirect-to' 以外的其他金鑰 + + Specified workload manifest was not found: {0} + Specified workload manifest was not found: {0} + + Unexpected token '{0}' at offset {1} 位移 {1} 有未預期的權杖 '{0}' diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs index 2f1845cc0edd..9fb3cb9f1534 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs @@ -22,20 +22,22 @@ namespace ManifestReaderTests public class SdkDirectoryWorkloadManifestProviderTests : SdkTest { private string? _testDirectory; - private string? _manifestDirectory; + private string? _manifestRoot; + private string? _manifestVersionBandDirectory; private string? _fakeDotnetRootDirectory; public SdkDirectoryWorkloadManifestProviderTests(ITestOutputHelper logger) : base(logger) { } - [MemberNotNull("_testDirectory", "_manifestDirectory", "_fakeDotnetRootDirectory")] - void Initialize([CallerMemberName] string? testName = null, string? identifier = null) + [MemberNotNull("_testDirectory", "_manifestRoot", "_manifestVersionBandDirectory", "_fakeDotnetRootDirectory")] + void Initialize(string featureBand = "5.0.100", [CallerMemberName] string? testName = null, string? identifier = null) { _testDirectory = _testAssetsManager.CreateTestDirectory(testName, identifier).Path; _fakeDotnetRootDirectory = Path.Combine(_testDirectory, "dotnet"); - _manifestDirectory = Path.Combine(_fakeDotnetRootDirectory, "sdk-manifests", "5.0.100"); - Directory.CreateDirectory(_manifestDirectory); + _manifestRoot = Path.Combine(_fakeDotnetRootDirectory, "sdk-manifests"); + _manifestVersionBandDirectory = Path.Combine(_manifestRoot, featureBand); + Directory.CreateDirectory(_manifestVersionBandDirectory); } [Fact] @@ -45,10 +47,10 @@ public void ItShouldReturnListOfManifestFiles() string androidManifestFileContent = "Android"; string iosManifestFileContent = "iOS"; - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Android", "WorkloadManifest.json"), androidManifestFileContent); - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "iOS")); - File.WriteAllText(Path.Combine(_manifestDirectory, "iOS", "WorkloadManifest.json"), iosManifestFileContent); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Android", "WorkloadManifest.json"), androidManifestFileContent); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "iOS")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "iOS", "WorkloadManifest.json"), iosManifestFileContent); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); @@ -64,8 +66,8 @@ public void GivenSDKVersionItShouldReturnListOfManifestFilesForThisVersionBand() Initialize(); string androidManifestFileContent = "Android"; - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Android", "WorkloadManifest.json"), androidManifestFileContent); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Android", "WorkloadManifest.json"), androidManifestFileContent); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); @@ -86,21 +88,83 @@ var sdkDirectoryWorkloadManifestProvider } [Fact] - public void GivenNoManifestJsonFileInDirectoryItShouldThrow() + public void GivenNoManifestJsonFileInDirectoryItShouldIgnoreIt() { Initialize(); - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); - Action a = () => sdkDirectoryWorkloadManifestProvider.GetManifests().Select(m => { - using (m.OpenManifestStream()) { } - return true; - }).ToList(); + sdkDirectoryWorkloadManifestProvider.GetManifests() + .Should() + .BeEmpty(); + } + + [Fact] + public void ItReturnsLatestManifestVersion() + { + Initialize(); + + CreateMockManifest(_manifestRoot, "5.0.100-preview.5", "ios", "11.0.3", true); + + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "11.0.1", true); + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "11.0.2", true); + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "11.0.2-rc.1", true); + + var sdkDirectoryWorkloadManifestProvider + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); + + GetManifestContents(sdkDirectoryWorkloadManifestProvider) + .Should() + .BeEquivalentTo("ios: 11.0.2/5.0.100"); + } + + [Fact] + public void ItPrefersManifestsInSubfolders() + { + Initialize(); + + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "11.0.1", true); + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "11.0.2", true); + + // Even though this manifest has a higher version, it is not in a versioned subfolder so the other manifests will be preferred + // In real use, we would expect the manifest outside the versioned subfolders to be a lower version + CreateMockManifest(_manifestRoot, "5.0.100", "ios", "12.0.1", false); + + var sdkDirectoryWorkloadManifestProvider + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); + + GetManifestContents(sdkDirectoryWorkloadManifestProvider) + .Should() + .BeEquivalentTo("ios: 11.0.2/5.0.100"); + } + + [Fact] + public void ItFallsBackToLatestManifestVersion() + { + Initialize("8.0.200"); + + var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", "8.0.100", "IncludedWorkloadManifests.txt"); + Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!); + File.WriteAllText(knownWorkloadsFilePath, "android\nios"); - a.Should().Throw(); + CreateMockManifest(_manifestRoot, "8.0.100", "android", "33.0.0", true); + CreateMockManifest(_manifestRoot, "8.0.100", "android", "33.0.1", true); + + CreateMockManifest(_manifestRoot, "7.0.400", "android", "32.0.1", true); + + CreateMockManifest(_manifestRoot, "7.0.400", "ios", "17.0.1", true); + CreateMockManifest(_manifestRoot, "7.0.400", "ios", "18.0.1", true); + + var sdkDirectoryWorkloadManifestProvider + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.100", userProfileDir: null); + + GetManifestContents(sdkDirectoryWorkloadManifestProvider) + .Should() + .BeEquivalentTo("android: 33.0.1/8.0.100", + "ios: 18.0.1/7.0.400"); } [Fact] @@ -121,8 +185,8 @@ public void ItShouldReturnManifestsFromTestHook() File.WriteAllText(Path.Combine(additionalManifestDirectory, sdkVersion, "Android", "WorkloadManifest.json"), "AndroidContent"); // Manifest in default directory - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "iOS")); - File.WriteAllText(Path.Combine(_manifestDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "iOS")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); var sdkDirectoryWorkloadManifestProvider @@ -151,8 +215,8 @@ public void ManifestFromTestHookShouldOverrideDefault() File.WriteAllText(Path.Combine(additionalManifestDirectory, sdkVersion, "Android", "WorkloadManifest.json"), "OverridingAndroidContent"); // Manifest in default directory - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Android", "WorkloadManifest.json"), "OverriddenAndroidContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Android", "WorkloadManifest.json"), "OverriddenAndroidContent"); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: sdkVersion, environmentMock.GetEnvironmentVariable, userProfileDir: null); @@ -180,11 +244,11 @@ public void ItSupportsMultipleTestHookFolders() // Manifests in default directory - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "iOS")); - File.WriteAllText(Path.Combine(_manifestDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "iOS")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Android", "WorkloadManifest.json"), "DefaultAndroidContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Android", "WorkloadManifest.json"), "DefaultAndroidContent"); // Manifests in first additional directory Directory.CreateDirectory(Path.Combine(additionalManifestDirectory1, sdkVersion, "Android")); @@ -217,8 +281,8 @@ public void IfTestHookFolderDoesNotExistItShouldBeIgnored() environmentMock.Add(EnvironmentVariableNames.WORKLOAD_MANIFEST_ROOTS, additionalManifestDirectory); // Manifest in default directory - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Android", "WorkloadManifest.json"), "AndroidContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Android", "WorkloadManifest.json"), "AndroidContent"); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", environmentMock.GetEnvironmentVariable, userProfileDir: null); @@ -234,10 +298,10 @@ public void ItShouldIgnoreOutdatedManifestIds() { Initialize(); - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "iOS")); - File.WriteAllText(Path.Combine(_manifestDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); - Directory.CreateDirectory(Path.Combine(_manifestDirectory, "Microsoft.NET.Workload.Android")); - File.WriteAllText(Path.Combine(_manifestDirectory, "Microsoft.NET.Workload.Android", "WorkloadManifest.json"), "iOSContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "iOS")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "iOS", "WorkloadManifest.json"), "iOSContent"); + Directory.CreateDirectory(Path.Combine(_manifestVersionBandDirectory, "Microsoft.NET.Workload.Android")); + File.WriteAllText(Path.Combine(_manifestVersionBandDirectory, "Microsoft.NET.Workload.Android", "WorkloadManifest.json"), "iOSContent"); var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.100", userProfileDir: null); @@ -250,117 +314,113 @@ var sdkDirectoryWorkloadManifestProvider [Fact] public void ItShouldFallbackWhenFeatureBandHasNoManifests() { - var testDirectory = _testAssetsManager.CreateTestDirectory().Path; - var fakeDotnetRootDirectory = Path.Combine(testDirectory, "dotnet"); + Initialize("6.0.100"); // Write 4.0.100 manifests-> android only - CreateMockManifest(fakeDotnetRootDirectory, "4.0.100", "Android"); + CreateMockManifest(_manifestRoot, "4.0.100", "Android", "1"); // Write 5.0.100 manifests-> ios and android - CreateMockManifest(fakeDotnetRootDirectory, "5.0.100", "Android"); - CreateMockManifest(fakeDotnetRootDirectory, "5.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "5.0.100", "Android", "2"); + CreateMockManifest(_manifestRoot, "5.0.100", "iOS", "3"); // Write 6.0.100 manifests-> ios only - CreateMockManifest(fakeDotnetRootDirectory, "6.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "6.0.100", "iOS", "4"); // Write 7.0.100 manifests-> ios and android - CreateMockManifest(fakeDotnetRootDirectory, "7.0.100", "Android"); - CreateMockManifest(fakeDotnetRootDirectory, "7.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "7.0.100", "Android", "5"); + CreateMockManifest(_manifestRoot, "7.0.100", "iOS", "6"); - var knownWorkloadsFilePath = Path.Combine(fakeDotnetRootDirectory, "sdk", "6.0.100", "KnownWorkloadManifests.txt"); + var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", "6.0.100", "IncludedWorkloadManifests.txt"); Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!); File.WriteAllText(knownWorkloadsFilePath, "Android\niOS"); var sdkDirectoryWorkloadManifestProvider - = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: fakeDotnetRootDirectory, sdkVersion: "6.0.100", userProfileDir: null); + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "6.0.100", userProfileDir: null); GetManifestContents(sdkDirectoryWorkloadManifestProvider) .Should() - .BeEquivalentTo("6.0.100/iOS", "5.0.100/Android"); + .BeEquivalentTo("iOS: 4/6.0.100", "Android: 2/5.0.100"); } [Fact] public void ItShouldFallbackWhenPreviewFeatureBandHasNoManifests() { - var testDirectory = _testAssetsManager.CreateTestDirectory().Path; - var fakeDotnetRootDirectory = Path.Combine(testDirectory, "dotnet"); + Initialize("6.0.100"); // Write 4.0.100 manifests-> android only - CreateMockManifest(fakeDotnetRootDirectory, "4.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "4.0.100", "iOS", "1"); // Write 5.0.100 manifests-> android - CreateMockManifest(fakeDotnetRootDirectory, "5.0.100", "Android"); + CreateMockManifest(_manifestRoot, "5.0.100", "Android", "2"); // Write 6.0.100-preview.2 manifests-> ios only - CreateMockManifest(fakeDotnetRootDirectory, "6.0.100-preview.2", "iOS"); + CreateMockManifest(_manifestRoot, "6.0.100-preview.2", "iOS", "3"); // Write 7.0.100 manifests-> ios and android - CreateMockManifest(fakeDotnetRootDirectory, "7.0.100", "Android"); - CreateMockManifest(fakeDotnetRootDirectory, "7.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "7.0.100", "Android", "4"); + CreateMockManifest(_manifestRoot, "7.0.100", "iOS", " 5"); var prev4Version = "6.0.100-preview.4.12345"; - var knownWorkloadsFilePath = Path.Combine(fakeDotnetRootDirectory, "sdk", prev4Version, "KnownWorkloadManifests.txt"); + var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", prev4Version, "IncludedWorkloadManifests.txt"); Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!); File.WriteAllText(knownWorkloadsFilePath, "Android\niOS"); var sdkDirectoryWorkloadManifestProvider - = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: fakeDotnetRootDirectory, sdkVersion: prev4Version, userProfileDir: null); + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: prev4Version, userProfileDir: null); GetManifestContents(sdkDirectoryWorkloadManifestProvider) .Should() - .BeEquivalentTo("6.0.100-preview.2/iOS", "5.0.100/Android"); + .BeEquivalentTo("iOS: 3/6.0.100-preview.2", "Android: 2/5.0.100"); } [Fact] public void ItShouldRollForwardToNonPrereleaseWhenPreviewFeatureBandHasNoManifests() { - var testDirectory = _testAssetsManager.CreateTestDirectory().Path; - var fakeDotnetRootDirectory = Path.Combine(testDirectory, "dotnet"); + Initialize("6.0.100"); // Write 4.0.100 manifests-> android only - CreateMockManifest(fakeDotnetRootDirectory, "4.0.100", "Android"); + CreateMockManifest(_manifestRoot, "4.0.100", "Android", "1"); // Write 5.0.100 manifests-> ios and android - CreateMockManifest(fakeDotnetRootDirectory, "5.0.100", "Android"); - CreateMockManifest(fakeDotnetRootDirectory, "5.0.100", "iOS"); + CreateMockManifest(_manifestRoot, "5.0.100", "Android", "2"); + CreateMockManifest(_manifestRoot, "5.0.100", "iOS", "3"); // Write 6.0.100-preview.4 manifests-> ios only - CreateMockManifest(fakeDotnetRootDirectory, "6.0.100-preview.4", "iOS"); + CreateMockManifest(_manifestRoot, "6.0.100-preview.4", "iOS", "4"); // Write 6.0.100 manifests-> android - CreateMockManifest(fakeDotnetRootDirectory, "6.0.100", "Android"); + CreateMockManifest(_manifestRoot, "6.0.100", "Android", "5"); var prev4Version = "6.0.100-preview.4.12345"; - var knownWorkloadsFilePath = Path.Combine(fakeDotnetRootDirectory, "sdk", prev4Version, "KnownWorkloadManifests.txt"); + var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", prev4Version, "IncludedWorkloadManifests.txt"); Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!); File.WriteAllText(knownWorkloadsFilePath, "Android\niOS"); var sdkDirectoryWorkloadManifestProvider - = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: fakeDotnetRootDirectory, sdkVersion: prev4Version, userProfileDir: null); + = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: prev4Version, userProfileDir: null); GetManifestContents(sdkDirectoryWorkloadManifestProvider) .Should() - .BeEquivalentTo("6.0.100-preview.4/iOS", "6.0.100/Android"); + .BeEquivalentTo("iOS: 4/6.0.100-preview.4", "Android: 5/6.0.100"); } [Fact] public void ItReturnsManifestsInOrderFromKnownWorkloadManifestsFile() { - var testDirectory = _testAssetsManager.CreateTestDirectory().Path; - var fakeDotnetRootDirectory = Path.Combine(testDirectory, "dotnet"); - // microsoft.net.workload.mono.toolchain.net6, microsoft.net.workload.mono.toolchain.net7, microsoft.net.workload.emscripten.net6, microsoft.net.workload.emscripten.net7 var currentSdkVersion = "7.0.100"; var fallbackWorkloadBand = "7.0.100-rc.2"; - CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "NotInIncudedWorkloadsFile"); - CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "Microsoft.Net.Workload.Mono.Toolchain.net6"); - CreateMockManifest(fakeDotnetRootDirectory, fallbackWorkloadBand, "Microsoft.Net.Workload.Mono.Toolchain.net7"); - CreateMockManifest(fakeDotnetRootDirectory, fallbackWorkloadBand, "Microsoft.Net.Workload.Emscripten.net6"); - CreateMockManifest(fakeDotnetRootDirectory, currentSdkVersion, "Microsoft.Net.Workload.Emscripten.net7"); + Initialize(currentSdkVersion); - var knownWorkloadsFilePath = Path.Combine(fakeDotnetRootDirectory, "sdk", currentSdkVersion, "KnownWorkloadManifests.txt"); + CreateMockManifest(_manifestRoot, currentSdkVersion, "NotInIncudedWorkloadsFile", "1"); + CreateMockManifest(_manifestRoot, currentSdkVersion, "Microsoft.Net.Workload.Mono.Toolchain.net6", "2"); + CreateMockManifest(_manifestRoot, fallbackWorkloadBand, "Microsoft.Net.Workload.Mono.Toolchain.net7", "3"); + CreateMockManifest(_manifestRoot, fallbackWorkloadBand, "Microsoft.Net.Workload.Emscripten.net6", "4"); + CreateMockManifest(_manifestRoot, currentSdkVersion, "Microsoft.Net.Workload.Emscripten.net7", "5"); + + var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", currentSdkVersion, "IncludedWorkloadManifests.txt"); Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!); File.WriteAllText(knownWorkloadsFilePath, @" Microsoft.Net.Workload.Mono.Toolchain.net6 @@ -369,29 +429,31 @@ public void ItReturnsManifestsInOrderFromKnownWorkloadManifestsFile() Microsoft.Net.Workload.Emscripten.net7" .Trim()); - var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: fakeDotnetRootDirectory, sdkVersion: currentSdkVersion, userProfileDir: null); + var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: currentSdkVersion, userProfileDir: null); GetManifestContents(sdkDirectoryWorkloadManifestProvider) .Should() - .Equal($"{currentSdkVersion}/Microsoft.Net.Workload.Mono.Toolchain.net6", - $"{fallbackWorkloadBand}/Microsoft.Net.Workload.Mono.Toolchain.net7", - $"{fallbackWorkloadBand}/Microsoft.Net.Workload.Emscripten.net6", - $"{currentSdkVersion}/Microsoft.Net.Workload.Emscripten.net7", - $"{currentSdkVersion}/NotInIncudedWorkloadsFile"); + .Equal($"Microsoft.Net.Workload.Mono.Toolchain.net6: 2/{currentSdkVersion}", + $"Microsoft.Net.Workload.Mono.Toolchain.net7: 3/{fallbackWorkloadBand}", + $"Microsoft.Net.Workload.Emscripten.net6: 4/{fallbackWorkloadBand}", + $"Microsoft.Net.Workload.Emscripten.net7: 5/{currentSdkVersion}", + $"NotInIncudedWorkloadsFile: 1/{currentSdkVersion}"); } - private void CreateMockManifest(string rootDir, string version, string manifestId) + private void CreateMockManifest(string manifestRoot, string featureBand, string manifestId, string manifestVersion, bool useVersionFolder = false) { - var manifestDirectory = Path.Combine(rootDir, "sdk-manifests", version); - if (!Directory.Exists(manifestDirectory)) + var manifestDirectory = Path.Combine(manifestRoot, featureBand, manifestId); + if (useVersionFolder) { - Directory.CreateDirectory(manifestDirectory); + manifestDirectory = Path.Combine(manifestDirectory, manifestVersion); } - if (!Directory.Exists(Path.Combine(manifestDirectory, manifestId))) + + if (!Directory.Exists(manifestDirectory)) { - Directory.CreateDirectory(Path.Combine(manifestDirectory, manifestId)); + Directory.CreateDirectory(manifestDirectory); } - File.WriteAllText(Path.Combine(manifestDirectory, manifestId, "WorkloadManifest.json"), $"{version}/{manifestId}"); + + File.WriteAllText(Path.Combine(manifestDirectory, "WorkloadManifest.json"), $"{manifestId}: {manifestVersion}/{featureBand}"); } [Fact]