From f9d957fc996fcc57d08da1b09e3b4091645c0c99 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 3 Jun 2021 11:14:52 -0400 Subject: [PATCH 01/26] Eliminate redundant existence checks in workload resolver --- .../WorkloadResolver.cs | 89 +++++++++---------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 62361bc3ff0a..2823ca34058b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -140,18 +140,20 @@ public void RefreshWorkloadManifests() /// public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) { - foreach (var pack in _packs) + foreach (var pack in _packs.Values) { - if (pack.Value.Kind != kind) + if (pack.Kind != kind) { continue; } - var aliasedPath = ResolvePackPath(pack.Value); - var resolvedPackageId = pack.Value.IsAlias ? pack.Value.TryGetAliasForRuntimeIdentifiers(_currentRuntimeIdentifiers)?.ToString() : pack.Value.Id.ToString(); - if (aliasedPath != null && resolvedPackageId != null && PackExists(aliasedPath, pack.Value.Kind)) + if (ResolveId(pack) is WorkloadPackId resolvedPackageId) { - yield return CreatePackInfo(pack.Value, aliasedPath, resolvedPackageId); + var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out bool isInstalled); + if (isInstalled) + { + yield return CreatePackInfo(pack, aliasedPath, resolvedPackageId); + } } } } @@ -162,58 +164,54 @@ internal void ReplaceFilesystemChecksForTest(Func fileExists, Func _directoryExistOverride = directoryExists; } - private PackInfo CreatePackInfo(WorkloadPack pack, string aliasedPath, string resolvedPackageId) => new PackInfo( + private PackInfo CreatePackInfo(WorkloadPack pack, string aliasedPath, WorkloadPackId resolvedPackageId) => new PackInfo( pack.Id.ToString(), pack.Version, pack.Kind, aliasedPath, - resolvedPackageId + resolvedPackageId.ToString() ); - private bool PackExists (string packPath, WorkloadPackKind packKind) + /// + /// Resolve the package ID for the host platform. + /// + /// The workload pack + /// The path to the pack, or null if the pack is not available on the host platform. + private WorkloadPackId? ResolveId(WorkloadPack pack) { - switch (packKind) + if (!pack.IsAlias) { - case WorkloadPackKind.Framework: - case WorkloadPackKind.Sdk: - case WorkloadPackKind.Tool: - //can we do a more robust check than directory.exists? - return _directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath); - case WorkloadPackKind.Library: - case WorkloadPackKind.Template: - return _fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath); - default: - throw new ArgumentException($"The package kind '{packKind}' is not known", nameof(packKind)); + return pack.Id; + } + + if (pack.TryGetAliasForRuntimeIdentifiers(_currentRuntimeIdentifiers) is WorkloadPackId aliasedId) + { + return aliasedId; } - } + return null; + } /// /// Resolve the pack path for the host platform. /// /// The workload pack + /// Whether the pack is installed /// The path to the pack, or null if the pack is not available on the host platform. - private string? ResolvePackPath(WorkloadPack pack) + private string? ResolvePackPath(WorkloadPack pack, out bool isInstalled) { - var resolvedId = pack.Id; - - if (pack.IsAlias) + if (ResolveId(pack) is WorkloadPackId resolvedId) { - if (pack.TryGetAliasForRuntimeIdentifiers(_currentRuntimeIdentifiers) is WorkloadPackId aliasedId) - { - resolvedId = aliasedId; - } - else - { - return null; - } + return GetPackPath(_dotnetRootPaths, resolvedId, pack.Version, pack.Kind, out isInstalled); } - return GetPackPath(_dotnetRootPaths, resolvedId, pack.Version, pack.Kind); + isInstalled = false; + return null; } - private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, string packageVersion, WorkloadPackKind kind) + private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, string packageVersion, WorkloadPackKind kind, out bool isInstalled) { + isInstalled = false; string packPath = ""; bool isFile; foreach (var rootPath in dotnetRootPaths) @@ -241,15 +239,15 @@ private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, throw new ArgumentException($"The package kind '{kind}' is not known", nameof(kind)); } - bool packFound = isFile ? + //can we do a more robust check than directory.exists? + isInstalled = isFile ? _fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath) : _directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath); ; - if (packFound) + if (isInstalled) { break; } - } return packPath; } @@ -262,9 +260,8 @@ private HashSet GetInstalledPacks() var installedPacks = new HashSet(); foreach (var pack in _packs) { - var packPath = ResolvePackPath(pack.Value); - - if (packPath != null && PackExists(packPath, pack.Value.Kind)) + ResolvePackPath(pack.Value, out bool isInstalled); + if (isInstalled) { installedPacks.Add(pack.Key); } @@ -349,11 +346,10 @@ IEnumerable ExpandPacks (WorkloadId workloadId) if (_packs.TryGetValue(new WorkloadPackId (packId), out var pack)) { - var packPath = ResolvePackPath(pack); - var resolvedPackageId = pack.IsAlias ? pack.TryGetAliasForRuntimeIdentifiers(_currentRuntimeIdentifiers)?.ToString() : pack.Id.ToString(); - if (packPath != null && resolvedPackageId != null) + if (ResolveId(pack) is WorkloadPackId resolvedPackageId) { - return CreatePackInfo(pack, packPath, resolvedPackageId); + var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out bool exists); + return CreatePackInfo(pack, aliasedPath, resolvedPackageId); } } @@ -397,6 +393,9 @@ public PackInfo(string id, string version, WorkloadPackKind kind, string path, s ResolvedPackageId = resolvedPackageId; } + /// + /// The workload pack ID. The NuGet package ID may differ from this. + /// public string Id { get; } public string Version { get; } From b8ade8ee1c3e2470db732fb934e9c6e1feeb9d1d Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 9 Jun 2021 01:07:43 -0400 Subject: [PATCH 02/26] Implement workload redirects --- .../install/WorkloadManifestUpdater.cs | 2 +- .../Strings.resx | 6 +++ .../WorkloadDefinition.cs | 27 ++++++++++++-- .../WorkloadManifest.cs | 4 +- .../WorkloadManifestFormatException.cs | 27 ++++++++++++-- .../WorkloadManifestReader.cs | 29 +++++++++++---- .../WorkloadResolver.cs | 37 ++++++++++++++++++- .../xlf/Strings.cs.xlf | 10 +++++ .../xlf/Strings.de.xlf | 10 +++++ .../xlf/Strings.es.xlf | 10 +++++ .../xlf/Strings.fr.xlf | 10 +++++ .../xlf/Strings.it.xlf | 10 +++++ .../xlf/Strings.ja.xlf | 10 +++++ .../xlf/Strings.ko.xlf | 10 +++++ .../xlf/Strings.pl.xlf | 10 +++++ .../xlf/Strings.pt-BR.xlf | 10 +++++ .../xlf/Strings.ru.xlf | 10 +++++ .../xlf/Strings.tr.xlf | 10 +++++ .../xlf/Strings.zh-Hans.xlf | 10 +++++ .../xlf/Strings.zh-Hant.xlf | 10 +++++ 20 files changed, 242 insertions(+), 20 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs index 03958cfeb60d..98297ff8384f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadManifestUpdater.cs @@ -309,7 +309,7 @@ private async Task UpdateAdvertisingManifestAsync(ManifestId manifestId, bool in using (FileStream fsSource = new FileStream(manifestPath, FileMode.Open, FileAccess.Read)) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId.ToString(), fsSource); - return (new ManifestVersion(manifest.Version), manifest.Workloads); + return (new ManifestVersion(manifest.Version), manifest.Workloads.Values.OfType().ToDictionary(w => w.Id)); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx index 175e34d134dc..0bbdbf68185d 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx @@ -159,4 +159,10 @@ Unknown workload pack kind '{0}' at offset {1} + + Redirect workload '{0}' has keys other than 'redirect-to' + + + One or more workload redirects failed to resolve: {0} + \ No newline at end of file diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadDefinition.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadDefinition.cs index e9ab1acb02ad..13a4e5ffd2b2 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadDefinition.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadDefinition.cs @@ -5,13 +5,23 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader { - public class WorkloadDefinition + public abstract class BaseWorkloadDefinition + { + public BaseWorkloadDefinition (WorkloadId id) + { + Id = id; + } + + public WorkloadId Id { get; } + } + + public class WorkloadDefinition : BaseWorkloadDefinition { public WorkloadDefinition( WorkloadId id, bool isAbstract, string? description, WorkloadDefinitionKind kind, List? extends, - List? packs, List? platforms) + List? packs, List? platforms + ) : base (id) { - Id = id; IsAbstract = isAbstract; Description = description; Kind = kind; @@ -20,7 +30,6 @@ public WorkloadDefinition( Platforms = platforms; } - public WorkloadId Id { get; } public bool IsAbstract { get; } public string? Description { get; } public WorkloadDefinitionKind Kind { get; } @@ -34,4 +43,14 @@ public enum WorkloadDefinitionKind Dev, Build } + + public class WorkloadRedirect : BaseWorkloadDefinition + { + public WorkloadRedirect(WorkloadId id, WorkloadId replaceWith) : base (id) + { + ReplaceWith = replaceWith; + } + + public WorkloadId ReplaceWith { get; } + } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs index 80145fa1b85f..a6540f5d6827 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs @@ -12,7 +12,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public class WorkloadManifest { - internal WorkloadManifest(string id, FXVersion version, string? description, Dictionary workloads, Dictionary packs, Dictionary? dependsOnManifests) + internal WorkloadManifest(string id, FXVersion version, string? description, Dictionary workloads, Dictionary packs, Dictionary? dependsOnManifests) { Id = id; ParsedVersion = version; @@ -44,7 +44,7 @@ internal WorkloadManifest(string id, FXVersion version, string? description, Dic public string? Description { get; } - public Dictionary Workloads { get; } + public Dictionary Workloads { get; } public Dictionary Packs { get; } } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs index 9879548f1f3e..fde8901805a0 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs @@ -2,18 +2,37 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Runtime.Serialization; namespace Microsoft.NET.Sdk.WorkloadManifestReader { [Serializable] - class WorkloadManifestFormatException: Exception + class WorkloadManifestFormatException: WorkloadManifestException { public WorkloadManifestFormatException() { } public WorkloadManifestFormatException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } public WorkloadManifestFormatException(string message) : base(message) { } public WorkloadManifestFormatException(string message, Exception inner) : base(message, inner) { } - protected WorkloadManifestFormatException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + protected WorkloadManifestFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } + + [Serializable] + class WorkloadManifestCompositionException: WorkloadManifestException + { + public WorkloadManifestCompositionException() { } + public WorkloadManifestCompositionException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } + public WorkloadManifestCompositionException(string message) : base(message) { } + public WorkloadManifestCompositionException(string message, Exception inner) : base(message, inner) { } + protected WorkloadManifestCompositionException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } + + [Serializable] + abstract class WorkloadManifestException: Exception + { + protected WorkloadManifestException() { } + protected WorkloadManifestException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } + protected WorkloadManifestException(string message) : base(message) { } + protected WorkloadManifestException(string message, Exception inner) : base(message, inner) { } + protected WorkloadManifestException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs index 0f0039ece0f7..c6b7a6267a38 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs @@ -68,7 +68,7 @@ private static WorkloadManifest ReadWorkloadManifest(string id, ref Utf8JsonStre FXVersion? version = null; string? description = null; - Dictionary? workloads = null; + Dictionary? workloads = null; Dictionary? packs = null; Dictionary? dependsOn = null; @@ -100,7 +100,6 @@ private static WorkloadManifest ReadWorkloadManifest(string id, ref Utf8JsonStre continue; } } - } throw new WorkloadManifestFormatException(Strings.MissingOrInvalidManifestVersion); } @@ -156,7 +155,7 @@ private static WorkloadManifest ReadWorkloadManifest(string id, ref Utf8JsonStre id, version, description, - workloads ?? new Dictionary (), + workloads ?? new Dictionary (), packs ?? new Dictionary (), dependsOn ); @@ -183,7 +182,7 @@ private static bool ConsumeValue (ref Utf8JsonStreamReader reader) { return true; } - + var depth = reader.CurrentDepth; do { @@ -228,11 +227,11 @@ private static Dictionary ReadDependsOn(ref Utf8JsonStreamRea throw new WorkloadManifestFormatException(Strings.IncompleteDocument); } - private static Dictionary ReadWorkloadDefinitions(ref Utf8JsonStreamReader reader) + private static Dictionary ReadWorkloadDefinitions(ref Utf8JsonStreamReader reader) { ConsumeToken(ref reader, JsonTokenType.StartObject); - var workloads = new Dictionary(); + var workloads = new Dictionary(); while (reader.Read()) { @@ -378,7 +377,7 @@ private static Dictionary ReadStringDictionary(ref Utf8J throw new WorkloadManifestFormatException(Strings.IncompleteDocument); } - private static WorkloadDefinition ReadWorkloadDefinition(WorkloadId id, ref Utf8JsonStreamReader reader) + private static BaseWorkloadDefinition ReadWorkloadDefinition(WorkloadId id, ref Utf8JsonStreamReader reader) { ConsumeToken(ref reader, JsonTokenType.StartObject); @@ -388,6 +387,7 @@ private static WorkloadDefinition ReadWorkloadDefinition(WorkloadId id, ref Utf8 List? packs = null; List? extends = null; List? platforms = null; + WorkloadId? replaceWith = null; while (reader.Read()) { @@ -447,8 +447,23 @@ private static WorkloadDefinition ReadWorkloadDefinition(WorkloadId id, ref Utf8 continue; } + if (string.Equals("replace-with", propName, StringComparison.OrdinalIgnoreCase)) + { + if (replaceWith != null) ThrowDuplicateKeyException(ref reader, propName); + replaceWith = new WorkloadId (ReadString(ref reader)); + continue; + } + throw new WorkloadManifestFormatException(Strings.UnknownKeyAtOffset, propName, reader.TokenStartIndex); case JsonTokenType.EndObject: + if (replaceWith is WorkloadId replacementId) + { + if (isAbstractOrNull != null || description != null || kind != null || extends != null || packs != null || platforms != null) + { + throw new WorkloadManifestFormatException(Strings.RedirectWorkloadHasOtherKeys, id); + } + return new WorkloadRedirect (id, replacementId); + } var isAbstract = isAbstractOrNull ?? false; if (!isAbstract && kind == WorkloadDefinitionKind.Dev && string.IsNullOrEmpty (description)) { diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 2823ca34058b..6e935d20d8d2 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.DotNet.MSBuildSdkResolver; + +using Microsoft.NET.Sdk.Localization; +using FXVersion = Microsoft.DotNet.MSBuildSdkResolver.FXVersion; namespace Microsoft.NET.Sdk.WorkloadManifestReader { @@ -120,10 +122,41 @@ public void RefreshWorkloadManifests() } } } + + HashSet? redirects = null; foreach (var workload in manifest.Workloads) { - _workloads.Add(workload.Key, workload.Value); + if (workload.Value is WorkloadRedirect redirect) + { + (redirects ?? (redirects = new HashSet())).Add(redirect); + } + else + { + _workloads.Add(workload.Key, (WorkloadDefinition)workload.Value); + } + } + + // resolve redirects upfront so they are transparent to the rest of the code + // the _workloads dictionary maps redirected ids directly to the replacement + if (redirects != null) + { + // handle multi-levels redirects via multiple resolve passes, bottom-up + while (redirects.RemoveWhere(redirect => + { + if (_workloads.TryGetValue(redirect.ReplaceWith, out var replacement)) + { + _workloads.Add(redirect.Id, replacement); + return true; + } + return false; + }) > 0) { }; + + if (redirects.Count > 0) + { + throw new WorkloadManifestCompositionException(Strings.UnresolvedWorkloadRedirects, string.Join("\", \"", redirects.Select(r => r.Id.ToString()))); + } } + foreach (var pack in manifest.Packs) { _packs.Add(pack.Key, pack.Value); 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 67763c58004c..59a157dec284 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf @@ -52,6 +52,11 @@ Chybějící verze pro sadu úloh {0} + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Neočekávaný token {0} u posunu {1} @@ -72,6 +77,11 @@ Neznámý druh sady úloh {0} u posunu {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 ffb39f00edb1..6aa7347d4a6e 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf @@ -52,6 +52,11 @@ Version für Workloadpaket "{0}" fehlt. + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Unerwartetes Token "{0}" bei Offset {1}. @@ -72,6 +77,11 @@ Unbekannte Art des Workloadpakets ({0}) bei Offset {1}. + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 a030c0ae8bee..4c4db267767b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf @@ -52,6 +52,11 @@ Falta la versión del paquete de carga de trabajo "{0}" + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Token "{0}" inesperado en el desplazamiento {1} @@ -72,6 +77,11 @@ Tipo de paquete de carga de trabajo "{0}" desconocido en el desplazamiento {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 f80535afd8f5..a3785ebf0e94 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf @@ -52,6 +52,11 @@ Version manquante pour le pack de charges de travail '{0}' + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Jeton '{0}' inattendu à l'offset {1} @@ -72,6 +77,11 @@ Genre de pack de charge de travail inconnu '{0}' à l'offset {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 e281a6f85a9a..31da602f755b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf @@ -52,6 +52,11 @@ Versione mancante per il pacchetto '{0}' del carico di lavoro + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Token '{0}' imprevisto alla posizione di offset {1} @@ -72,6 +77,11 @@ Tipo di pacchetto del carico di lavoro '{0}' sconosciuto alla posizione di offset {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 d9ca8fc1a54c..31179702791d 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf @@ -52,6 +52,11 @@ ワークロード パック '{0}' のバージョンがありません + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} オフセット {1} に予期しないトークン '{0}' があります @@ -72,6 +77,11 @@ オフセット {1} に不明なワークロード パックの種類 '{0}' があります + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 2587cfc7d288..3d98adb5472e 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf @@ -52,6 +52,11 @@ Missing version for workload pack '{0}' + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Unexpected token '{0}' at offset {1} @@ -72,6 +77,11 @@ Unknown workload pack kind '{0}' at offset {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 9051ac7b88a6..b664bf148d90 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf @@ -52,6 +52,11 @@ Brak wersji dla pakietu obciążenia „{0}” + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Nieoczekiwany token „{0}” pod przesunięciem {1} @@ -72,6 +77,11 @@ Nieznany rodzaj pakietu obciążenia „{0}” pod przesunięciem {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 c1888c4ebe7f..16d6a2192caf 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 @@ -52,6 +52,11 @@ Versão do pacote de carga de trabalho '{0}' ausente + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Token inesperado '{0}' no deslocamento {1} @@ -72,6 +77,11 @@ Tipo de pacote de carga de trabalho '{0}' desconhecido no deslocamento {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 5953ddec9385..04a06fe54999 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf @@ -52,6 +52,11 @@ Отсутствует версия для пакета рабочей нагрузки "{0}" + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} Непредвиденный токен "{0}" в смещении {1} @@ -72,6 +77,11 @@ Неизвестный тип пакета рабочей нагрузки "{0}" в смещении {1} + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 097436ebcc41..eb4c40fa81c7 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf @@ -52,6 +52,11 @@ '{0}' iş yükü paketi için sürüm eksik + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} {1} uzaklığında beklenmeyen '{0}' belirteci @@ -72,6 +77,11 @@ {1} uzaklığında bilinmeyen '{0}' iş yükü paketi tipi + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 7881abb4b892..dac807caebe9 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 @@ -52,6 +52,11 @@ 工作负载包“{0}”版本缺失 + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} 偏移为 {1} 时意外出现的标记“{0}” @@ -72,6 +77,11 @@ 偏移为 {1} 时的未知工作负载包类型“{0}” + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file 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 11e37b0f7350..3ca30463c9d5 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 @@ -52,6 +52,11 @@ 缺少工作負載套件 '{0}' 的版本 + + Redirect workload '{0}' has keys other than 'redirect-to' + Redirect workload '{0}' has keys other than 'redirect-to' + + Unexpected token '{0}' at offset {1} 位移 {1} 有未預期的權杖 '{0}' @@ -72,6 +77,11 @@ 位移 {1} 有不明的工作負載套件種類 '{0}' + + One or more workload redirects failed to resolve: {0} + One or more workload redirects failed to resolve: {0} + + \ No newline at end of file From a22e8d0db58d55553ebccf113fa9310cc119dd31 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 9 Jun 2021 18:33:13 -0400 Subject: [PATCH 03/26] Fix 'avaliable' typo --- .../dotnet-sdk/check/LocalizableStrings.resx | 2 +- .../dotnet-sdk/check/RuntimeOutputWriter.cs | 2 +- .../commands/dotnet-sdk/check/SdkOutputWriter.cs | 12 ++++++------ .../check/xlf/LocalizableStrings.cs.xlf | 2 +- .../check/xlf/LocalizableStrings.de.xlf | 2 +- .../check/xlf/LocalizableStrings.es.xlf | 2 +- .../check/xlf/LocalizableStrings.fr.xlf | 2 +- .../check/xlf/LocalizableStrings.it.xlf | 2 +- .../check/xlf/LocalizableStrings.ja.xlf | 2 +- .../check/xlf/LocalizableStrings.ko.xlf | 2 +- .../check/xlf/LocalizableStrings.pl.xlf | 2 +- .../check/xlf/LocalizableStrings.pt-BR.xlf | 2 +- .../check/xlf/LocalizableStrings.ru.xlf | 2 +- .../check/xlf/LocalizableStrings.tr.xlf | 2 +- .../check/xlf/LocalizableStrings.zh-Hans.xlf | 2 +- .../check/xlf/LocalizableStrings.zh-Hant.xlf | 2 +- .../install/WorkloadInstallCommand.cs | 4 ++-- .../search/LocalizableStrings.resx | 2 +- .../search/WorkloadSearchCommand.cs | 6 +++--- .../search/xlf/LocalizableStrings.cs.xlf | 2 +- .../search/xlf/LocalizableStrings.de.xlf | 2 +- .../search/xlf/LocalizableStrings.es.xlf | 2 +- .../search/xlf/LocalizableStrings.fr.xlf | 2 +- .../search/xlf/LocalizableStrings.it.xlf | 2 +- .../search/xlf/LocalizableStrings.ja.xlf | 2 +- .../search/xlf/LocalizableStrings.ko.xlf | 2 +- .../search/xlf/LocalizableStrings.pl.xlf | 2 +- .../search/xlf/LocalizableStrings.pt-BR.xlf | 2 +- .../search/xlf/LocalizableStrings.ru.xlf | 2 +- .../search/xlf/LocalizableStrings.tr.xlf | 2 +- .../search/xlf/LocalizableStrings.zh-Hans.xlf | 2 +- .../search/xlf/LocalizableStrings.zh-Hant.xlf | 2 +- .../IWorkloadResolver.cs | 2 +- .../WorkloadResolver.cs | 4 ++-- .../ProcessFrameworkReferences.cs | 2 +- .../GivenDotnetSdkCheck.cs | 4 ++-- .../GivenDotnetWorkloadSearch.cs | 16 ++++++++-------- .../MockWorkloadResolver.cs | 10 +++++----- 38 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-sdk/check/LocalizableStrings.resx index fbc618738a51..ae15ab37186f 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/LocalizableStrings.resx @@ -132,7 +132,7 @@ Up to date. - + Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/RuntimeOutputWriter.cs b/src/Cli/dotnet/commands/dotnet-sdk/check/RuntimeOutputWriter.cs index 6ef7e841f55d..5c6f07a06af4 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/RuntimeOutputWriter.cs +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/RuntimeOutputWriter.cs @@ -49,7 +49,7 @@ private string GetRuntimeStatusMessage(NetRuntimeInfo runtime) } else if (NewerRuntimePatchExists(runtime)) { - return string.Format(LocalizableStrings.NewPatchAvaliableMessage, NewestRuntimePatchVersion(runtime)); + return string.Format(LocalizableStrings.NewPatchAvailableMessage, NewestRuntimePatchVersion(runtime)); } else { diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/SdkOutputWriter.cs b/src/Cli/dotnet/commands/dotnet-sdk/check/SdkOutputWriter.cs index e1fa02219785..9d3b924b28fe 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/SdkOutputWriter.cs +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/SdkOutputWriter.cs @@ -33,10 +33,10 @@ public void PrintSdkInfo() table.PrintRows(_sdkInfo.OrderBy(sdk => sdk.Version), l => _reporter.WriteLine(l)); - if (NewFeatureBandAvaliable()) + if (NewFeatureBandAvailable()) { _reporter.WriteLine(); - _reporter.WriteLine(string.Format(LocalizableStrings.NewFeatureBandMessage, NewestFeatureBandAvaliable())); + _reporter.WriteLine(string.Format(LocalizableStrings.NewFeatureBandMessage, NewestFeatureBandAvailable())); } } @@ -52,7 +52,7 @@ private string GetSdkStatusMessage(NetSdkInfo sdk) } else if (NewerSdkPatchExists(sdk)) { - return string.Format(LocalizableStrings.NewPatchAvaliableMessage, NewestSdkPatchVersion(sdk)); + return string.Format(LocalizableStrings.NewPatchAvailableMessage, NewestSdkPatchVersion(sdk)); } else { @@ -86,12 +86,12 @@ private ReleaseVersion NewestSdkPatchVersion(NetSdkInfo bundle) } } - private bool NewFeatureBandAvaliable() + private bool NewFeatureBandAvailable() { - return NewestFeatureBandAvaliable() > _sdkInfo.Select(sdk => sdk.Version).Max(); + return NewestFeatureBandAvailable() > _sdkInfo.Select(sdk => sdk.Version).Max(); } - private ReleaseVersion NewestFeatureBandAvaliable() + private ReleaseVersion NewestFeatureBandAvailable() { return _productCollection.OrderByDescending(product => product.ProductVersion).First().LatestSdkVersion; } diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.cs.xlf index 2d3e00d00f69..7ae678e7f495 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.cs.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.de.xlf index ed98a894c724..99373fd4bb4a 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.de.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.es.xlf index adbdb9cabbb7..5f90b85381df 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.es.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.fr.xlf index acb098165968..e2be6dcdc0b6 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.fr.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.it.xlf index 3af9103a3f61..d89ac7c37a5e 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.it.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ja.xlf index 8d5d6e741f45..d9afa75e7dbe 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ja.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ko.xlf index a977de150a65..16de158ae511 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ko.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pl.xlf index 1c5649d42e06..ca87d3c302e1 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pl.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pt-BR.xlf index 84a36e4170c2..fba2286454ac 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.pt-BR.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ru.xlf index 8136ec70448b..55ca01f7ffd6 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.ru.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.tr.xlf index 9b9cc8807146..ab343ba44577 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.tr.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hans.xlf index 5e41a2f74ce6..715c39fc9d76 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hans.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hant.xlf index cee6d3a8706b..9301a9677633 100644 --- a/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-sdk/check/xlf/LocalizableStrings.zh-Hant.xlf @@ -37,7 +37,7 @@ Try out the newest .NET SDK features with .NET {0}. - + Patch {0} is available. Patch {0} is available. diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index 9c9470e81e55..013b48c394d3 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -102,10 +102,10 @@ public WorkloadInstallCommand( private void ValidateWorkloadIdsInput() { - var avaliableWorkloads = _workloadResolver.GetAvaliableWorkloads(); + var availableWorkloads = _workloadResolver.GetAvailableWorkloads(); foreach (var workloadId in _workloadIds) { - if (avaliableWorkloads.Select(workload => workload.Id.ToString()).Contains(workloadId)) + if (availableWorkloads.Select(workload => workload.Id.ToString()).Contains(workloadId)) { if (!_workloadResolver.IsWorkloadPlatformCompatible(new WorkloadId(workloadId))) { diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx index b3ead42dc42c..cbca41ae7783 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-workload/search/LocalizableStrings.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Search for avaliable workloads. + Search for available workloads. WORKLOAD_ID diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs index 9fcee1c2540a..e9783d081dad 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs @@ -39,12 +39,12 @@ public WorkloadSearchCommand( public override int Execute() { - IEnumerable avaliableWorkloads = _workloadResolver.GetAvaliableWorkloads() + IEnumerable availableWorkloads = _workloadResolver.GetAvailableWorkloads() .OrderBy(workload => workload.Id); if (!string.IsNullOrEmpty(_workloadIdStub)) { - avaliableWorkloads = avaliableWorkloads.Where(workload => workload.Id.ToString().Contains(_workloadIdStub, StringComparison.OrdinalIgnoreCase)); + availableWorkloads = availableWorkloads.Where(workload => workload.Id.ToString().Contains(_workloadIdStub, StringComparison.OrdinalIgnoreCase)); } var table = new PrintableTable(); @@ -56,7 +56,7 @@ public override int Execute() } _reporter.WriteLine(); - table.PrintRows(avaliableWorkloads, l => _reporter.WriteLine(l)); + table.PrintRows(availableWorkloads, l => _reporter.WriteLine(l)); _reporter.WriteLine(); return 0; diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf index 657e6ac1ce84..debc37f78824 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.cs.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Vypíše globálně nebo místně nainstalované nástroje. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf index da79c52bf51d..44b02029ebe1 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.de.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Hiermit listen Sie die global oder lokal installierten Tools auf. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf index d1dc347feb45..dcf1b20c5bcc 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.es.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Mostrar las herramientas instaladas local o globalmente. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf index 6ff364efeeb4..9b34cd9998d7 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.fr.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Liste les outils installés globalement ou localement. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf index a345dd2aa070..fa5707d2d16f 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.it.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Elenca gli strumenti installati a livello globale o locale. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf index d6653328c9b1..3306c5ee79cd 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ja.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. グローバルまたはローカルにインストールされているツールを一覧表示します。 diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf index 482526411876..186277671f66 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ko.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. 전역으로 또는 로컬로 설치된 도구를 나열합니다. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf index bd7b416bd748..cb7846689609 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pl.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Wyświetl listę narzędzi zainstalowanych globalnie lub lokalnie. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf index 5cf2a248acbd..fcb6078739e7 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.pt-BR.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Ferramentas de lista instaladas de forma global ou local. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf index 9cb9fd039940..2586a5e4c328 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.ru.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Перечисление средств, установленных глобально или локально. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf index b838f954bbdd..ed2277797cab 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.tr.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. Genel veya yerel olarak yüklü araçları listeleyin. diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf index 7ba9928f3be6..fec0729e073e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hans.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. 列出全局或本地安装的工具。 diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf index ee803c2794cf..80ba345619f0 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-workload/search/xlf/LocalizableStrings.zh-Hant.xlf @@ -3,7 +3,7 @@ - Search for avaliable workloads. + Search for available workloads. 列出已安裝在全域或本機的工具。 diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index 409356f3113e..bacae97dbb86 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -10,7 +10,7 @@ public interface IWorkloadResolver IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind); IEnumerable GetPacksInWorkload(string workloadId); ISet GetWorkloadSuggestionForMissingPacks(IList packId); - IEnumerable GetAvaliableWorkloads(); + IEnumerable GetAvailableWorkloads(); WorkloadResolver CreateTempDirResolver(IWorkloadManifestProvider manifestProvider, string dotnetRootPath, string sdkVersion); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 6e935d20d8d2..03b3f8538b09 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -410,7 +410,7 @@ public ISet GetWorkloadSuggestionForMissingPacks(IList pac /// /// Returns the list of workloads defined by the manifests on disk /// - public IEnumerable GetAvaliableWorkloads() + public IEnumerable GetAvailableWorkloads() { return _workloads.Values; } @@ -478,7 +478,7 @@ public WorkloadInfo GetWorkloadInfo(WorkloadId WorkloadId) public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) { - var workloadDef = GetAvaliableWorkloads().FirstOrDefault(workload => workload.Id.ToString().Equals(workloadId.ToString())); + var workloadDef = GetAvailableWorkloads().FirstOrDefault(workload => workload.Id.ToString().Equals(workloadId.ToString())); if (workloadDef == null) { throw new Exception("Workload not found"); diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index b8e0f86e8736..e8b48a506cfb 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -255,7 +255,7 @@ protected override void ExecuteCore() } else { - // For the remaining profiles, don't include them in package download but add them to unavaliable if necessary. + // For the remaining profiles, don't include them in package download but add them to unavailable if necessary. runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack(); includeInPackageDownload = false; } diff --git a/src/Tests/dotnet-sdk-check.Tests/GivenDotnetSdkCheck.cs b/src/Tests/dotnet-sdk-check.Tests/GivenDotnetSdkCheck.cs index 252528c9e970..bd02e29cbfe2 100644 --- a/src/Tests/dotnet-sdk-check.Tests/GivenDotnetSdkCheck.cs +++ b/src/Tests/dotnet-sdk-check.Tests/GivenDotnetSdkCheck.cs @@ -109,7 +109,7 @@ public void ItContainsInfoForAllInstalledBundles() [InlineData(new string[] { "1.1.10", "2.1.300", "2.1.810", "3.1.400" }, new string[] { }, new string[] { "2.1.302", "2.1.811", "3.1.404" })] [InlineData(new string[] { }, new string[] { "1.1.10", "2.1.20", "3.1.0" }, new string[] { "2.1.23", "3.1.10" })] [InlineData(new string[] { "1.1.10", "2.1.300", "2.1.810", "3.1.400" }, new string[] { "1.1.10", "2.1.20", "3.1.0" }, new string[] { "2.1.302", "2.1.811", "3.1.404", "2.1.23", "3.1.10" })] - public void WhenANewPatchIsAvaliableItIsAdvertised(string[] sdkVersions, string[] runtimeVersions, string[] latestPatchVersions) + public void WhenANewPatchIsAvailableItIsAdvertised(string[] sdkVersions, string[] runtimeVersions, string[] latestPatchVersions) { var parseResult = Parser.Instance.Parse(new string[] { "dotnet", "sdk", "check" }); var bundles = GetFakeEnvironmentInfo(sdkVersions, runtimeVersions); @@ -117,7 +117,7 @@ public void WhenANewPatchIsAvaliableItIsAdvertised(string[] sdkVersions, string[ new SdkCheckCommand(parseResult, new MockNETBundleProvider(bundles), new MockProductCollectionProvider(fakeReleasesPath), _reporter).Execute(); var commandResult = string.Join(' ', _reporter.Lines); - var expectedLines = latestPatchVersions.Select(version => string.Format(LocalizableStrings.NewPatchAvaliableMessage, version)); + var expectedLines = latestPatchVersions.Select(version => string.Format(LocalizableStrings.NewPatchAvailableMessage, version)); foreach (var line in expectedLines) { commandResult diff --git a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs index 62981a47a524..0458e0e54bf8 100644 --- a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs +++ b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs @@ -18,7 +18,7 @@ namespace Microsoft.DotNet.Cli.Workload.Search.Tests public class GivenDotnetWorkloadSearch : SdkTest { private readonly BufferedReporter _reporter; - private readonly IEnumerable _avaliableWorkloads = + private readonly IEnumerable _availableWorkloads = new List() { new WorkloadDefinition(new WorkloadId("mock-workload-1"), false, null, WorkloadDefinitionKind.Dev, new List(), @@ -55,12 +55,12 @@ public void GivenNoStubIsProvidedSearchShowsAllWorkloads() { _reporter.Clear(); var parseResult = Parser.GetWorkloadsInstance.Parse("dotnet workload search"); - var workloadResolver = new MockWorkloadResolver(_avaliableWorkloads); + var workloadResolver = new MockWorkloadResolver(_availableWorkloads); var command = new WorkloadSearchCommand(parseResult, _reporter, workloadResolver, "6.0.100"); command.Execute(); var output = string.Join(" ", _reporter.Lines); - foreach (var workload in _avaliableWorkloads) + foreach (var workload in _availableWorkloads) { output.Contains(workload.Id.ToString()).Should().BeTrue(); if (workload.Description != null) @@ -79,12 +79,12 @@ public void GivenDetailedVerbositySearchShowsAllColumns() { _reporter.Clear(); var parseResult = Parser.GetWorkloadsInstance.Parse("dotnet workload search -v d"); - var workloadResolver = new MockWorkloadResolver(_avaliableWorkloads); + var workloadResolver = new MockWorkloadResolver(_availableWorkloads); var command = new WorkloadSearchCommand(parseResult, _reporter, workloadResolver, "6.0.100"); command.Execute(); var output = string.Join(" ", _reporter.Lines); - foreach (var workload in _avaliableWorkloads) + foreach (var workload in _availableWorkloads) { output.Contains(workload.Id.ToString()).Should().BeTrue(); if (workload.Description != null) @@ -103,12 +103,12 @@ public void GivenStubIsProvidedSearchShowsAllMatchingWorkloads() { _reporter.Clear(); var parseResult = Parser.GetWorkloadsInstance.Parse("dotnet workload search mock"); - var workloadResolver = new MockWorkloadResolver(_avaliableWorkloads); + var workloadResolver = new MockWorkloadResolver(_availableWorkloads); var command = new WorkloadSearchCommand(parseResult, _reporter, workloadResolver, "6.0.100"); command.Execute(); var output = string.Join(" ", _reporter.Lines); - var expectedWorkloads = _avaliableWorkloads.Take(3); + var expectedWorkloads = _availableWorkloads.Take(3); foreach (var workload in expectedWorkloads) { output.Contains(workload.Id.ToString()).Should().BeTrue(); @@ -124,7 +124,7 @@ public void GivenSearchResultsAreOrdered() { _reporter.Clear(); var parseResult = Parser.GetWorkloadsInstance.Parse("dotnet workload search"); - var workloadResolver = new MockWorkloadResolver(_avaliableWorkloads); + var workloadResolver = new MockWorkloadResolver(_availableWorkloads); var command = new WorkloadSearchCommand(parseResult, _reporter, workloadResolver, "6.0.100"); command.Execute(); diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index a87cd91b36d3..bd63fd935653 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -9,16 +9,16 @@ namespace Microsoft.DotNet.Cli.Workload.Search.Tests { public class MockWorkloadResolver : IWorkloadResolver { - private readonly IEnumerable _avaliableWorkloads; + private readonly IEnumerable _availableWorkloads; - public MockWorkloadResolver(IEnumerable avaliableWorkloads) + public MockWorkloadResolver(IEnumerable availableWorkloads) { - _avaliableWorkloads = avaliableWorkloads; + _availableWorkloads = availableWorkloads; } - public IEnumerable GetAvaliableWorkloads() + public IEnumerable GetAvailableWorkloads() { - return _avaliableWorkloads; + return _availableWorkloads; } public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) => throw new NotImplementedException(); From e7a3eb27df05f9053f255883b1eabea67ed54085 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 9 Jun 2021 19:04:32 -0400 Subject: [PATCH 04/26] Allow deferred opening of workload manifest stream --- .../dotnet-workload/install/WorkloadOptionsExtensions.cs | 4 ++-- .../IWorkloadManifestProvider.cs | 3 ++- .../SdkDirectoryWorkloadManifestProvider.cs | 4 ++-- .../TempDirectoryWorkloadManifestProvider.cs | 5 +++-- .../WorkloadResolver.cs | 4 ++-- .../FakeManifestProvider.cs | 8 +++++--- .../SdkDirectoryWorkloadManifestProviderTests.cs | 8 ++++++-- .../dotnet-workload-install.Tests/MockManifestProvider.cs | 6 ++++-- 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs index 782802653ef8..90f7439a368e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs @@ -33,9 +33,9 @@ internal static ReleaseVersion GetValidatedSdkVersion(string versionOption, stri } try { - foreach ((string manifestId, Stream manifestStream) in manifests) + foreach ((string manifestId, Func openManifestStream) in manifests) { - using (manifestStream) + using (var manifestStream = openManifestStream()) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs index 1d3c2d103555..8b56785f5507 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs @@ -1,6 +1,7 @@ // 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.IO; @@ -12,7 +13,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public interface IWorkloadManifestProvider { - IEnumerable<(string manifestId, Stream manifestStream)> GetManifests(); + IEnumerable<(string manifestId, Func openManifestStream)> GetManifests(); IEnumerable GetManifestDirectories(); string GetSdkFeatureBand(); } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs index d71ac662d806..c78e4e001cdc 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs @@ -68,13 +68,13 @@ static int Last2DigitsTo0(int versionBuild) } } - public IEnumerable<(string manifestId, Stream manifestStream)> GetManifests() + public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() { foreach (var workloadManifestDirectory in GetManifestDirectories()) { var workloadManifest = Path.Combine(workloadManifestDirectory, "WorkloadManifest.json"); var id = Path.GetFileName(workloadManifestDirectory); - yield return (id, File.OpenRead(workloadManifest)); + yield return (id, () => File.OpenRead(workloadManifest)); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs index 0ad77c589196..0aeb93754bb5 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs @@ -1,6 +1,7 @@ // 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.IO; @@ -17,13 +18,13 @@ public TempDirectoryWorkloadManifestProvider(string manifestsPath, string sdkVer _sdkVersionBand = sdkVersion; } - public IEnumerable<(string manifestId, Stream manifestStream)> GetManifests() + public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() { foreach (var workloadManifestDirectory in GetManifestDirectories()) { var workloadManifest = Path.Combine(workloadManifestDirectory, "WorkloadManifest.json"); var id = Path.GetFileName(workloadManifestDirectory); - yield return (id, File.OpenRead(workloadManifest)); + yield return (id, () => File.OpenRead(workloadManifest)); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 03b3f8538b09..5cbfed0377f0 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -89,10 +89,10 @@ public void RefreshWorkloadManifests() var manifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach ((string manifestId, Stream manifestStream) in _manifestProvider.GetManifests()) + foreach ((string manifestId, Func openManifestStream) in _manifestProvider.GetManifests()) { - using (manifestStream) + using (var manifestStream = openManifestStream()) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); if (manifests.ContainsKey(manifestId)) diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs index a2cee1abb6f6..697010aea9aa 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs @@ -3,6 +3,7 @@ using Microsoft.NET.Sdk.WorkloadManifestReader; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -22,11 +23,11 @@ public FakeManifestProvider(params string[] filePaths) public IEnumerable GetManifestDirectories() => throw new System.NotImplementedException(); - public IEnumerable<(string manifestId, Stream manifestStream)> GetManifests() + public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() { foreach (var filePath in _filePaths) { - yield return (Path.GetFileNameWithoutExtension(filePath), new FileStream(filePath, FileMode.Open, FileAccess.Read)); + yield return (Path.GetFileNameWithoutExtension(filePath), () => new FileStream(filePath, FileMode.Open, FileAccess.Read)); } } @@ -40,7 +41,8 @@ internal class InMemoryFakeManifestProvider : IWorkloadManifestProvider, IEnumer public void Add(string id, string content) => _manifests.Add((id, Encoding.UTF8.GetBytes(content))); public IEnumerable GetManifestDirectories() => throw new System.NotImplementedException(); - public IEnumerable<(string manifestId, Stream manifestStream)> GetManifests() => _manifests.Select(m => (m.id, (Stream)new MemoryStream(m.content))); + public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() + => _manifests.Select(m => (m.id, (Func)(() => new MemoryStream(m.content)))); // these are just so the collection initializer works public IEnumerator<(string id, string content)> GetEnumerator() => throw new System.NotImplementedException(); diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs index 247b52305698..801d14779261 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs @@ -90,7 +90,11 @@ public void GivenNoManifestJsonFileInDirectoryItShouldThrow() var sdkDirectoryWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "5.0.105"); - Action a = () => sdkDirectoryWorkloadManifestProvider.GetManifests().ToList(); + Action a = () => sdkDirectoryWorkloadManifestProvider.GetManifests().Select(m => { + using (m.openManifestStream()) { } + return true; + }).ToList(); + a.ShouldThrow(); } @@ -240,7 +244,7 @@ var sdkDirectoryWorkloadManifestProvider private IEnumerable GetManifestContents(SdkDirectoryWorkloadManifestProvider manifestProvider) { - return manifestProvider.GetManifests().Select(manifest => new StreamReader(manifest.manifestStream).ReadToEnd()); + return manifestProvider.GetManifests().Select(manifest => new StreamReader(manifest.openManifestStream()).ReadToEnd()); } private class EnvironmentMock diff --git a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs index da3e5c359cfc..7aa08a82b50f 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs @@ -2,6 +2,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.NET.Sdk.WorkloadManifestReader; + +using System; using System.Collections.Generic; using System.IO; @@ -24,11 +26,11 @@ public IEnumerable GetManifestDirectories() } } - public IEnumerable<(string manifestId, Stream manifestStream)> GetManifests() + public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() { foreach (var filePath in _filePaths) { - yield return (filePath, new FileStream(filePath, FileMode.Open, FileAccess.Read)); + yield return (filePath, () => new FileStream(filePath, FileMode.Open, FileAccess.Read)); } } From cf013d21529987a77e79e072186ebe0b9c159527 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 9 Jun 2021 19:13:16 -0400 Subject: [PATCH 05/26] Add workload resolver method to determine updated workloads --- .../WorkloadResolver.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 5cbfed0377f0..8b04e00092f3 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -415,6 +415,47 @@ public IEnumerable GetAvailableWorkloads() return _workloads.Values; } + /// + /// Determines which of the installed workloads has updates available in the advertising manifests. + /// + /// A resolver that composes the advertising manifests with the installed manifests that do not have corresponding advertising manifests + /// The IDs of all of the installed workloads + /// + public IEnumerable GetUpdatedWorkloads(WorkloadResolver advertisingManifestResolver, IEnumerable installedWorkloads) + { + foreach(var workloadId in installedWorkloads) + { + var existingWorkload = _workloads[workloadId]; + var existingPacks = GetPacksInWorkload(existingWorkload).ToHashSet(); + var updatedWorkload = advertisingManifestResolver._workloads[workloadId]; + var updatedPacks = advertisingManifestResolver.GetPacksInWorkload(updatedWorkload); + + if (!existingPacks.SetEquals(updatedPacks) || existingPacks.Any(p=> PackHasChanged(_packs[p], advertisingManifestResolver._packs[p]))) + { + yield return workloadId; + } + } + } + + private bool PackHasChanged(WorkloadPack oldPack, WorkloadPack newPack) + { + var existingPackResolvedId = ResolveId(oldPack); + var newPackResolvedId = ResolveId(newPack); + if (existingPackResolvedId is null && newPackResolvedId is null) + { + return false; // pack still aliases to nothing + } + else if (existingPackResolvedId is null || newPackResolvedId is null || !existingPackResolvedId.Value.Equals(newPackResolvedId.Value)) + { + return true; // alias has changed + } + if (!string.Equals(oldPack.Version, newPack.Version, StringComparison.OrdinalIgnoreCase)) + { + return true; // version has changed + } + return false; + } + public class PackInfo { public PackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) From 3374ec9f3c49785f041e986b8bbaf24409defeff Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Wed, 9 Jun 2021 23:06:16 -0400 Subject: [PATCH 06/26] Replace workload TempDirResolver with more generic OverlayResolver --- .../install/WorkloadInstallCommand.cs | 15 ++- .../IWorkloadResolver.cs | 7 +- .../WorkloadResolver.cs | 101 +++++++++++++----- .../MockWorkloadResolver.cs | 2 +- 4 files changed, 88 insertions(+), 37 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index 013b48c394d3..12fa024d9c8e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -38,7 +38,6 @@ internal class WorkloadInstallCommand : CommandBase private readonly IReadOnlyCollection _workloadIds; private readonly IInstaller _workloadInstaller; private IWorkloadResolver _workloadResolver; - private IWorkloadManifestProvider _workloadManifestProvider; private readonly INuGetPackageDownloader _nugetPackageDownloader; private readonly IWorkloadManifestUpdater _workloadManifestUpdater; private readonly ReleaseVersion _sdkVersion; @@ -80,8 +79,8 @@ public WorkloadInstallCommand( _packageSourceLocation = string.IsNullOrEmpty(configOption) && (sourceOption == null || !sourceOption.Any()) ? null : new PackageSourceLocation(string.IsNullOrEmpty(configOption) ? null : new FilePath(configOption), sourceFeedOverrides: sourceOption); - _workloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(_dotnetPath, _sdkVersion.ToString()); - _workloadResolver = workloadResolver ?? WorkloadResolver.Create(_workloadManifestProvider, _dotnetPath, _sdkVersion.ToString()); + var _sdkWorkloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(_dotnetPath, _sdkVersion.ToString()); + _workloadResolver = workloadResolver ?? WorkloadResolver.Create(_sdkWorkloadManifestProvider, _dotnetPath, _sdkVersion.ToString()); var sdkFeatureBand = new SdkFeatureBand(_sdkVersion); var tempPackagesDir = new DirectoryPath(Path.Combine(_tempDirPath, "dotnet-sdk-advertising-temp")); var restoreActionConfig = _parseResult.ToRestoreActionConfig(); @@ -95,7 +94,7 @@ public WorkloadInstallCommand( _workloadResolver, _verbosity, _nugetPackageDownloader, _dotnetPath, _tempDirPath, _packageSourceLocation, restoreActionConfig, elevationRequired: !_printDownloadLinkOnly && string.IsNullOrWhiteSpace(_downloadToCacheOption)); _userHome = userHome ?? CliFolderPathCalculator.DotnetHomePath; - _workloadManifestUpdater = workloadManifestUpdater ?? new WorkloadManifestUpdater(_reporter, _workloadManifestProvider, _workloadResolver, _nugetPackageDownloader, _userHome, _tempDirPath, _packageSourceLocation); + _workloadManifestUpdater = workloadManifestUpdater ?? new WorkloadManifestUpdater(_reporter, _sdkWorkloadManifestProvider, _workloadResolver, _nugetPackageDownloader, _userHome, _tempDirPath, _packageSourceLocation); ValidateWorkloadIdsInput(); } @@ -318,8 +317,8 @@ private async Task UseTempManifestsToResolvePacksAsync(DirectoryPath tempPath, b return; } await _workloadManifestUpdater.ExtractManifestPackagesToTempDirAsync(manifestPackagePaths, tempPath); - _workloadManifestProvider = new TempDirectoryWorkloadManifestProvider(tempPath.Value, _sdkVersion.ToString()); - _workloadResolver = _workloadResolver.CreateTempDirResolver(_workloadManifestProvider, _dotnetPath, _sdkVersion.ToString()); + var overlayProvider = new TempDirectoryWorkloadManifestProvider(tempPath.Value, _sdkVersion.ToString()); + _workloadResolver = _workloadResolver.CreateOverlayResolver(overlayProvider); } private async Task DownloadToOfflineCacheAsync(IEnumerable workloadIds, DirectoryPath offlineCache, bool skipManifestUpdate, bool includePreviews) @@ -332,8 +331,8 @@ private async Task DownloadToOfflineCacheAsync(IEnumerable workloadI { tempManifestDir = Path.Combine(offlineCache.Value, "temp-manifests"); await _workloadManifestUpdater.ExtractManifestPackagesToTempDirAsync(manifestPackagePaths, new DirectoryPath(tempManifestDir)); - _workloadManifestProvider = new TempDirectoryWorkloadManifestProvider(tempManifestDir, _sdkVersion.ToString()); - _workloadResolver = _workloadResolver.CreateTempDirResolver(_workloadManifestProvider, _dotnetPath, _sdkVersion.ToString()); + var overlayProvider = new TempDirectoryWorkloadManifestProvider(tempManifestDir, _sdkVersion.ToString()); + _workloadResolver = _workloadResolver.CreateOverlayResolver(overlayProvider); } else { diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index bacae97dbb86..d2c5d984963b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -11,7 +11,6 @@ public interface IWorkloadResolver IEnumerable GetPacksInWorkload(string workloadId); ISet GetWorkloadSuggestionForMissingPacks(IList packId); IEnumerable GetAvailableWorkloads(); - WorkloadResolver CreateTempDirResolver(IWorkloadManifestProvider manifestProvider, string dotnetRootPath, string sdkVersion); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); IDictionary GetInstalledManifests(); @@ -30,6 +29,12 @@ public interface IWorkloadResolver /// /// Refresh workload and pack information based on the current installed workload manifest files /// + /// This is not valid for overlay resolvers void RefreshWorkloadManifests(); + + /// + /// Derives a resolver from this resolver by overlaying a set of updated manifests and recomposing. + /// + IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 8b04e00092f3..f590c5d12217 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -17,9 +17,10 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public class WorkloadResolver : IWorkloadResolver { + private readonly Dictionary _manifests = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _workloads = new Dictionary(); private readonly Dictionary _packs = new Dictionary(); - private readonly IWorkloadManifestProvider _manifestProvider; + private IWorkloadManifestProvider? _manifestProvider; private string[] _currentRuntimeIdentifiers; private readonly string [] _dotnetRootPaths; @@ -57,59 +58,70 @@ public static WorkloadResolver CreateForTests(IWorkloadManifestProvider manifest return new WorkloadResolver(manifestProvider, dotNetRootPaths, currentRuntimeIdentifiers); } - public WorkloadResolver CreateTempDirResolver(IWorkloadManifestProvider manifestProvider, string dotnetRootPath, string sdkVersion) + /// + /// Creates a resolver by composing all the manifests from the provider. + /// + private WorkloadResolver(IWorkloadManifestProvider manifestProvider, string [] dotnetRootPaths, string [] currentRuntimeIdentifiers) + : this (dotnetRootPaths, currentRuntimeIdentifiers) { - var packRootEnvironmentVariable = Environment.GetEnvironmentVariable("DOTNETSDK_WORKLOAD_PACK_ROOTS"); - string[] dotnetRootPaths; - if (!string.IsNullOrEmpty(packRootEnvironmentVariable)) - { - dotnetRootPaths = packRootEnvironmentVariable.Split(Path.PathSeparator).Append(dotnetRootPath).ToArray(); - } - else - { - dotnetRootPaths = new[] { dotnetRootPath }; - } + _manifestProvider = manifestProvider; - return new WorkloadResolver(manifestProvider, dotnetRootPaths, _currentRuntimeIdentifiers); + LoadManifestsFromProvider(manifestProvider); + ComposeWorkloadManifests(); } - private WorkloadResolver(IWorkloadManifestProvider manifestProvider, string [] dotnetRootPaths, string [] currentRuntimeIdentifiers) + /// + /// Creates a resolver with no manifests. + /// A + private WorkloadResolver(string[] dotnetRootPaths, string[] currentRuntimeIdentifiers) { _dotnetRootPaths = dotnetRootPaths; _currentRuntimeIdentifiers = currentRuntimeIdentifiers; - _manifestProvider = manifestProvider; - - RefreshWorkloadManifests(); } public void RefreshWorkloadManifests() { - _workloads.Clear(); - _packs.Clear(); - - var manifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach ((string manifestId, Func openManifestStream) in _manifestProvider.GetManifests()) + if (_manifestProvider == null) + { + throw new InvalidOperationException("Resolver was created without provider and cannot be refreshed"); + } + _manifests.Clear(); + LoadManifestsFromProvider(_manifestProvider); + ComposeWorkloadManifests(); + } + private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvider) + { + foreach ((string manifestId, Func openManifestStream) in manifestProvider.GetManifests()) { using (var manifestStream = openManifestStream()) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); - if (manifests.ContainsKey(manifestId)) + if (_manifests.ContainsKey(manifestId)) { throw new Exception($"Duplicate workload manifest {manifestId}"); } - manifests.Add(manifestId, manifest); + if(!string.Equals (manifestId, manifest.Id, StringComparison.OrdinalIgnoreCase)) + { + throw new Exception($"Manifest provider {manifestProvider} supplied manifest '{manifestId}' does not match payload id '{manifest.Id}'"); + } + _manifests.Add(manifestId, manifest); } } + } + + private void ComposeWorkloadManifests() + { + _workloads.Clear(); + _packs.Clear(); - foreach (var manifest in manifests.Values) + foreach (var manifest in _manifests.Values) { if (manifest.DependsOnManifests != null) { foreach (var dependency in manifest.DependsOnManifests) { - if (manifests.TryGetValue(dependency.Key, out var resolvedDependency)) + if (_manifests.TryGetValue(dependency.Key, out var resolvedDependency)) { if (FXVersion.Compare(dependency.Value, resolvedDependency.ParsedVersion) > 0) { @@ -456,6 +468,25 @@ private bool PackHasChanged(WorkloadPack oldPack, WorkloadPack newPack) return false; } + public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) + { + // we specifically don't assign the overlayManifestProvider to the new resolver + // because it's not possible to refresh an overlay resolver + var overlayResolver = new WorkloadResolver(_dotnetRootPaths, _currentRuntimeIdentifiers); + overlayResolver.LoadManifestsFromProvider(overlayManifestProvider); + + // after loading the overlay manifests into the new resolver + // we add all the manifests from this resolver that are not overlayed + foreach (var manifest in _manifests) + { + overlayResolver._manifests.TryAdd(manifest.Key, manifest.Value); + } + + overlayResolver.ComposeWorkloadManifests(); + + return overlayResolver; + } + public class PackInfo { public PackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) @@ -561,4 +592,20 @@ public IDictionary GetInstalledManifests() return manifests; } } + +#if !NETCOREAPP + + static class DictionaryExtensions + { + public static bool TryAdd(this Dictionary dictionary, TKey key, TValue value) where TKey : notnull + { + if (dictionary.ContainsKey(key)) + { + return false; + } + dictionary.Add(key, value); + return true; + } + } +#endif } diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index bd63fd935653..86a3e9782254 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -26,9 +26,9 @@ public IEnumerable GetAvailableWorkloads() public ISet GetWorkloadSuggestionForMissingPacks(IList packId) => throw new NotImplementedException(); public void RefreshWorkloadManifests() => throw new NotImplementedException(); public WorkloadResolver.PackInfo TryGetPackInfo(string packId) => throw new NotImplementedException(); - public WorkloadResolver CreateTempDirResolver(IWorkloadManifestProvider manifestProvider, string dotnetRootPath, string sdkVersion) => throw new NotImplementedException(); public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) => throw new NotImplementedException(); public string GetManifestVersion(string manifestId) => throw new NotImplementedException(); public IDictionary GetInstalledManifests() => throw new NotImplementedException(); + public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) => throw new NotImplementedException(); } } From 0a8238c223cb821f136ff9070497c14e36d49bb2 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 10 Jun 2021 13:38:27 -0400 Subject: [PATCH 07/26] Improve diagnosability of manifest conflicts --- .../WorkloadResolver.cs | 95 ++++++++++++------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index f590c5d12217..93b326773d63 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -18,8 +18,8 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader public class WorkloadResolver : IWorkloadResolver { private readonly Dictionary _manifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _workloads = new Dictionary(); - private readonly Dictionary _packs = new Dictionary(); + private readonly Dictionary _workloads = new Dictionary(); + private readonly Dictionary _packs = new Dictionary(); private IWorkloadManifestProvider? _manifestProvider; private string[] _currentRuntimeIdentifiers; private readonly string [] _dotnetRootPaths; @@ -97,15 +97,14 @@ private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvide using (var manifestStream = openManifestStream()) { var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); - if (_manifests.ContainsKey(manifestId)) + if(!string.Equals (manifestId, manifest.Id, StringComparison.OrdinalIgnoreCase)) { - throw new Exception($"Duplicate workload manifest {manifestId}"); + throw new WorkloadManifestCompositionException($"Manifest '{manifestId}' from provider {manifestProvider} does not match payload id '{manifest.Id}'"); } - if(!string.Equals (manifestId, manifest.Id, StringComparison.OrdinalIgnoreCase)) + if (!_manifests.TryAdd(manifestId, manifest)) { - throw new Exception($"Manifest provider {manifestProvider} supplied manifest '{manifestId}' does not match payload id '{manifest.Id}'"); + throw new WorkloadManifestCompositionException($"Duplicate manifest '{manifestId}' from provider {manifestProvider}"); } - _manifests.Add(manifestId, manifest); } } } @@ -125,12 +124,12 @@ private void ComposeWorkloadManifests() { if (FXVersion.Compare(dependency.Value, resolvedDependency.ParsedVersion) > 0) { - throw new Exception($"Inconsistency in workload manifest '{manifest.Id}': requires '{dependency.Key}' version at least {dependency.Value} but found {resolvedDependency.Version}"); + throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}': requires '{dependency.Key}' version at least {dependency.Value} but found {resolvedDependency.Version}"); } } else { - throw new Exception($"Inconsistency in workload manifest '{manifest.Id}': missing dependency '{dependency.Key}'"); + throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}': missing dependency '{dependency.Key}'"); } } } @@ -140,11 +139,14 @@ private void ComposeWorkloadManifests() { if (workload.Value is WorkloadRedirect redirect) { - (redirects ?? (redirects = new HashSet())).Add(redirect); + (redirects ??= new HashSet()).Add(redirect); } else { - _workloads.Add(workload.Key, (WorkloadDefinition)workload.Value); + if (!_workloads.TryAdd(workload.Key, ((WorkloadDefinition)workload.Value, manifest))) + { + throw new WorkloadManifestCompositionException($"Workload '{workload.Key}' in manifest '{manifest.Id}' conflicts with manifest '{_workloads[workload.Key].manifest.Id}'"); + } } } @@ -157,7 +159,10 @@ private void ComposeWorkloadManifests() { if (_workloads.TryGetValue(redirect.ReplaceWith, out var replacement)) { - _workloads.Add(redirect.Id, replacement); + if (!_workloads.TryAdd(redirect.Id, replacement)) + { + throw new WorkloadManifestCompositionException($"Workload '{redirect.Id}' in manifest '{manifest.Id}' conflicts with manifest '{_workloads[redirect.Id].manifest.Id}'"); + } return true; } return false; @@ -171,7 +176,10 @@ private void ComposeWorkloadManifests() foreach (var pack in manifest.Packs) { - _packs.Add(pack.Key, pack.Value); + if (!_packs.TryAdd(pack.Key, (pack.Value, manifest))) + { + throw new WorkloadManifestCompositionException($"Workload pack '{pack.Key}' in manifest '{manifest.Id}' conflicts with manifest '{_packs[pack.Key].manifest.Id}'"); + } } } } @@ -185,7 +193,7 @@ private void ComposeWorkloadManifests() /// public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) { - foreach (var pack in _packs.Values) + foreach ((var pack, _) in _packs.Values) { if (pack.Kind != kind) { @@ -303,12 +311,12 @@ private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, private HashSet GetInstalledPacks() { var installedPacks = new HashSet(); - foreach (var pack in _packs) + foreach ((WorkloadPackId id, (WorkloadPack pack, WorkloadManifest _)) in _packs) { - ResolvePackPath(pack.Value, out bool isInstalled); + ResolvePackPath(pack, out bool isInstalled); if (isInstalled) { - installedPacks.Add(pack.Key); + installedPacks.Add(id); } } return installedPacks; @@ -323,10 +331,11 @@ public IEnumerable GetPacksInWorkload(string workloadId) var id = new WorkloadId(workloadId); - if (!_workloads.TryGetValue(id, out var workload)) + if (!_workloads.TryGetValue(id, out var value)) { throw new Exception($"Workload not found: {id}. Known workloads: {string.Join(" ", _workloads.Select(workload => workload.Key.ToString()))}"); } + var workload = value.workload; if (workload.Extends?.Count > 0) { @@ -344,7 +353,7 @@ internal IEnumerable GetPacksInWorkload(WorkloadDefinition workl IEnumerable ExpandPacks (WorkloadId workloadId) { - if (!_workloads.TryGetValue (workloadId, out var workloadInfo)) + if (!(_workloads.TryGetValue (workloadId) is (WorkloadDefinition workloadInfo, _))) { // inconsistent manifest throw new Exception("Workload not found"); @@ -389,11 +398,11 @@ IEnumerable ExpandPacks (WorkloadId workloadId) throw new ArgumentException($"'{nameof(packId)}' cannot be null or whitespace", nameof(packId)); } - if (_packs.TryGetValue(new WorkloadPackId (packId), out var pack)) + if (_packs.TryGetValue(new WorkloadPackId (packId)) is (WorkloadPack pack, _)) { if (ResolveId(pack) is WorkloadPackId resolvedPackageId) { - var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out bool exists); + var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out _); return CreatePackInfo(pack, aliasedPath, resolvedPackageId); } } @@ -410,12 +419,12 @@ IEnumerable ExpandPacks (WorkloadId workloadId) public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) { var requestedPacks = new HashSet(packIds.Select(p => new WorkloadPackId(p))); - var expandedWorkloads = _workloads.Select(w => (w.Key, new HashSet(GetPacksInWorkload(w.Value)))); + var expandedWorkloads = _workloads.Select(w => (w.Key, new HashSet(GetPacksInWorkload(w.Value.workload)))); var finder = new WorkloadSuggestionFinder(GetInstalledPacks(), requestedPacks, expandedWorkloads); return new HashSet ( - finder.GetBestSuggestion().Workloads.Select(s => new WorkloadInfo(s.ToString(), _workloads[s].Description)) + finder.GetBestSuggestion().Workloads.Select(s => new WorkloadInfo(s.ToString(), _workloads[s].workload.Description)) ); } @@ -424,7 +433,10 @@ public ISet GetWorkloadSuggestionForMissingPacks(IList pac /// public IEnumerable GetAvailableWorkloads() { - return _workloads.Values; + foreach ((WorkloadId _, (WorkloadDefinition workload, WorkloadManifest _)) in _workloads) + { + yield return workload; + } } /// @@ -437,12 +449,12 @@ public IEnumerable GetUpdatedWorkloads(WorkloadResolver advertisingM { foreach(var workloadId in installedWorkloads) { - var existingWorkload = _workloads[workloadId]; + var existingWorkload = _workloads[workloadId].workload; var existingPacks = GetPacksInWorkload(existingWorkload).ToHashSet(); - var updatedWorkload = advertisingManifestResolver._workloads[workloadId]; + var updatedWorkload = advertisingManifestResolver._workloads[workloadId].workload; var updatedPacks = advertisingManifestResolver.GetPacksInWorkload(updatedWorkload); - if (!existingPacks.SetEquals(updatedPacks) || existingPacks.Any(p=> PackHasChanged(_packs[p], advertisingManifestResolver._packs[p]))) + if (!existingPacks.SetEquals(updatedPacks) || existingPacks.Any(p=> PackHasChanged(_packs[p].pack, advertisingManifestResolver._packs[p].pack))) { yield return workloadId; } @@ -540,12 +552,11 @@ public WorkloadInfo(string id, string? description) public WorkloadInfo GetWorkloadInfo(WorkloadId WorkloadId) { - if (!_workloads.TryGetValue(WorkloadId, out var workload)) + if (_workloads.TryGetValue(WorkloadId) is (WorkloadDefinition workload, _)) { - throw new Exception("Workload not found"); + return new WorkloadInfo(workload.Id.ToString(), workload.Description); } - - return new WorkloadInfo(workload.Id.ToString(), workload.Description); + throw new Exception("Workload not found"); } public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) @@ -593,10 +604,9 @@ public IDictionary GetInstalledManifests() } } -#if !NETCOREAPP - static class DictionaryExtensions { +#if !NETCOREAPP public static bool TryAdd(this Dictionary dictionary, TKey key, TValue value) where TKey : notnull { if (dictionary.ContainsKey(key)) @@ -606,6 +616,23 @@ public static bool TryAdd(this Dictionary dictionary, dictionary.Add(key, value); return true; } - } + + public static void Deconstruct(this KeyValuePair kvp, out TKey key, out TValue value) + { + key = kvp.Key; + value = kvp.Value; + } #endif + + public static TValue? TryGetValue(this Dictionary dictionary, TKey key) + where TKey : notnull + where TValue : struct + { + if (dictionary.TryGetValue(key, out TValue value)) + { + return value; + } + return default(TValue?); + } + } } From accd6692504823392cb216ba3d7453dabf7ab3f6 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 21 Jun 2021 21:48:06 -0400 Subject: [PATCH 08/26] Improve workload composition errors Manifests have an "informational path" describing where they were loaded from. The workload resolver includes the manifest IDs and associated informational path in composition errors, so it's easier to see what caused the conflict. --- .../install/WorkloadOptionsExtensions.cs | 2 +- .../IWorkloadManifestProvider.cs | 4 +++- ...soft.NET.Sdk.WorkloadManifestReader.csproj | 1 - .../SdkDirectoryWorkloadManifestProvider.cs | 4 ++-- .../TempDirectoryWorkloadManifestProvider.cs | 4 ++-- .../WorkloadManifest.cs | 9 +++++++- .../WorkloadManifestReader.NewtonsoftJson.cs | 5 ++--- .../WorkloadManifestReader.SystemTextJson.cs | 4 ++-- .../WorkloadManifestReader.cs | 3 ++- .../WorkloadResolver.cs | 21 +++++++++---------- .../FakeManifestProvider.cs | 20 +++++++++--------- .../ManifestTests.cs | 4 ++-- .../MockManifestProvider.cs | 19 ++++++++++------- 13 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs index 90f7439a368e..dcdbf057cf8c 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadOptionsExtensions.cs @@ -33,7 +33,7 @@ internal static ReleaseVersion GetValidatedSdkVersion(string versionOption, stri } try { - foreach ((string manifestId, Func openManifestStream) in manifests) + foreach ((string manifestId, string informationalPath, Func openManifestStream) in manifests) { using (var manifestStream = openManifestStream()) { diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs index 8b56785f5507..d84a81d7b518 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadManifestProvider.cs @@ -13,8 +13,10 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public interface IWorkloadManifestProvider { - IEnumerable<(string manifestId, Func openManifestStream)> GetManifests(); + IEnumerable<(string manifestId, string? informationalPath, Func openManifestStream)> GetManifests(); + IEnumerable GetManifestDirectories(); + string GetSdkFeatureBand(); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Microsoft.NET.Sdk.WorkloadManifestReader.csproj b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Microsoft.NET.Sdk.WorkloadManifestReader.csproj index 35fc75564b54..e4b6e59d46a8 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Microsoft.NET.Sdk.WorkloadManifestReader.csproj +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Microsoft.NET.Sdk.WorkloadManifestReader.csproj @@ -8,7 +8,6 @@ true MicrosoftAspNetCore - 8.0 Enable true diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs index c78e4e001cdc..cb657650f3dd 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/SdkDirectoryWorkloadManifestProvider.cs @@ -68,13 +68,13 @@ static int Last2DigitsTo0(int versionBuild) } } - public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() + public IEnumerable<(string manifestId, string? informationalPath, Func openManifestStream)> GetManifests() { foreach (var workloadManifestDirectory in GetManifestDirectories()) { var workloadManifest = Path.Combine(workloadManifestDirectory, "WorkloadManifest.json"); var id = Path.GetFileName(workloadManifestDirectory); - yield return (id, () => File.OpenRead(workloadManifest)); + yield return (id, workloadManifest, () => File.OpenRead(workloadManifest)); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs index 0aeb93754bb5..73b30491547b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/TempDirectoryWorkloadManifestProvider.cs @@ -18,13 +18,13 @@ public TempDirectoryWorkloadManifestProvider(string manifestsPath, string sdkVer _sdkVersionBand = sdkVersion; } - public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() + public IEnumerable<(string manifestId, string? informationalPath, Func openManifestStream)> GetManifests() { foreach (var workloadManifestDirectory in GetManifestDirectories()) { var workloadManifest = Path.Combine(workloadManifestDirectory, "WorkloadManifest.json"); var id = Path.GetFileName(workloadManifestDirectory); - yield return (id, () => File.OpenRead(workloadManifest)); + yield return (id, workloadManifest, () => File.OpenRead(workloadManifest)); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs index a6540f5d6827..2edeee1b6681 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifest.cs @@ -12,11 +12,12 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public class WorkloadManifest { - internal WorkloadManifest(string id, FXVersion version, string? description, Dictionary workloads, Dictionary packs, Dictionary? dependsOnManifests) + internal WorkloadManifest(string id, FXVersion version, string? description, string? informationalPath, Dictionary workloads, Dictionary packs, Dictionary? dependsOnManifests) { Id = id; ParsedVersion = version; Description = description; + InformationalPath = informationalPath; Workloads = workloads; Packs = packs; DependsOnManifests = dependsOnManifests; @@ -44,6 +45,12 @@ internal WorkloadManifest(string id, FXVersion version, string? description, Dic public string? Description { get; } + /// + /// A path that indicates where the manifest was loaded from, for diagnostic purposes only. + /// Not guaranteed to be set or to be a valid filesystem path. + /// + public string? InformationalPath { get; } + public Dictionary Workloads { get; } public Dictionary Packs { get; } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.NewtonsoftJson.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.NewtonsoftJson.cs index 351c93d73ff3..a5a4791416b9 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.NewtonsoftJson.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.NewtonsoftJson.cs @@ -14,15 +14,14 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader { public partial class WorkloadManifestReader { - - public static WorkloadManifest ReadWorkloadManifest(string manifestId, Stream manifestStream) + public static WorkloadManifest ReadWorkloadManifest(string manifestId, Stream manifestStream, string? informationalPath = null) { using var textReader = new StreamReader(manifestStream, System.Text.Encoding.UTF8, true); using var jsonReader = new JsonTextReader(textReader); var reader = new Utf8JsonStreamReader(jsonReader); - return ReadWorkloadManifest(manifestId, ref reader); + return ReadWorkloadManifest(manifestId, informationalPath, ref reader); } // this is a compat wrapper so the source matches the system.text.json impl private ref struct Utf8JsonStreamReader diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.SystemTextJson.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.SystemTextJson.cs index 2d1951d7d15a..85e17b7c6665 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.SystemTextJson.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.SystemTextJson.cs @@ -12,7 +12,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader { public partial class WorkloadManifestReader { - public static WorkloadManifest ReadWorkloadManifest(string manifestId, Stream manifestStream) + public static WorkloadManifest ReadWorkloadManifest(string manifestId, Stream manifestStream, string? informationalPath = null) { var readerOptions = new JsonReaderOptions { @@ -22,7 +22,7 @@ public static WorkloadManifest ReadWorkloadManifest(string manifestId, Stream ma var reader = new Utf8JsonStreamReader(manifestStream, readerOptions); - return ReadWorkloadManifest(manifestId, ref reader); + return ReadWorkloadManifest(manifestId, informationalPath, ref reader); } private ref struct Utf8JsonStreamReader diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs index c6b7a6267a38..5b5f2b99973f 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs @@ -62,7 +62,7 @@ private static bool ReadBool(ref Utf8JsonStreamReader reader) private static void ThrowDuplicateKeyException (ref Utf8JsonStreamReader reader, T key) => throw new WorkloadManifestFormatException(Strings.DuplicateKeyAtOffset, key?.ToString() ?? throw new ArgumentNullException (nameof(key)), reader.TokenStartIndex); - private static WorkloadManifest ReadWorkloadManifest(string id, ref Utf8JsonStreamReader reader) + private static WorkloadManifest ReadWorkloadManifest(string id, string? informationalPath, ref Utf8JsonStreamReader reader) { ConsumeToken(ref reader, JsonTokenType.StartObject); @@ -155,6 +155,7 @@ private static WorkloadManifest ReadWorkloadManifest(string id, ref Utf8JsonStre id, version, description, + informationalPath, workloads ?? new Dictionary (), packs ?? new Dictionary (), dependsOn diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 93b326773d63..46d26f740622 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -92,15 +92,11 @@ public void RefreshWorkloadManifests() private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvider) { - foreach ((string manifestId, Func openManifestStream) in manifestProvider.GetManifests()) + foreach ((string manifestId, string? informationalPath, Func openManifestStream) in manifestProvider.GetManifests()) { using (var manifestStream = openManifestStream()) { - var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); - if(!string.Equals (manifestId, manifest.Id, StringComparison.OrdinalIgnoreCase)) - { - throw new WorkloadManifestCompositionException($"Manifest '{manifestId}' from provider {manifestProvider} does not match payload id '{manifest.Id}'"); - } + var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream, informationalPath); if (!_manifests.TryAdd(manifestId, manifest)) { throw new WorkloadManifestCompositionException($"Duplicate manifest '{manifestId}' from provider {manifestProvider}"); @@ -124,12 +120,12 @@ private void ComposeWorkloadManifests() { if (FXVersion.Compare(dependency.Value, resolvedDependency.ParsedVersion) > 0) { - throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}': requires '{dependency.Key}' version at least {dependency.Value} but found {resolvedDependency.Version}"); + throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}' ({manifest.InformationalPath}): requires '{dependency.Key}' version at least {dependency.Value} but found {resolvedDependency.Version}"); } } else { - throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}': missing dependency '{dependency.Key}'"); + throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}' ({manifest.InformationalPath}): missing dependency '{dependency.Key}'"); } } } @@ -145,7 +141,8 @@ private void ComposeWorkloadManifests() { if (!_workloads.TryAdd(workload.Key, ((WorkloadDefinition)workload.Value, manifest))) { - throw new WorkloadManifestCompositionException($"Workload '{workload.Key}' in manifest '{manifest.Id}' conflicts with manifest '{_workloads[workload.Key].manifest.Id}'"); + WorkloadManifest conflictingManifest = _workloads[workload.Key].manifest; + throw new WorkloadManifestCompositionException($"Workload '{workload.Key}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); } } } @@ -161,7 +158,8 @@ private void ComposeWorkloadManifests() { if (!_workloads.TryAdd(redirect.Id, replacement)) { - throw new WorkloadManifestCompositionException($"Workload '{redirect.Id}' in manifest '{manifest.Id}' conflicts with manifest '{_workloads[redirect.Id].manifest.Id}'"); + WorkloadManifest conflictingManifest = _workloads[redirect.Id].manifest; + throw new WorkloadManifestCompositionException($"Workload '{redirect.Id}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); } return true; } @@ -178,7 +176,8 @@ private void ComposeWorkloadManifests() { if (!_packs.TryAdd(pack.Key, (pack.Value, manifest))) { - throw new WorkloadManifestCompositionException($"Workload pack '{pack.Key}' in manifest '{manifest.Id}' conflicts with manifest '{_packs[pack.Key].manifest.Id}'"); + WorkloadManifest conflictingManifest = _packs[pack.Key].manifest; + throw new WorkloadManifestCompositionException($"Workload pack '{pack.Key}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); } } } diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs index 697010aea9aa..10bcc9e908ef 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/FakeManifestProvider.cs @@ -21,17 +21,17 @@ public FakeManifestProvider(params string[] filePaths) _filePaths = filePaths; } - public IEnumerable GetManifestDirectories() => throw new System.NotImplementedException(); + public IEnumerable GetManifestDirectories() => throw new NotImplementedException(); - public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() + public IEnumerable<(string manifestId, string? informationalPath, Func openManifestStream)> GetManifests() { foreach (var filePath in _filePaths) { - yield return (Path.GetFileNameWithoutExtension(filePath), () => new FileStream(filePath, FileMode.Open, FileAccess.Read)); + yield return (Path.GetFileNameWithoutExtension(filePath), filePath,() => new FileStream(filePath, FileMode.Open, FileAccess.Read)); } } - public string GetSdkFeatureBand() => throw new System.NotImplementedException(); + public string GetSdkFeatureBand() => throw new NotImplementedException(); } internal class InMemoryFakeManifestProvider : IWorkloadManifestProvider, IEnumerable<(string id, string content)> @@ -39,14 +39,14 @@ internal class InMemoryFakeManifestProvider : IWorkloadManifestProvider, IEnumer readonly List<(string id, byte[] content)> _manifests = new List<(string, byte[])>(); public void Add(string id, string content) => _manifests.Add((id, Encoding.UTF8.GetBytes(content))); - public IEnumerable GetManifestDirectories() => throw new System.NotImplementedException(); + public IEnumerable GetManifestDirectories() => throw new NotImplementedException(); - public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() - => _manifests.Select(m => (m.id, (Func)(() => new MemoryStream(m.content)))); + public IEnumerable<(string manifestId, string? informationalPath, Func openManifestStream)> GetManifests() + => _manifests.Select(m => (m.id, (string?)null, (Func)(() => new MemoryStream(m.content)))); // these are just so the collection initializer works - public IEnumerator<(string id, string content)> GetEnumerator() => throw new System.NotImplementedException(); - IEnumerator IEnumerable.GetEnumerator() => throw new System.NotImplementedException(); - public string GetSdkFeatureBand() => throw new System.NotImplementedException(); + public IEnumerator<(string id, string content)> GetEnumerator() => throw new NotImplementedException(); + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); + public string GetSdkFeatureBand() => throw new NotImplementedException(); } } diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs index 74c7121f84c1..204f81644541 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs @@ -190,7 +190,7 @@ string MakeManifest(string version, params (string id, string version)[] depends { "AAA", MakeManifest("20.0.0", ("BBB", "5.0.0"), ("CCC", "63.0.0"), ("DDD", "25.0.0")) } }; - var missingManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(missingManifestProvider, new[] { fakeRootPath })); + var missingManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(missingManifestProvider, new[] { fakeRootPath })); Assert.Contains("missing dependency", missingManifestEx.Message); var inconsistentManifestProvider = new InMemoryFakeManifestProvider @@ -201,7 +201,7 @@ string MakeManifest(string version, params (string id, string version)[] depends { "DDD", MakeManifest("30.0.0") }, }; - var inconsistentManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(inconsistentManifestProvider, new[] { fakeRootPath })); + var inconsistentManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(inconsistentManifestProvider, new[] { fakeRootPath })); Assert.Contains("Inconsistency in workload manifest", inconsistentManifestEx.Message); } diff --git a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs index 7aa08a82b50f..03da94e224cd 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs @@ -11,26 +11,31 @@ namespace ManifestReaderTests { internal class MockManifestProvider : IWorkloadManifestProvider { - readonly string[] _filePaths; + readonly (string name, string path)[] _manifests; - public MockManifestProvider(params string[] filePaths) + public MockManifestProvider(params string[] manifestPaths) { - _filePaths = filePaths; + _manifests = Array.ConvertAll(manifestPaths, mp => (mp, mp)); + } + + public MockManifestProvider(params (string name, string path)[] manifests) + { + _manifests = manifests; } public IEnumerable GetManifestDirectories() { - foreach (var filePath in _filePaths) + foreach ((_, var filePath) in _manifests) { yield return Path.GetDirectoryName(filePath); } } - public IEnumerable<(string manifestId, Func openManifestStream)> GetManifests() + public IEnumerable<(string manifestId, string informationalPath, Func openManifestStream)> GetManifests() { - foreach (var filePath in _filePaths) + foreach ((var id, var path) in _manifests) { - yield return (filePath, () => new FileStream(filePath, FileMode.Open, FileAccess.Read)); + yield return (id, path, () => File.OpenRead(path)); } } From ed81dd491c5b72b95c1cb26db798f48a08d975b1 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 21 Jun 2021 21:49:01 -0400 Subject: [PATCH 09/26] Nullability checks in workload manifest reader tests --- .../ManifestTests.cs | 6 +-- ...ET.Sdk.WorkloadManifestReader.Tests.csproj | 1 + ...kDirectoryWorkloadManifestProviderTests.cs | 50 ++++++++++++++----- .../WorkloadSuggestionFinderTests.cs | 4 +- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs index 204f81644541..ce3524a08bb8 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs @@ -58,7 +58,7 @@ public void AliasedPackPath() var buildToolsPack = resolver.GetInstalledWorkloadPacksOfKind(WorkloadPackKind.Sdk).FirstOrDefault(pack => pack.Id == "Xamarin.Android.BuildTools"); buildToolsPack.Should().NotBeNull(); - buildToolsPack.Id.Should().Be("Xamarin.Android.BuildTools"); + buildToolsPack!.Id.Should().Be("Xamarin.Android.BuildTools"); buildToolsPack.Version.Should().Be("8.4.7"); buildToolsPack.Path.Should().Be(Path.Combine(fakeRootPath, "packs", "Xamarin.Android.BuildTools.Win64Host", "8.4.7")); } @@ -128,7 +128,7 @@ void TestMultiplePackRoots(bool defaultExists, bool additionalExists) string expectedPath = additionalExists ? additionalPackPath : defaultPackPath; - pack.Path.Should().Be(expectedPath); + pack!.Path.Should().Be(expectedPath); } [Fact] @@ -148,7 +148,7 @@ public void GivenNonExistentPackRoot_ItIgnoresIt() var pack = resolver.TryGetPackInfo("Xamarin.Android.Sdk"); pack.Should().NotBeNull(); - pack.Path.Should().Be(defaultPackPath); + pack!.Path.Should().Be(defaultPackPath); } [Fact] diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests.csproj b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests.csproj index caf1307af9b4..b21b7ac07e4c 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests.csproj +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests.csproj @@ -5,6 +5,7 @@ $(ToolsetTargetFramework) Exe MicrosoftAspNetCore + Enable diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs index 801d14779261..9ed324fb802e 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/SdkDirectoryWorkloadManifestProviderTests.cs @@ -2,30 +2,35 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using FluentAssertions; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; -using Xunit; -using Xunit.Abstractions; -using Microsoft.NET.TestFramework; using System.Linq; -using Microsoft.NET.Sdk.WorkloadManifestReader; -using System.Collections.Generic; using System.Runtime.CompilerServices; +using FluentAssertions; + +using Microsoft.NET.Sdk.WorkloadManifestReader; +using Microsoft.NET.TestFramework; + +using Xunit; +using Xunit.Abstractions; + namespace ManifestReaderTests { public class SdkDirectoryWorkloadManifestProviderTests : SdkTest { - private string _testDirectory; - private string _manifestDirectory; - private string _fakeDotnetRootDirectory; + private string? _testDirectory; + private string? _manifestDirectory; + private string? _fakeDotnetRootDirectory; public SdkDirectoryWorkloadManifestProviderTests(ITestOutputHelper logger) : base(logger) { } - void Initialize([CallerMemberName] string testName = null, string identifier = null) + [MemberNotNull("_testDirectory", "_manifestDirectory", "_fakeDotnetRootDirectory")] + void Initialize([CallerMemberName] string? testName = null, string? identifier = null) { _testDirectory = _testAssetsManager.CreateTestDirectory(testName, identifier).Path; _fakeDotnetRootDirectory = Path.Combine(_testDirectory, "dotnet"); @@ -256,9 +261,9 @@ public void Add(string variable, string value) _mockedEnvironmentVariables[variable] = value; } - public string GetEnvironmentVariable(string variable) + public string? GetEnvironmentVariable(string variable) { - if (_mockedEnvironmentVariables.TryGetValue(variable, out string value)) + if (_mockedEnvironmentVariables.TryGetValue(variable, out string? value)) { return value; } @@ -267,3 +272,24 @@ public string GetEnvironmentVariable(string variable) } } } + +#if NETFRAMEWORK +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true, Inherited = false)] + sealed class MemberNotNullAttribute : Attribute + { + public MemberNotNullAttribute(params string[] members) + { + Members = members; + } + + public MemberNotNullAttribute(string member) + { + Members = new[] { member }; + } + + public string[] Members { get; } + } +} +#endif diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs index 93186ef8d5b7..4dcc4ccec89f 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs @@ -197,12 +197,12 @@ private static void FakeFileSystemChecksSoThesePackagesAppearInstalled(WorkloadR fileName => { var versionDir = Path.GetDirectoryName(fileName); - var idDir = Path.GetDirectoryName(versionDir); + var idDir = Path.GetDirectoryName(versionDir)!; return installedPacks.Contains(Path.GetFileName(idDir)); }, dirName => { - var idDir = Path.GetDirectoryName(dirName); + var idDir = Path.GetDirectoryName(dirName)!; return installedPacks.Contains(Path.GetFileName(idDir)); }); } From 3d64056448b16a822d7826b8b279769858bf6b0a Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 21 Jun 2021 21:50:55 -0400 Subject: [PATCH 10/26] Stronger typing of workload/pack ids in public API IIRC WorkloadId used to be private but now it's public there's no reason not to use it --- .../Installer/Windows/WorkloadPackRecord.cs | 5 ++- .../install/IWorkloadPackInstaller.cs | 3 +- .../install/MsiInstallerBase.cs | 2 +- .../install/NetSdkManagedInstaller.cs | 10 ++--- .../install/NetSdkMsiInstallerClient.cs | 6 +-- .../install/WorkloadInstallCommand.cs | 2 +- .../repair/WorkloadRepairCommand.cs | 2 +- .../update/WorkloadUpdateCommand.cs | 2 +- .../CachingWorkloadResolver.cs | 2 +- .../IWorkloadResolver.cs | 6 +-- .../WorkloadId.cs | 6 +++ .../WorkloadPackId.cs | 8 +++- .../WorkloadResolver.cs | 36 +++++++++--------- .../ShowMissingWorkloads.cs | 2 +- .../ManifestReaderFunctionalTests.cs | 4 +- .../ManifestTests.cs | 6 +-- .../WorkloadSuggestionFinderTests.cs | 10 ++--- .../GivenDotnetWorkloadInstall.cs | 6 +-- .../GivenNetSdkManagedWorkloadInstall.cs | 37 ++++++++++--------- .../MockPackWorkloadInstaller.cs | 2 +- .../MockWorkloadResolver.cs | 6 +-- .../GivenDotnetWorkloadUpdate.cs | 16 ++++---- 22 files changed, 99 insertions(+), 80 deletions(-) diff --git a/src/Cli/dotnet/Installer/Windows/WorkloadPackRecord.cs b/src/Cli/dotnet/Installer/Windows/WorkloadPackRecord.cs index 6fdc139118a3..5a37366075f8 100644 --- a/src/Cli/dotnet/Installer/Windows/WorkloadPackRecord.cs +++ b/src/Cli/dotnet/Installer/Windows/WorkloadPackRecord.cs @@ -3,6 +3,9 @@ #nullable disable using System; + +using Microsoft.NET.Sdk.WorkloadManifestReader; + using NuGet.Versioning; namespace Microsoft.DotNet.Installer.Windows @@ -25,7 +28,7 @@ public string ProviderKeyName /// /// The ID of the workload pack. /// - public string PackId + public WorkloadPackId PackId { get; set; diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadPackInstaller.cs b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadPackInstaller.cs index c77b6ab549e1..7c5c9546f717 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadPackInstaller.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/IWorkloadPackInstaller.cs @@ -5,6 +5,7 @@ using Microsoft.DotNet.Workloads.Workload.Install.InstallRecord; using Microsoft.Extensions.EnvironmentAbstractions; using System.Collections.Generic; +using Microsoft.NET.Sdk.WorkloadManifestReader; namespace Microsoft.DotNet.Workloads.Workload.Install { @@ -20,6 +21,6 @@ internal interface IWorkloadPackInstaller : IInstaller void GarbageCollectInstalledWorkloadPacks(); - IEnumerable<(string Id, string Version)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand); + IEnumerable<(WorkloadPackId Id, string Version)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand); } } diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs b/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs index 88e852779a70..86d12ce1ebab 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/MsiInstallerBase.cs @@ -127,7 +127,7 @@ private IReadOnlyDictionary> GetWorkloadPackRec WorkloadPackRecord record = new WorkloadPackRecord { ProviderKeyName = (string)packVersionKey.GetValue("DependencyProviderKey"), - PackId = packId, + PackId = new NET.Sdk.WorkloadManifestReader.WorkloadPackId(packId), PackVersion = new NuGetVersion(packVersion), ProductCode = (string)packVersionKey.GetValue("ProductCode"), ProductVersion = new Version((string)packVersionKey.GetValue("ProductVersion")) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkManagedInstaller.cs b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkManagedInstaller.cs index e4d3b691f1d6..5cf3c2092435 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkManagedInstaller.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkManagedInstaller.cs @@ -344,17 +344,17 @@ public void GarbageCollectInstalledWorkloadPacks() } } - public IEnumerable<(string, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) + public IEnumerable<(WorkloadPackId, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) { var installedPacksDir = Path.Combine(_workloadMetadataDir, _installedPacksDir, "v1"); if (!Directory.Exists(installedPacksDir)) { - return Enumerable.Empty<(string, string)>(); + return Enumerable.Empty<(WorkloadPackId, string)>(); } return Directory.GetDirectories(installedPacksDir) .Where(packIdDir => HasFeatureBandMarkerFile(packIdDir, sdkFeatureBand)) .SelectMany(packIdPath => Directory.GetDirectories(packIdPath)) - .Select(packVersionPath => (Path.GetFileName(Path.GetDirectoryName(packVersionPath)), Path.GetFileName(packVersionPath))); + .Select(packVersionPath => (new WorkloadPackId(Path.GetFileName(Path.GetDirectoryName(packVersionPath))), Path.GetFileName(packVersionPath))); } public void Shutdown() @@ -376,7 +376,7 @@ private IEnumerable GetExpectedPackInstallRecords(SdkFeatureBand sdkFeat { var installedWorkloads = _installationRecordRepository.GetInstalledWorkloads(sdkFeatureBand); return installedWorkloads - .SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload.ToString())) + .SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload)) .Select(pack => _workloadResolver.TryGetPackInfo(pack)) .Where(pack => pack != null) .Select(packInfo => GetPackInstallRecordPath(packInfo, sdkFeatureBand)); @@ -387,7 +387,7 @@ private PackInfo GetPackInfo(string packRecordDir) // Expected path: /metadata/workloads/installedpacks/v1/// var idRecordPath = Path.GetDirectoryName(packRecordDir); var packId = Path.GetFileName(idRecordPath); - var packInfo = _workloadResolver.TryGetPackInfo(packId); + var packInfo = _workloadResolver.TryGetPackInfo(new WorkloadPackId(packId)); if (packInfo != null && packInfo.Version.Equals(Path.GetFileName(packRecordDir))) { return packInfo; diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs index a8b0e2c60095..091a704ab0a1 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/NetSdkMsiInstallerClient.cs @@ -96,10 +96,10 @@ public void GarbageCollectInstalledWorkloadPacks() IEnumerable installedFeatureBands = GetInstalledFeatureBands(); IEnumerable installedWorkloads = RecordRepository.GetInstalledWorkloads(_sdkFeatureBand); IEnumerable expectedWorkloadPacks = installedWorkloads - .SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload.ToString())) + .SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload)) .Select(pack => _workloadResolver.TryGetPackInfo(pack)) .Where(pack => pack != null); - IEnumerable expectedPackIds = expectedWorkloadPacks.Select(p => p.Id); + IEnumerable expectedPackIds = expectedWorkloadPacks.Select(p => p.Id); foreach (PackInfo expectedPack in expectedWorkloadPacks) { @@ -219,7 +219,7 @@ public void GarbageCollectInstalledWorkloadPacks() public InstallationUnit GetInstallationUnit() => InstallationUnit.Packs; - public IEnumerable<(string, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) + public IEnumerable<(WorkloadPackId, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) { string dependent = $"{DependentPrefix},{sdkFeatureBand},{HostArchitecture}"; diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index 12fa024d9c8e..c64c03ac9f5e 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -373,7 +373,7 @@ private IEnumerable GetPacksToInstall(IEnumerable workload { var installedPacks = _workloadInstaller.GetPackInstaller().GetInstalledPacks(_sdkFeatureBand); return workloadIds - .SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId.ToString())) + .SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId)) .Distinct() .Select(packId => _workloadResolver.TryGetPackInfo(packId)) .Where(pack => pack != null) diff --git a/src/Cli/dotnet/commands/dotnet-workload/repair/WorkloadRepairCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/repair/WorkloadRepairCommand.cs index 9628e2e81ec3..fa0c2fd1d9d2 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/repair/WorkloadRepairCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/repair/WorkloadRepairCommand.cs @@ -109,7 +109,7 @@ private void ReinstallWorkloadsBasedOnCurrentManifests(IEnumerable w var installer = _workloadInstaller.GetPackInstaller(); var packsToInstall = workloadIds - .SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId.ToString())) + .SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId)) .Distinct() .Select(packId => _workloadResolver.TryGetPackInfo(packId)) .Where(pack => pack != null); diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs index 33e9798366ea..80d038b3e7a6 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs @@ -340,7 +340,7 @@ private IEnumerable GetUpdatablePacks(IWorkloadPackInstaller installer { var currentFeatureBand = new SdkFeatureBand(_sdkVersion); var workloads = GetUpdatableWorkloads(); - var updatedPacks = workloads.SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId.ToString())) + var updatedPacks = workloads.SelectMany(workloadId => _workloadResolver.GetPacksInWorkload(workloadId)) .Distinct() .Select(packId => _workloadResolver.TryGetPackInfo(packId)) .Where(pack => pack != null); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs index 351b003d4a0e..136251301819 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadMSBuildSdkResolver/CachingWorkloadResolver.cs @@ -148,7 +148,7 @@ private static ResolutionResult Resolve(string sdkReferenceName, IWorkloadManife } else { - var packInfo = workloadResolver.TryGetPackInfo(sdkReferenceName); + var packInfo = workloadResolver.TryGetPackInfo(new WorkloadPackId (sdkReferenceName)); if (packInfo != null) { if (Directory.Exists(packInfo.Path)) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index d2c5d984963b..a95e24a53c4a 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -8,8 +8,8 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader public interface IWorkloadResolver { IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind); - IEnumerable GetPacksInWorkload(string workloadId); - ISet GetWorkloadSuggestionForMissingPacks(IList packId); + IEnumerable GetPacksInWorkload(WorkloadId workloadId); + ISet GetWorkloadSuggestionForMissingPacks(IList packId); IEnumerable GetAvailableWorkloads(); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); @@ -24,7 +24,7 @@ public interface IWorkloadResolver /// /// A workload pack ID /// Information about the workload pack, or null if the specified pack ID isn't found in the manifests - WorkloadResolver.PackInfo? TryGetPackInfo(string packId); + WorkloadResolver.PackInfo? TryGetPackInfo(WorkloadPackId packId); /// /// Refresh workload and pack information based on the current installed workload manifest files diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadId.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadId.cs index a09b035f4ddb..ccadf4e41563 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadId.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadId.cs @@ -32,5 +32,11 @@ public WorkloadId(string id) public override bool Equals(object? obj) => obj is WorkloadId id && Equals(id); public override string ToString() => _id; + + public static implicit operator string(WorkloadId id) => id._id; + + public static bool operator ==(WorkloadId a, WorkloadId b) => a.Equals(b); + + public static bool operator !=(WorkloadId a, WorkloadId b) => !a.Equals(b); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadPackId.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadPackId.cs index b23e59b3ea5a..3296a1beab67 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadPackId.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadPackId.cs @@ -10,7 +10,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// However, display strings and paths in the sdk/packs/* folder use original casing. /// This internal struct helps preserve/annotate these semantics. /// - /// We also use this for workload definition ids for consistency + /// This is distinct from to prevent accidental confusion, but the behavior is identical public struct WorkloadPackId : IComparable, IEquatable { string _id; @@ -36,5 +36,11 @@ public WorkloadPackId(string id) public override string ToString() => _id; public string GetNuGetCanonicalId() => _id.ToLowerInvariant(); + + public static implicit operator string(WorkloadPackId id) => id._id; + + public static bool operator ==(WorkloadPackId a, WorkloadPackId b) => a.Equals(b); + + public static bool operator !=(WorkloadPackId a, WorkloadPackId b) => !a.Equals(b); } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 46d26f740622..143587616f3d 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -217,7 +217,7 @@ internal void ReplaceFilesystemChecksForTest(Func fileExists, Func } private PackInfo CreatePackInfo(WorkloadPack pack, string aliasedPath, WorkloadPackId resolvedPackageId) => new PackInfo( - pack.Id.ToString(), + pack.Id, pack.Version, pack.Kind, aliasedPath, @@ -321,28 +321,26 @@ private HashSet GetInstalledPacks() return installedPacks; } - public IEnumerable GetPacksInWorkload(string workloadId) + public IEnumerable GetPacksInWorkload(WorkloadId workloadId) { if (string.IsNullOrEmpty(workloadId)) { throw new ArgumentException($"'{nameof(workloadId)}' cannot be null or empty", nameof(workloadId)); } - var id = new WorkloadId(workloadId); - - if (!_workloads.TryGetValue(id, out var value)) + if (!_workloads.TryGetValue(workloadId, out var value)) { - throw new Exception($"Workload not found: {id}. Known workloads: {string.Join(" ", _workloads.Select(workload => workload.Key.ToString()))}"); + throw new Exception($"Workload not found: {workloadId}. Known workloads: {string.Join(" ", _workloads.Select(workload => workload.Key.ToString()))}"); } var workload = value.workload; if (workload.Extends?.Count > 0) { - return GetPacksInWorkload(workload).Select (p => p.ToString()); + return GetPacksInWorkload(workload); } #nullable disable - return workload.Packs.Select(p => p.ToString()) ?? Enumerable.Empty(); + return workload.Packs ?? Enumerable.Empty(); #nullable restore } @@ -390,11 +388,11 @@ IEnumerable ExpandPacks (WorkloadId workloadId) /// /// Used by the MSBuild SDK resolver to look up which versions of the SDK packs to import. /// - public PackInfo? TryGetPackInfo(string packId) + public PackInfo? TryGetPackInfo(WorkloadPackId packId) { - if (string.IsNullOrWhiteSpace(packId)) + if (string.IsNullOrEmpty(packId)) { - throw new ArgumentException($"'{nameof(packId)}' cannot be null or whitespace", nameof(packId)); + throw new ArgumentException($"'{nameof(packId)}' cannot be null or empty", nameof(packId)); } if (_packs.TryGetValue(new WorkloadPackId (packId)) is (WorkloadPack pack, _)) @@ -415,15 +413,15 @@ IEnumerable ExpandPacks (WorkloadId workloadId) /// /// Used by the MSBuild workload resolver to emit actionable errors /// - public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) + public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) { - var requestedPacks = new HashSet(packIds.Select(p => new WorkloadPackId(p))); + var requestedPacks = new HashSet(packIds); var expandedWorkloads = _workloads.Select(w => (w.Key, new HashSet(GetPacksInWorkload(w.Value.workload)))); var finder = new WorkloadSuggestionFinder(GetInstalledPacks(), requestedPacks, expandedWorkloads); return new HashSet ( - finder.GetBestSuggestion().Workloads.Select(s => new WorkloadInfo(s.ToString(), _workloads[s].workload.Description)) + finder.GetBestSuggestion().Workloads.Select(s => new WorkloadInfo(s, _workloads[s].workload.Description)) ); } @@ -500,7 +498,7 @@ public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlay public class PackInfo { - public PackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) + public PackInfo(WorkloadPackId id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) { Id = id; Version = version; @@ -512,7 +510,7 @@ public PackInfo(string id, string version, WorkloadPackKind kind, string path, s /// /// The workload pack ID. The NuGet package ID may differ from this. /// - public string Id { get; } + public WorkloadPackId Id { get; } public string Version { get; } @@ -539,13 +537,13 @@ public PackInfo(string id, string version, WorkloadPackKind kind, string path, s public class WorkloadInfo { - public WorkloadInfo(string id, string? description) + public WorkloadInfo(WorkloadId id, string? description) { Id = id; Description = description; } - public string Id { get; } + public WorkloadId Id { get; } public string? Description { get; } } @@ -553,7 +551,7 @@ public WorkloadInfo GetWorkloadInfo(WorkloadId WorkloadId) { if (_workloads.TryGetValue(WorkloadId) is (WorkloadDefinition workload, _)) { - return new WorkloadInfo(workload.Id.ToString(), workload.Description); + return new WorkloadInfo(workload.Id, workload.Description); } throw new Exception("Workload not found"); } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs index 9e1522d83986..560188eb32ad 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs @@ -34,7 +34,7 @@ protected override void ExecuteCore() var workloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(NetCoreRoot, NETCoreSdkVersion); var workloadResolver = WorkloadResolver.Create(workloadManifestProvider, NetCoreRoot, NETCoreSdkVersion); - var suggestedWorkloads = workloadResolver.GetWorkloadSuggestionForMissingPacks(MissingWorkloadPacks.Select(item => item.ItemSpec).ToList()); + var suggestedWorkloads = workloadResolver.GetWorkloadSuggestionForMissingPacks(MissingWorkloadPacks.Select(item => new WorkloadPackId (item.ItemSpec)).ToList()); if (GenerateErrorsForMissingWorkloads) { diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestReaderFunctionalTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestReaderFunctionalTests.cs index a18df0bdee71..ce7da0d9bc87 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestReaderFunctionalTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestReaderFunctionalTests.cs @@ -27,7 +27,7 @@ public void ItShouldGetAllTemplatesPacks() var result = workloadResolver.GetInstalledWorkloadPacksOfKind(WorkloadPackKind.Template); result.Should().HaveCount(1); var templateItem = result.First(); - templateItem.Id.Should().Be("Xamarin.Android.Templates"); + templateItem.Id.ToString().Should().Be("Xamarin.Android.Templates"); templateItem.IsStillPacked.Should().BeFalse(); templateItem.Kind.Should().Be(WorkloadPackKind.Template); templateItem.Path.Should() @@ -41,7 +41,7 @@ public void ItShouldGetAllSdkPacks() var result = workloadResolver.GetInstalledWorkloadPacksOfKind(WorkloadPackKind.Sdk); result.Should().HaveCount(5); var androidWorkloads = result.Single(w => w.Id == "Xamarin.Android.Sdk"); - androidWorkloads.Id.Should().Be("Xamarin.Android.Sdk"); + androidWorkloads.Id.ToString().Should().Be("Xamarin.Android.Sdk"); androidWorkloads.IsStillPacked.Should().BeTrue(); androidWorkloads.Kind.Should().Be(WorkloadPackKind.Sdk); androidWorkloads.Version.Should().Be("8.4.7"); diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs index ce3524a08bb8..dfc83699e12a 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs @@ -58,7 +58,7 @@ public void AliasedPackPath() var buildToolsPack = resolver.GetInstalledWorkloadPacksOfKind(WorkloadPackKind.Sdk).FirstOrDefault(pack => pack.Id == "Xamarin.Android.BuildTools"); buildToolsPack.Should().NotBeNull(); - buildToolsPack!.Id.Should().Be("Xamarin.Android.BuildTools"); + buildToolsPack!.Id.ToString().Should().Be("Xamarin.Android.BuildTools"); buildToolsPack.Version.Should().Be("8.4.7"); buildToolsPack.Path.Should().Be(Path.Combine(fakeRootPath, "packs", "Xamarin.Android.BuildTools.Win64Host", "8.4.7")); } @@ -123,7 +123,7 @@ void TestMultiplePackRoots(bool defaultExists, bool additionalExists) var manifestProvider = new FakeManifestProvider(ManifestPath); var resolver = WorkloadResolver.CreateForTests(manifestProvider, new[] { additionalRoot, dotnetRoot }); - var pack = resolver.TryGetPackInfo("Xamarin.Android.Sdk"); + var pack = resolver.TryGetPackInfo(new WorkloadPackId("Xamarin.Android.Sdk")); pack.Should().NotBeNull(); string expectedPath = additionalExists ? additionalPackPath : defaultPackPath; @@ -145,7 +145,7 @@ public void GivenNonExistentPackRoot_ItIgnoresIt() var manifestProvider = new FakeManifestProvider(ManifestPath); var resolver = WorkloadResolver.CreateForTests(manifestProvider, new[] { additionalRoot, dotnetRoot }); - var pack = resolver.TryGetPackInfo("Xamarin.Android.Sdk"); + var pack = resolver.TryGetPackInfo(new WorkloadPackId("Xamarin.Android.Sdk")); pack.Should().NotBeNull(); pack!.Path.Should().Be(defaultPackPath); diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs index 4dcc4ccec89f..f991b37b4c50 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs @@ -34,9 +34,9 @@ public void CanSuggestSimpleWorkload() FakeFileSystemChecksSoThesePackagesAppearInstalled(resolver, "Xamarin.Android.Sdk", "Xamarin.Android.BuildTools"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Sdk" }); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Sdk" }.Select(s => new WorkloadPackId(s)).ToList()); suggestions.Count().Should().Be(1); - suggestions.First().Id.Should().Be("xamarin-android-build"); + suggestions.First().Id.ToString().Should().Be("xamarin-android-build"); } [Fact] @@ -53,7 +53,7 @@ public void CanSuggestTwoWorkloadsToFulfilTwoRequirements() "Xamarin.Android.Runtime", "Mono.Android.Sdk"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Runtime.x86", "Mono.Android.Runtime.Armv7a" }); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Runtime.x86", "Mono.Android.Runtime.Armv7a" }.Select(s => new WorkloadPackId(s)).ToList()); suggestions.Count().Should().Be(2); suggestions.Should().Contain(s => s.Id == "xamarin-android-build-armv7a"); suggestions.Should().Contain(s => s.Id == "xamarin-android-build-x86"); @@ -73,9 +73,9 @@ public void CanSuggestWorkloadThatFulfillsTwoRequirements() "Xamarin.Android.Runtime", "Mono.Android.Sdk"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Xamarin.Android.Templates", "Xamarin.Android.LLVM.Aot.armv7a" }); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Xamarin.Android.Templates", "Xamarin.Android.LLVM.Aot.armv7a" }.Select(s => new WorkloadPackId(s)).ToList()); suggestions.Count().Should().Be(1); - suggestions.First().Id.Should().Be("xamarin-android-complete"); + suggestions.First().Id.ToString().Should().Be("xamarin-android-complete"); } [Fact] diff --git a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs index 6702fb7ae522..7b58d4fc59b3 100644 --- a/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs +++ b/src/Tests/dotnet-workload-install.Tests/GivenDotnetWorkloadInstall.cs @@ -62,7 +62,7 @@ public void GivenWorkloadInstallItCanInstallPacks() installer.CachePath.Should().BeNull(); installer.InstallationRecordRepository.WorkloadInstallRecord.Should().BeEquivalentTo(mockWorkloadIds); installer.InstalledPacks.Count.Should().Be(8); - installer.InstalledPacks.Where(pack => pack.Id.Contains("Android")).Count().Should().Be(8); + installer.InstalledPacks.Where(pack => pack.Id.ToString().Contains("Android")).Count().Should().Be(8); } [Fact] @@ -75,7 +75,7 @@ public void GivenWorkloadInstallItCanRollBackPackInstallation() var exceptionThrown = Assert.Throws(() => installManager.InstallWorkloads(mockWorkloadIds, true)); exceptionThrown.Message.Should().Be("Failing workload: xamarin-android-build"); var expectedPacks = mockWorkloadIds - .SelectMany(workloadId => workloadResolver.GetPacksInWorkload(workloadId.ToString())) + .SelectMany(workloadId => workloadResolver.GetPacksInWorkload(workloadId)) .Distinct() .Select(packId => workloadResolver.TryGetPackInfo(packId)) .Where(pack => pack != null); @@ -194,7 +194,7 @@ public void GivenWorkloadInstallItCanInstallFromOfflineCache() installer.CachePath.Should().Contain(cachePath); installer.InstallationRecordRepository.WorkloadInstallRecord.Should().BeEquivalentTo(mockWorkloadIds); installer.InstalledPacks.Count.Should().Be(8); - installer.InstalledPacks.Where(pack => pack.Id.Contains("Android")).Count().Should().Be(8); + installer.InstalledPacks.Where(pack => pack.Id.ToString().Contains("Android")).Count().Should().Be(8); nugetDownloader.DownloadCallParams.Count().Should().Be(0); } diff --git a/src/Tests/dotnet-workload-install.Tests/GivenNetSdkManagedWorkloadInstall.cs b/src/Tests/dotnet-workload-install.Tests/GivenNetSdkManagedWorkloadInstall.cs index 20b98e6e41a9..35e72fa80b20 100644 --- a/src/Tests/dotnet-workload-install.Tests/GivenNetSdkManagedWorkloadInstall.cs +++ b/src/Tests/dotnet-workload-install.Tests/GivenNetSdkManagedWorkloadInstall.cs @@ -109,11 +109,14 @@ public void GivenManagedInstallItCanWriteInstallationRecord() File.Exists(expectedPath).Should().BeTrue(); } + static PackInfo CreatePackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) + => new PackInfo(new WorkloadPackId(id), version, kind, path, resolvedPackageId); + [Fact] public void GivenManagedInstallItCanInstallDirectoryPacks() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var version = "6.0.100"; installer.InstallWorkloadPack(packInfo, new SdkFeatureBand(version)); @@ -134,7 +137,7 @@ public void GivenManagedInstallItCanInstallDirectoryPacks() public void GivenManagedInstallItCanInstallSingleFilePacks() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Template, Path.Combine(dotnetRoot, "template-packs", "Xamarin.Android.Sdk.8.4.7.nupkg"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Template, Path.Combine(dotnetRoot, "template-packs", "Xamarin.Android.Sdk.8.4.7.nupkg"), "Xamarin.Android.Sdk"); var version = "6.0.100"; installer.InstallWorkloadPack(packInfo, new SdkFeatureBand(version)); @@ -153,7 +156,7 @@ public void GivenManagedInstallItCanInstallPacksWithAliases() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); var alias = "Xamarin.Android.BuildTools.Alias"; - var packInfo = new PackInfo("Xamarin.Android.BuildTools", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", alias, "8.4.7"), alias); + var packInfo = CreatePackInfo("Xamarin.Android.BuildTools", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", alias, "8.4.7"), alias); var version = "6.0.100"; installer.InstallWorkloadPack(packInfo, new SdkFeatureBand(version)); @@ -166,7 +169,7 @@ public void GivenManagedInstallItHonorsNuGetSources() { var packageSource = new PackageSourceLocation(new FilePath("mock-file")); var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(packageSourceLocation: packageSource); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var version = "6.0.100"; installer.InstallWorkloadPack(packInfo, new SdkFeatureBand(version)); @@ -179,7 +182,7 @@ public void GivenManagedInstallItHonorsNuGetSources() public void GivenManagedInstallItDetectsInstalledPacks() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var version = "6.0.100"; // Mock installing the pack @@ -195,7 +198,7 @@ public void GivenManagedInstallItCanRollBackInstallFailures() { var version = "6.0.100"; var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(failingInstaller: true); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var exceptionThrown = Assert.Throws(() => installer.InstallWorkloadPack(packInfo, new SdkFeatureBand(version))); exceptionThrown.Message.Should().Be("Test Failure"); @@ -212,8 +215,8 @@ public void GivenManagedInstallItCanGarbageCollect() var (dotnetRoot, installer, _) = GetTestInstaller(); var packs = new PackInfo[] { - new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Library, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), - new PackInfo("Xamarin.Android.Framework", "8.4.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.4.0"), "Xamarin.Android.Framework") + CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Library, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), + CreatePackInfo("Xamarin.Android.Framework", "8.4.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.4.0"), "Xamarin.Android.Framework") }; var sdkVersions = new string[] { "6.0.100", "6.0.300" }; @@ -254,8 +257,8 @@ public void GivenManagedInstallItCanGarbageCollectPacksMissingFromManifest() // Define packs that don't show up in the manifest var packs = new PackInfo[] { - new PackInfo("Xamarin.Android.Sdk.fake", "8.4.7", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk.fake", "8.4.7"), "Xamarin.Android.Sdk.fake"), - new PackInfo("Xamarin.Android.Framework.mock", "8.4", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework.mock", "8.4"), "Xamarin.Android.Framework.mock") + CreatePackInfo("Xamarin.Android.Sdk.fake", "8.4.7", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk.fake", "8.4.7"), "Xamarin.Android.Sdk.fake"), + CreatePackInfo("Xamarin.Android.Framework.mock", "8.4", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework.mock", "8.4"), "Xamarin.Android.Framework.mock") }; var sdkVersions = new string[] { "6.0.100", "6.0.300" }; @@ -291,13 +294,13 @@ public void GivenManagedInstallItDoesNotRemovePacksWithInstallRecords() var (dotnetRoot, installer, _) = GetTestInstaller(); var packs = new PackInfo[] { - new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Library, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), - new PackInfo("Xamarin.Android.Framework", "8.4.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.4.0"), "Xamarin.Android.Framework") + CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Library, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), + CreatePackInfo("Xamarin.Android.Framework", "8.4.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.4.0"), "Xamarin.Android.Framework") }; var packsToBeGarbageCollected = new PackInfo[] { - new PackInfo("Test.Pack.A", "1.0.0", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Test.Pack.A", "1.0.0"), "Test.Pack.A"), - new PackInfo("Test.Pack.B", "2.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Test.Pack.B", "2.0.0"), "Test.Pack.B"), + CreatePackInfo("Test.Pack.A", "1.0.0", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Test.Pack.A", "1.0.0"), "Test.Pack.A"), + CreatePackInfo("Test.Pack.B", "2.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Test.Pack.B", "2.0.0"), "Test.Pack.B"), }; var sdkVersions = new string[] { "6.0.100", "6.0.300" }; @@ -364,7 +367,7 @@ public void GivenManagedInstallItCanDownloadToOfflineCache() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); var version = "6.0.100"; - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var cachePath = Path.Combine(dotnetRoot, "MockCache"); installer.DownloadToOfflineCache(packInfo, new DirectoryPath(cachePath), false); @@ -384,7 +387,7 @@ public void GivenManagedInstallItCanDownloadToOfflineCache() public void GivenManagedInstallItCanInstallPacksFromOfflineCache() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var version = "6.0.100"; var cachePath = Path.Combine(dotnetRoot, "MockCache"); @@ -412,7 +415,7 @@ public void GivenManagedInstallItCanInstallPacksFromOfflineCache() public void GivenManagedInstallItCanErrorsWhenMissingOfflineCache() { var (dotnetRoot, installer, nugetInstaller) = GetTestInstaller(); - var packInfo = new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); + var packInfo = CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"); var version = "6.0.100"; var cachePath = Path.Combine(dotnetRoot, "MockCache"); diff --git a/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs b/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs index eb9c36dcdc09..bc94e814111d 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockPackWorkloadInstaller.cs @@ -90,7 +90,7 @@ public void DownloadToOfflineCache(PackInfo pack, DirectoryPath cachePath, bool CachePath = cachePath.Value; } - public IEnumerable<(string, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) + public IEnumerable<(WorkloadPackId, string)> GetInstalledPacks(SdkFeatureBand sdkFeatureBand) { return InstalledPacks.Select(pack => (pack.Id, pack.Version)); } diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index 86a3e9782254..362367842190 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -22,10 +22,10 @@ public IEnumerable GetAvailableWorkloads() } public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) => throw new NotImplementedException(); - public IEnumerable GetPacksInWorkload(string workloadId) => throw new NotImplementedException(); - public ISet GetWorkloadSuggestionForMissingPacks(IList packId) => throw new NotImplementedException(); + public IEnumerable GetPacksInWorkload(WorkloadId workloadId) => throw new NotImplementedException(); + public ISet GetWorkloadSuggestionForMissingPacks(IList packId) => throw new NotImplementedException(); public void RefreshWorkloadManifests() => throw new NotImplementedException(); - public WorkloadResolver.PackInfo TryGetPackInfo(string packId) => throw new NotImplementedException(); + public WorkloadResolver.PackInfo TryGetPackInfo(WorkloadPackId packId) => throw new NotImplementedException(); public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) => throw new NotImplementedException(); public string GetManifestVersion(string manifestId) => throw new NotImplementedException(); public IDictionary GetInstalledManifests() => throw new NotImplementedException(); diff --git a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs index 793b410b543a..777e43b901db 100644 --- a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs +++ b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs @@ -124,8 +124,8 @@ public void GivenWorkloadUpdateAcrossFeatureBandsItUpdatesPacks() var sdkFeatureVersion = "6.0.100"; var installingWorkload = "simple-workload"; var workloadPacks = new List() { - new PackInfo("mock-pack-1", "1.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "mock-pack-1", "1.0.0"), "mock-pack-1"), - new PackInfo("mock-pack-2", "2.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "mock-pack-2", "2.0.0"), "mock-pack-2") + CreatePackInfo("mock-pack-1", "1.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "mock-pack-1", "1.0.0"), "mock-pack-1"), + CreatePackInfo("mock-pack-2", "2.0.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "mock-pack-2", "2.0.0"), "mock-pack-2") }; // Lay out workload installs for a previous feature band @@ -159,6 +159,8 @@ public void GivenWorkloadUpdateAcrossFeatureBandsItUpdatesPacks() .Should().BeTrue(because: "Workload install record should be present for current feature band"); } + static PackInfo CreatePackInfo(string id, string version, WorkloadPackKind kind, string path, string resolvedPackageId) => new(new WorkloadPackId(id), version, kind, path, resolvedPackageId); + [Fact] public void GivenWorkloadUpdateItUpdatesOutOfDatePacks() { @@ -170,7 +172,7 @@ public void GivenWorkloadUpdateItUpdatesOutOfDatePacks() installer.GarbageCollectionCalled.Should().BeTrue(); installer.CachePath.Should().BeNull(); installer.InstalledPacks.Count.Should().Be(8); - installer.InstalledPacks.Where(pack => pack.Id.Contains("Android")).Count().Should().Be(8); + installer.InstalledPacks.Where(pack => pack.Id.ToString().Contains("Android")).Count().Should().Be(8); } [Fact] @@ -182,7 +184,7 @@ public void GivenWorkloadUpdateItRollsBackOnFailedUpdate() var exceptionThrown = Assert.Throws(() => command.Execute()); exceptionThrown.Message.Should().Contain("Failing pack: Xamarin.Android.Framework"); var expectedPacks = mockWorkloadIds - .SelectMany(workloadId => workloadResolver.GetPacksInWorkload(workloadId.ToString())) + .SelectMany(workloadId => workloadResolver.GetPacksInWorkload(workloadId)) .Distinct() .Select(packId => workloadResolver.TryGetPackInfo(packId)) .Where(pack => pack != null); @@ -222,7 +224,7 @@ public void GivenWorkloadUpdateItCanInstallFromOfflineCache() installer.GarbageCollectionCalled.Should().BeTrue(); installer.CachePath.Should().Contain(cachePath); installer.InstalledPacks.Count.Should().Be(8); - installer.InstalledPacks.Where(pack => pack.Id.Contains("Android")).Count().Should().Be(8); + installer.InstalledPacks.Where(pack => pack.Id.ToString().Contains("Android")).Count().Should().Be(8); nugetDownloader.DownloadCallParams.Count().Should().Be(0); } @@ -310,8 +312,8 @@ public void GivenPrintRollbackDefinitionItIncludesAllInstalledManifests() var testDirectory = _testAssetsManager.CreateTestDirectory(testName: testName).Path; var dotnetRoot = Path.Combine(testDirectory, "dotnet"); var installedPacks = new PackInfo[] { - new PackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), - new PackInfo("Xamarin.Android.Framework", "8.2.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.2.0"), "Xamarin.Android.Framework") + CreatePackInfo("Xamarin.Android.Sdk", "8.4.7", WorkloadPackKind.Sdk, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Sdk", "8.4.7"), "Xamarin.Android.Sdk"), + CreatePackInfo("Xamarin.Android.Framework", "8.2.0", WorkloadPackKind.Framework, Path.Combine(dotnetRoot, "packs", "Xamarin.Android.Framework", "8.2.0"), "Xamarin.Android.Framework") }; var installer = includeInstalledPacks ? new MockPackWorkloadInstaller(failingWorkload, failingPack, installedWorkloads: installedWorkloads, installedPacks: installedPacks) : From a6cd134e68b805057b53520577389f4522e539d9 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 15:38:30 -0400 Subject: [PATCH 11/26] Disable workload redirects for now We are not fully certain that they are transparent and that they won't cause unintended knock-on effects. --- .../WorkloadManifestReader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs index 5b5f2b99973f..fe89710c9b20 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestReader.cs @@ -463,7 +463,8 @@ private static BaseWorkloadDefinition ReadWorkloadDefinition(WorkloadId id, ref { throw new WorkloadManifestFormatException(Strings.RedirectWorkloadHasOtherKeys, id); } - return new WorkloadRedirect (id, replacementId); + throw new NotImplementedException("Workload redirects are not yet fully implemented"); + //return new WorkloadRedirect (id, replacementId); } var isAbstract = isAbstractOrNull ?? false; if (!isAbstract && kind == WorkloadDefinitionKind.Dev && string.IsNullOrEmpty (description)) From 0254d9586088745e05c1e84cbfa58ba394103e9f Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 22:38:47 -0400 Subject: [PATCH 12/26] Improve WorkloadResolver.GetPacksInWorkload * Better error for missing base workload * Now returns information about where the pack was referenced so better errors can be provided * Factored out a helper for enumerating base workloads --- .../WorkloadResolver.cs | 73 ++++++++++++------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 143587616f3d..ca99f9606cbf 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -336,7 +336,7 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) if (workload.Extends?.Count > 0) { - return GetPacksInWorkload(workload); + return GetPacksInWorkload(workload, value.manifest).Select(p => p.packId); } #nullable disable @@ -344,42 +344,61 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) #nullable restore } - internal IEnumerable GetPacksInWorkload(WorkloadDefinition workload) + private IEnumerable<(WorkloadDefinition workload, WorkloadManifest workloadManifest)> EnumerateWorkloadWithExtends(WorkloadDefinition workload, WorkloadManifest manifest) { - var dedup = new HashSet(); + HashSet? dedup = null; - IEnumerable ExpandPacks (WorkloadId workloadId) + IEnumerable<(WorkloadDefinition workload, WorkloadManifest workloadManifest)> EnumerateWorkloadWithExtendsRec(WorkloadDefinition workload, WorkloadManifest manifest) { - if (!(_workloads.TryGetValue (workloadId) is (WorkloadDefinition workloadInfo, _))) + yield return (workload, manifest); + + if (workload.Extends == null || workload.Extends.Count == 0) { - // inconsistent manifest - throw new Exception("Workload not found"); + yield break; } - if (workloadInfo.Packs != null && workloadInfo.Packs.Count > 0) + dedup ??= new HashSet { workload.Id }; + + foreach (var baseWorkloadId in workload.Extends) { - foreach (var p in workloadInfo.Packs) + if (!dedup.Add(baseWorkloadId)) + { + continue; + } + + if (_workloads.TryGetValue(baseWorkloadId) is not (WorkloadDefinition baseWorkload, WorkloadManifest baseWorkloadManifest)) + { + throw new WorkloadManifestCompositionException($"Could not find workload '{baseWorkloadId}' extended by workload '{workload.Id}' in manifest '{manifest.Id}' ({manifest.InformationalPath})"); + } + + // the workload's ID may not match the value we looked up if it's a redirect + if (baseWorkloadId != baseWorkload.Id && !dedup.Add(baseWorkload.Id)) + { + continue; + } + + foreach (var enumeratedbaseWorkload in EnumerateWorkloadWithExtendsRec(baseWorkload, baseWorkloadManifest)) { - yield return p; + yield return enumeratedbaseWorkload; } } + } + + return EnumerateWorkloadWithExtendsRec(workload, manifest); + } - if (workloadInfo.Extends != null && workloadInfo.Extends.Count > 0) + internal IEnumerable<(WorkloadPackId packId, WorkloadDefinition referencingWorkload, WorkloadManifest workloadDefinedIn)> GetPacksInWorkload(WorkloadDefinition workload, WorkloadManifest manifest) + { + foreach((WorkloadDefinition w, WorkloadManifest m) in EnumerateWorkloadWithExtends(workload, manifest)) + { + if (w.Packs != null && w.Packs.Count > 0) { - foreach (var e in workloadInfo.Extends) + foreach (var p in w.Packs) { - if (dedup.Add(e)) - { - foreach (var ep in ExpandPacks(e)) - { - yield return ep; - } - } + yield return (p, w, m); } } } - - return ExpandPacks(workload.Id); } /// @@ -416,7 +435,7 @@ IEnumerable ExpandPacks (WorkloadId workloadId) public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) { var requestedPacks = new HashSet(packIds); - var expandedWorkloads = _workloads.Select(w => (w.Key, new HashSet(GetPacksInWorkload(w.Value.workload)))); + var expandedWorkloads = _workloads.Select(w => (w.Value.workload.Id, new HashSet(GetPacksInWorkload(w.Value.workload, w.Value.manifest).Select(p => p.packId)))); var finder = new WorkloadSuggestionFinder(GetInstalledPacks(), requestedPacks, expandedWorkloads); return new HashSet @@ -444,14 +463,14 @@ public IEnumerable GetAvailableWorkloads() /// public IEnumerable GetUpdatedWorkloads(WorkloadResolver advertisingManifestResolver, IEnumerable installedWorkloads) { - foreach(var workloadId in installedWorkloads) + foreach (var workloadId in installedWorkloads) { - var existingWorkload = _workloads[workloadId].workload; - var existingPacks = GetPacksInWorkload(existingWorkload).ToHashSet(); + var existingWorkload = _workloads[workloadId]; + var existingPacks = GetPacksInWorkload(existingWorkload.workload, existingWorkload.manifest).Select(p => p.packId).ToHashSet(); var updatedWorkload = advertisingManifestResolver._workloads[workloadId].workload; - var updatedPacks = advertisingManifestResolver.GetPacksInWorkload(updatedWorkload); + var updatedPacks = advertisingManifestResolver.GetPacksInWorkload(existingWorkload.workload, existingWorkload.manifest).Select(p => p.packId); - if (!existingPacks.SetEquals(updatedPacks) || existingPacks.Any(p=> PackHasChanged(_packs[p].pack, advertisingManifestResolver._packs[p].pack))) + if (!existingPacks.SetEquals(updatedPacks) || existingPacks.Any(p => PackHasChanged(_packs[p].pack, advertisingManifestResolver._packs[p].pack))) { yield return workloadId; } From 15d527ff753ea5648abacddfda7473292fb47283 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 22:23:53 -0400 Subject: [PATCH 13/26] Fix available workloads returned by resolver Platform checks should take restrictions on base workloads into account, as clarified in https://github.com/dotnet/designs/pull/230. This means that the CLI can no longer trivially display the RIDs for the platforms on which the workloads are available. This could be added back in future using the RID graph to coalesce values, but would probably need additional work to ensure the values were user friendly. The resolver no longer returns workload definitions. The ensures clients use the resolver's APIs that work on the composed manifest data. Having all code that deals with manifest data direct in a central location helps keep behaviour consistent. It also does not be return abstract or empty workloads as these cannot be installed. --- .../search/WorkloadSearchCommand.cs | 8 ++--- .../update/WorkloadUpdateCommand.cs | 2 +- .../IWorkloadResolver.cs | 2 +- .../WorkloadResolver.cs | 31 ++++++++++++------- .../GivenDotnetWorkloadSearch.cs | 31 ++++++------------- .../MockWorkloadResolver.cs | 9 ++---- 6 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs index e9783d081dad..de6bbbbf7088 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/search/WorkloadSearchCommand.cs @@ -39,7 +39,7 @@ public WorkloadSearchCommand( public override int Execute() { - IEnumerable availableWorkloads = _workloadResolver.GetAvailableWorkloads() + IEnumerable availableWorkloads = _workloadResolver.GetAvailableWorkloads() .OrderBy(workload => workload.Id); if (!string.IsNullOrEmpty(_workloadIdStub)) @@ -47,13 +47,9 @@ public override int Execute() availableWorkloads = availableWorkloads.Where(workload => workload.Id.ToString().Contains(_workloadIdStub, StringComparison.OrdinalIgnoreCase)); } - var table = new PrintableTable(); + var table = new PrintableTable(); table.AddColumn(LocalizableStrings.WorkloadIdColumnName, workload => workload.Id.ToString()); table.AddColumn(LocalizableStrings.DescriptionColumnName, workload => workload.Description); - if (_verbosity.VerbosityIsDetailedOrDiagnostic()) - { - table.AddColumn(LocalizableStrings.PlatformColumnName, workload => workload.Platforms == null ? string.Empty : string.Join(" ", workload.Platforms)); - } _reporter.WriteLine(); table.PrintRows(availableWorkloads, l => _reporter.WriteLine(l)); diff --git a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs index 80d038b3e7a6..e3b1e85babd2 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/update/WorkloadUpdateCommand.cs @@ -127,7 +127,7 @@ public override int Execute() } else if (_printRollbackDefinitionOnly) { - var manifests = _workloadResolver.GetInstalledManifests(); + var manifests = _workloadResolver.GetInstalledManifests().ToDictionary(m => m.Id, m => m.Version, StringComparer.OrdinalIgnoreCase); _reporter.WriteLine("==workloadRollbackDefinitionJsonOutputStart=="); _reporter.WriteLine(JsonSerializer.Serialize(manifests)); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index a95e24a53c4a..7fcbcab2dfb4 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -10,7 +10,7 @@ public interface IWorkloadResolver IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind); IEnumerable GetPacksInWorkload(WorkloadId workloadId); ISet GetWorkloadSuggestionForMissingPacks(IList packId); - IEnumerable GetAvailableWorkloads(); + IEnumerable GetAvailableWorkloads(); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); IDictionary GetInstalledManifests(); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index ca99f9606cbf..01769a2ac60e 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -445,13 +445,19 @@ public ISet GetWorkloadSuggestionForMissingPacks(IList - /// Returns the list of workloads defined by the manifests on disk + /// Returns the list of workloads available (installed or not) on the current platform, defined by the manifests on disk /// - public IEnumerable GetAvailableWorkloads() + public IEnumerable GetAvailableWorkloads() + => GetAvailableWorkloadDefinitions().Select(w => new WorkloadInfo(w.workload.Id, w.workload.Description)); + + private IEnumerable<(WorkloadDefinition workload, WorkloadManifest manifest)> GetAvailableWorkloadDefinitions() { - foreach ((WorkloadId _, (WorkloadDefinition workload, WorkloadManifest _)) in _workloads) + foreach ((WorkloadId _, (WorkloadDefinition workload, WorkloadManifest manifest)) in _workloads) { - yield return workload; + if (!workload.IsAbstract && IsWorkloadPlatformCompatible(workload, manifest) && !IsWorkloadImplicitlyAbstract(workload, manifest)) + { + yield return (workload, manifest); + } } } @@ -577,18 +583,19 @@ public WorkloadInfo GetWorkloadInfo(WorkloadId WorkloadId) public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) { - var workloadDef = GetAvailableWorkloads().FirstOrDefault(workload => workload.Id.ToString().Equals(workloadId.ToString())); - if (workloadDef == null) + if (_workloads.TryGetValue(workloadId) is not (WorkloadDefinition workload, WorkloadManifest manifest)) { - throw new Exception("Workload not found"); + throw new ArgumentException($"Workload '{workloadId}' not found", nameof(workloadId)); } - if (workloadDef.Platforms == null) - { - return true; - } - return workloadDef.Platforms.Any(supportedPlatform => _currentRuntimeIdentifiers.Contains(supportedPlatform)); + return IsWorkloadPlatformCompatible(workload, manifest); } + private bool IsWorkloadPlatformCompatible(WorkloadDefinition workload, WorkloadManifest manifest) + => EnumerateWorkloadWithExtends(workload, manifest).All(w => + w.workload.Platforms == null || w.workload.Platforms.Count == 0 || w.workload.Platforms.Any(platform => _currentRuntimeIdentifiers.Contains(platform))); + + private bool IsWorkloadImplicitlyAbstract(WorkloadDefinition workload, WorkloadManifest manifest) => !GetPacksInWorkload(workload, manifest).Any(); + public string GetManifestVersion(string manifestId) { (_, Stream manifestStream) = _manifestProvider.GetManifests().FirstOrDefault(manifest => manifest.manifestId.Contains(manifestId)); diff --git a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs index 0458e0e54bf8..c2eb32493fc9 100644 --- a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs +++ b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs @@ -18,21 +18,18 @@ namespace Microsoft.DotNet.Cli.Workload.Search.Tests public class GivenDotnetWorkloadSearch : SdkTest { private readonly BufferedReporter _reporter; - private readonly IEnumerable _availableWorkloads = - new List() + private readonly IEnumerable _availableWorkloads = + new List() { - new WorkloadDefinition(new WorkloadId("mock-workload-1"), false, null, WorkloadDefinitionKind.Dev, new List(), - new List(), new List()), - new WorkloadDefinition(new WorkloadId("mock-workload-2"), false, string.Empty, WorkloadDefinitionKind.Build, null, - new List(), new List() { "platform1", "platform2" }), - new WorkloadDefinition(new WorkloadId("mock-workload-3"), true, "Fake description 1", WorkloadDefinitionKind.Dev, - new List() { new WorkloadId("mock-workload-2") }, new List(), new List()), - new WorkloadDefinition(new WorkloadId("fake-workload-1"), true, null, WorkloadDefinitionKind.Build, - new List(), new List(), null), - new WorkloadDefinition(new WorkloadId("fake-workload-2"), false, "Fake description 2", WorkloadDefinitionKind.Dev, null, - new List(), new List()) + CreateWorkloadInfo("mock-workload-1"), + CreateWorkloadInfo("mock-workload-2"), + CreateWorkloadInfo("fake-workload-1"), + CreateWorkloadInfo("fake-workload-2", "Fake description 2") }; + static WorkloadResolver.WorkloadInfo CreateWorkloadInfo(string id, string description = null) + => new WorkloadResolver.WorkloadInfo(new WorkloadId(id), description); + public GivenDotnetWorkloadSearch(ITestOutputHelper log) : base(log) { _reporter = new BufferedReporter(); @@ -43,7 +40,7 @@ public void GivenNoWorkloadsAreInstalledSearchIsEmpty() { _reporter.Clear(); var parseResult = Parser.GetWorkloadsInstance.Parse("dotnet workload search"); - var workloadResolver = new MockWorkloadResolver(new List()); + var workloadResolver = new MockWorkloadResolver(Enumerable.Empty()); var command = new WorkloadSearchCommand(parseResult, _reporter, workloadResolver, "6.0.100"); command.Execute(); @@ -67,10 +64,6 @@ public void GivenNoStubIsProvidedSearchShowsAllWorkloads() { output.Contains(workload.Description).Should().BeTrue(); } - if (workload.Platforms != null && workload.Platforms.Any()) - { - output.Contains(workload.Platforms.First().ToString()).Should().BeFalse(); - } } } @@ -91,10 +84,6 @@ public void GivenDetailedVerbositySearchShowsAllColumns() { output.Contains(workload.Description).Should().BeTrue(); } - if (workload.Platforms != null && workload.Platforms.Any()) - { - output.Contains(workload.Platforms.First().ToString()).Should().BeTrue(); - } } } diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index 362367842190..3d215e97f7b3 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -9,17 +9,14 @@ namespace Microsoft.DotNet.Cli.Workload.Search.Tests { public class MockWorkloadResolver : IWorkloadResolver { - private readonly IEnumerable _availableWorkloads; + private readonly IEnumerable _availableWorkloads; - public MockWorkloadResolver(IEnumerable availableWorkloads) + public MockWorkloadResolver(IEnumerable availableWorkloads) { _availableWorkloads = availableWorkloads; } - public IEnumerable GetAvailableWorkloads() - { - return _availableWorkloads; - } + public IEnumerable GetAvailableWorkloads() => _availableWorkloads; public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) => throw new NotImplementedException(); public IEnumerable GetPacksInWorkload(WorkloadId workloadId) => throw new NotImplementedException(); From 619304d8714099e5cf6f00dd1cd45195b54c53f1 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 22:25:40 -0400 Subject: [PATCH 14/26] Include workload ID in exception when resolver cannot find it --- .../WorkloadResolver.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 01769a2ac60e..467435f9b1a9 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -572,13 +572,13 @@ public WorkloadInfo(WorkloadId id, string? description) public string? Description { get; } } - public WorkloadInfo GetWorkloadInfo(WorkloadId WorkloadId) + public WorkloadInfo GetWorkloadInfo(WorkloadId workloadId) { - if (_workloads.TryGetValue(WorkloadId) is (WorkloadDefinition workload, _)) + if (_workloads.TryGetValue(workloadId) is not (WorkloadDefinition workload, _)) { - return new WorkloadInfo(workload.Id, workload.Description); + throw new ArgumentException($"Workload '{workloadId}' not found", nameof(workloadId)); } - throw new Exception("Workload not found"); + return new WorkloadInfo(workload.Id, workload.Description); } public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) From d867fef3540c3e125fb213037921dc686dd67435 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 22:31:49 -0400 Subject: [PATCH 15/26] Hide WorkloadResolver.GetPackPath in favor of ResolvePackPath Ensures aliased pack IDs are always resolved --- .../WorkloadResolver.cs | 96 ++++++++++--------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 467435f9b1a9..ffa5fcf116d3 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -199,13 +199,9 @@ public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind ki continue; } - if (ResolveId(pack) is WorkloadPackId resolvedPackageId) + if (ResolvePackPath(pack, out WorkloadPackId resolvedPackageId, out bool isInstalled) is string aliasedPath && isInstalled) { - var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out bool isInstalled); - if (isInstalled) - { - yield return CreatePackInfo(pack, aliasedPath, resolvedPackageId); - } + yield return CreatePackInfo(pack, aliasedPath, resolvedPackageId); } } } @@ -251,57 +247,64 @@ internal void ReplaceFilesystemChecksForTest(Func fileExists, Func /// Whether the pack is installed /// The path to the pack, or null if the pack is not available on the host platform. private string? ResolvePackPath(WorkloadPack pack, out bool isInstalled) + => ResolvePackPath(pack, out _, out isInstalled); + + private string? ResolvePackPath( + WorkloadPack pack, + out WorkloadPackId resolvedId, + out bool isInstalled) { - if (ResolveId(pack) is WorkloadPackId resolvedId) + resolvedId = ResolveId(pack) ?? default; + if (resolvedId is WorkloadPackId resolved) { - return GetPackPath(_dotnetRootPaths, resolvedId, pack.Version, pack.Kind, out isInstalled); + return GetPackPath(resolved, pack.Version, pack.Kind, out isInstalled); } isInstalled = false; return null; - } - private string GetPackPath(string [] dotnetRootPaths, WorkloadPackId packageId, string packageVersion, WorkloadPackKind kind, out bool isInstalled) - { - isInstalled = false; - string packPath = ""; - bool isFile; - foreach (var rootPath in dotnetRootPaths) + string GetPackPath(WorkloadPackId resolvedPackageId, string packageVersion, WorkloadPackKind kind, out bool isInstalled) { - switch (kind) + isInstalled = false; + string packPath = ""; + bool isFile; + foreach (var rootPath in _dotnetRootPaths) { - case WorkloadPackKind.Framework: - case WorkloadPackKind.Sdk: - packPath = Path.Combine(rootPath, "packs", packageId.ToString(), packageVersion); - isFile = false; - break; - case WorkloadPackKind.Template: - packPath = Path.Combine(rootPath, "template-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); - isFile = true; - break; - case WorkloadPackKind.Library: - packPath = Path.Combine(rootPath, "library-packs", packageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); - isFile = true; - break; - case WorkloadPackKind.Tool: - packPath = Path.Combine(rootPath, "tool-packs", packageId.ToString(), packageVersion); - isFile = false; - break; - default: - throw new ArgumentException($"The package kind '{kind}' is not known", nameof(kind)); - } + switch (kind) + { + case WorkloadPackKind.Framework: + case WorkloadPackKind.Sdk: + packPath = Path.Combine(rootPath, "packs", resolvedPackageId.ToString(), packageVersion); + isFile = false; + break; + case WorkloadPackKind.Template: + packPath = Path.Combine(rootPath, "template-packs", resolvedPackageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); + isFile = true; + break; + case WorkloadPackKind.Library: + packPath = Path.Combine(rootPath, "library-packs", resolvedPackageId.GetNuGetCanonicalId() + "." + packageVersion.ToLowerInvariant() + ".nupkg"); + isFile = true; + break; + case WorkloadPackKind.Tool: + packPath = Path.Combine(rootPath, "tool-packs", resolvedPackageId.ToString(), packageVersion); + isFile = false; + break; + default: + throw new ArgumentException($"The package kind '{kind}' is not known", nameof(kind)); + } - //can we do a more robust check than directory.exists? - isInstalled = isFile ? - _fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath) : - _directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath); ; + //can we do a more robust check than directory.exists? + isInstalled = isFile ? + _fileExistOverride?.Invoke(packPath) ?? File.Exists(packPath) : + _directoryExistOverride?.Invoke(packPath) ?? Directory.Exists(packPath); ; - if (isInstalled) - { - break; + if (isInstalled) + { + break; + } } + return packPath; } - return packPath; } /// @@ -414,11 +417,10 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) throw new ArgumentException($"'{nameof(packId)}' cannot be null or empty", nameof(packId)); } - if (_packs.TryGetValue(new WorkloadPackId (packId)) is (WorkloadPack pack, _)) + if (_packs.TryGetValue(packId) is (WorkloadPack pack, _)) { - if (ResolveId(pack) is WorkloadPackId resolvedPackageId) + if (ResolvePackPath(pack, out WorkloadPackId resolvedPackageId, out bool isInstalled) is string aliasedPath) { - var aliasedPath = GetPackPath(_dotnetRootPaths, resolvedPackageId, pack.Version, pack.Kind, out _); return CreatePackInfo(pack, aliasedPath, resolvedPackageId); } } From 536f67c11b526ec1f169b1f29dc8c477932f0218 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 1 Jul 2021 22:39:38 -0400 Subject: [PATCH 16/26] When suggesting workloads, only consider available workloads --- .../WorkloadResolver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index ffa5fcf116d3..7d5ac0444809 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -437,7 +437,8 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) { var requestedPacks = new HashSet(packIds); - var expandedWorkloads = _workloads.Select(w => (w.Value.workload.Id, new HashSet(GetPacksInWorkload(w.Value.workload, w.Value.manifest).Select(p => p.packId)))); + var availableWorkloads = GetAvailableWorkloadDefinitions(); + var expandedWorkloads = availableWorkloads.Select(w => (w.workload.Id, new HashSet(GetPacksInWorkload(w.workload, w.manifest).Select(p => p.packId)))); var finder = new WorkloadSuggestionFinder(GetInstalledPacks(), requestedPacks, expandedWorkloads); return new HashSet From e4b36e3183d5c5182bfe474c47264cc64bee450a Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 12 Jul 2021 21:43:12 -0400 Subject: [PATCH 17/26] Localize remaining workload composition errors Also improves errors from unresolved redirects, and handles redirects in a second pass so they're not dependent on order of manifests and definitions --- .../Strings.resx | 25 +++++- .../WorkloadManifestFormatException.cs | 6 +- .../WorkloadResolver.cs | 90 +++++++++++-------- .../xlf/Strings.cs.xlf | 41 ++++++++- .../xlf/Strings.de.xlf | 41 ++++++++- .../xlf/Strings.es.xlf | 41 ++++++++- .../xlf/Strings.fr.xlf | 41 ++++++++- .../xlf/Strings.it.xlf | 41 ++++++++- .../xlf/Strings.ja.xlf | 41 ++++++++- .../xlf/Strings.ko.xlf | 41 ++++++++- .../xlf/Strings.pl.xlf | 41 ++++++++- .../xlf/Strings.pt-BR.xlf | 41 ++++++++- .../xlf/Strings.ru.xlf | 41 ++++++++- .../xlf/Strings.tr.xlf | 41 ++++++++- .../xlf/Strings.zh-Hans.xlf | 41 ++++++++- .../xlf/Strings.zh-Hant.xlf | 41 ++++++++- 16 files changed, 573 insertions(+), 81 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx index 0bbdbf68185d..cadeb62d78f4 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx @@ -162,7 +162,28 @@ Redirect workload '{0}' has keys other than 'redirect-to' - - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] \ No newline at end of file diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs index fde8901805a0..bfe1039df6a0 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadManifestFormatException.cs @@ -10,7 +10,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader class WorkloadManifestFormatException: WorkloadManifestException { public WorkloadManifestFormatException() { } - public WorkloadManifestFormatException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } + public WorkloadManifestFormatException(string messageFormat, params object?[] args) : base(messageFormat, args) { } public WorkloadManifestFormatException(string message) : base(message) { } public WorkloadManifestFormatException(string message, Exception inner) : base(message, inner) { } protected WorkloadManifestFormatException(SerializationInfo info, StreamingContext context) : base(info, context) { } @@ -20,7 +20,7 @@ protected WorkloadManifestFormatException(SerializationInfo info, StreamingConte class WorkloadManifestCompositionException: WorkloadManifestException { public WorkloadManifestCompositionException() { } - public WorkloadManifestCompositionException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } + public WorkloadManifestCompositionException(string messageFormat, params object?[] args) : base(messageFormat, args) { } public WorkloadManifestCompositionException(string message) : base(message) { } public WorkloadManifestCompositionException(string message, Exception inner) : base(message, inner) { } protected WorkloadManifestCompositionException(SerializationInfo info, StreamingContext context) : base(info, context) { } @@ -30,7 +30,7 @@ protected WorkloadManifestCompositionException(SerializationInfo info, Streaming abstract class WorkloadManifestException: Exception { protected WorkloadManifestException() { } - protected WorkloadManifestException(string messageFormat, params object[] args) : base(string.Format (messageFormat, args)) { } + protected WorkloadManifestException(string messageFormat, params object?[] args) : base(string.Format (messageFormat, args)) { } protected WorkloadManifestException(string message) : base(message) { } protected WorkloadManifestException(string message, Exception inner) : base(message, inner) { } protected WorkloadManifestException(SerializationInfo info, StreamingContext context) : base(info, context) { } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 7d5ac0444809..d003198f7449 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -17,12 +17,12 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader /// public class WorkloadResolver : IWorkloadResolver { - private readonly Dictionary _manifests = new Dictionary(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _workloads = new Dictionary(); - private readonly Dictionary _packs = new Dictionary(); + private readonly Dictionary _manifests = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _workloads = new(); + private readonly Dictionary _packs = new(); private IWorkloadManifestProvider? _manifestProvider; private string[] _currentRuntimeIdentifiers; - private readonly string [] _dotnetRootPaths; + private readonly string[] _dotnetRootPaths; private Func? _fileExistOverride; private Func? _directoryExistOverride; @@ -61,8 +61,8 @@ public static WorkloadResolver CreateForTests(IWorkloadManifestProvider manifest /// /// Creates a resolver by composing all the manifests from the provider. /// - private WorkloadResolver(IWorkloadManifestProvider manifestProvider, string [] dotnetRootPaths, string [] currentRuntimeIdentifiers) - : this (dotnetRootPaths, currentRuntimeIdentifiers) + private WorkloadResolver(IWorkloadManifestProvider manifestProvider, string[] dotnetRootPaths, string[] currentRuntimeIdentifiers) + : this(dotnetRootPaths, currentRuntimeIdentifiers) { _manifestProvider = manifestProvider; @@ -99,7 +99,8 @@ private void LoadManifestsFromProvider(IWorkloadManifestProvider manifestProvide var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream, informationalPath); if (!_manifests.TryAdd(manifestId, manifest)) { - throw new WorkloadManifestCompositionException($"Duplicate manifest '{manifestId}' from provider {manifestProvider}"); + var existingManifest = _manifests[manifestId]; + throw new WorkloadManifestCompositionException(Strings.DuplicateManifestID, manifestProvider.GetType().FullName, manifestId, informationalPath, existingManifest.InformationalPath); } } } @@ -110,6 +111,8 @@ private void ComposeWorkloadManifests() _workloads.Clear(); _packs.Clear(); + Dictionary? redirects = null; + foreach (var manifest in _manifests.Values) { if (manifest.DependsOnManifests != null) @@ -120,64 +123,77 @@ private void ComposeWorkloadManifests() { if (FXVersion.Compare(dependency.Value, resolvedDependency.ParsedVersion) > 0) { - throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}' ({manifest.InformationalPath}): requires '{dependency.Key}' version at least {dependency.Value} but found {resolvedDependency.Version}"); + throw new WorkloadManifestCompositionException(Strings.ManifestDependencyVersionTooLow, dependency.Key, dependency.Value, resolvedDependency.Version, manifest.Id, manifest.InformationalPath); } } else { - throw new WorkloadManifestCompositionException($"Inconsistency in workload manifest '{manifest.Id}' ({manifest.InformationalPath}): missing dependency '{dependency.Key}'"); - } + throw new WorkloadManifestCompositionException(Strings.ManifestDependencyMissing, dependency.Key, manifest.Id, manifest.InformationalPath); + } } } - HashSet? redirects = null; foreach (var workload in manifest.Workloads) { if (workload.Value is WorkloadRedirect redirect) { - (redirects ??= new HashSet()).Add(redirect); + (redirects ??= new()).Add(redirect.Id, (redirect, manifest)); } else { if (!_workloads.TryAdd(workload.Key, ((WorkloadDefinition)workload.Value, manifest))) { WorkloadManifest conflictingManifest = _workloads[workload.Key].manifest; - throw new WorkloadManifestCompositionException($"Workload '{workload.Key}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); + throw new WorkloadManifestCompositionException(Strings.ConflictingWorkloadDefinition, workload.Key, manifest.Id, manifest.InformationalPath, conflictingManifest.Id, conflictingManifest.InformationalPath); } } } - // resolve redirects upfront so they are transparent to the rest of the code - // the _workloads dictionary maps redirected ids directly to the replacement - if (redirects != null) + foreach (var pack in manifest.Packs) { - // handle multi-levels redirects via multiple resolve passes, bottom-up - while (redirects.RemoveWhere(redirect => + if (!_packs.TryAdd(pack.Key, (pack.Value, manifest))) { - if (_workloads.TryGetValue(redirect.ReplaceWith, out var replacement)) - { - if (!_workloads.TryAdd(redirect.Id, replacement)) - { - WorkloadManifest conflictingManifest = _workloads[redirect.Id].manifest; - throw new WorkloadManifestCompositionException($"Workload '{redirect.Id}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); - } - return true; - } - return false; - }) > 0) { }; + WorkloadManifest conflictingManifest = _packs[pack.Key].manifest; + throw new WorkloadManifestCompositionException(Strings.ConflictingWorkloadPack, pack.Key, manifest.Id, manifest.InformationalPath, conflictingManifest.Id, conflictingManifest.InformationalPath); + } + } + } - if (redirects.Count > 0) + // resolve redirects upfront so they are transparent to the rest of the code + // the _workloads dictionary maps redirected ids directly to the replacement + if (redirects != null) + { + // handle multi-levels redirects via multiple resolve passes, bottom-up i.e. iteratively try + // to resolve unresolved redirects to resolved workloads/redirects until we stop making progress + var unresolvedRedirects = new HashSet(redirects.Keys); + while (unresolvedRedirects.RemoveWhere(redirectId => + { + (var redirect, var manifest) = redirects[redirectId]; + + if (_workloads.TryGetValue(redirect.ReplaceWith, out var replacement)) { - throw new WorkloadManifestCompositionException(Strings.UnresolvedWorkloadRedirects, string.Join("\", \"", redirects.Select(r => r.Id.ToString()))); + if (!_workloads.TryAdd(redirect.Id, replacement)) + { + WorkloadManifest conflictingManifest = _workloads[redirect.Id].manifest; + throw new WorkloadManifestCompositionException(Strings.ConflictingWorkloadDefinition, redirect.Id, manifest.Id, manifest.InformationalPath, conflictingManifest.Id, conflictingManifest.InformationalPath); + } + return true; } - } + return false; + }) > 0) { }; - foreach (var pack in manifest.Packs) + if (unresolvedRedirects.Count > 0) { - if (!_packs.TryAdd(pack.Key, (pack.Value, manifest))) + // if one or more of them doesn't resolve into another redirect, it's an actual unresolved redirect + var unresolved = unresolvedRedirects.Select(ur => redirects[ur]).Where(ur => !redirects.ContainsKey(ur.redirect.ReplaceWith)).FirstOrDefault(); + if (unresolved is (WorkloadRedirect redirect, WorkloadManifest manifest)) { - WorkloadManifest conflictingManifest = _packs[pack.Key].manifest; - throw new WorkloadManifestCompositionException($"Workload pack '{pack.Key}' in manifest '{manifest.Id}' ({manifest.InformationalPath}) conflicts with manifest '{conflictingManifest.Id}' ({conflictingManifest.InformationalPath})"); + throw new WorkloadManifestCompositionException(Strings.UnresolvedWorkloadRedirect, redirect.ReplaceWith, redirect.Id, manifest.Id, manifest.InformationalPath); + } + else + { + var cyclic = redirects[unresolvedRedirects.First()]; + throw new WorkloadManifestCompositionException(Strings.CyclicWorkloadRedirect, cyclic.redirect.Id, cyclic.manifest.Id, cyclic.manifest.InformationalPath); } } } @@ -371,7 +387,7 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) if (_workloads.TryGetValue(baseWorkloadId) is not (WorkloadDefinition baseWorkload, WorkloadManifest baseWorkloadManifest)) { - throw new WorkloadManifestCompositionException($"Could not find workload '{baseWorkloadId}' extended by workload '{workload.Id}' in manifest '{manifest.Id}' ({manifest.InformationalPath})"); + throw new WorkloadManifestCompositionException(Strings.MissingBaseWorkload, baseWorkloadId, workload.Id, manifest.Id, manifest.InformationalPath); } // the workload's ID may not match the value we looked up if it's a redirect 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 59a157dec284..62304df730a1 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf @@ -7,11 +7,31 @@ Definice úlohy {0} je konkrétní vývojářská úloha, která ale nemá žádný popis. + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Duplicitní klíč {0} u posunu {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Očekávána logická hodnota u posunu {0} @@ -37,6 +57,21 @@ Dokument předčasně ukončen + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Chybějící nebo neplatná verze manifestu @@ -77,9 +112,9 @@ Neznámý druh sady úloh {0} u posunu {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 6aa7347d4a6e..dde0ff30dec5 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf @@ -7,11 +7,31 @@ Die Workloaddefinition "{0}" ist eine konkrete Entwicklungsworkload, enthält aber keine Beschreibung. + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Doppelter Schlüssel "{0}" bei Offset {1}. + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Boolescher Wert bei Offset {0} erwartet. @@ -37,6 +57,21 @@ Dokument ist unvollständig. + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Manifestversion fehlt oder ist ungültig. @@ -77,9 +112,9 @@ Unbekannte Art des Workloadpakets ({0}) bei Offset {1}. - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 4c4db267767b..88b4346568c0 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf @@ -7,11 +7,31 @@ La definición de la carga de trabajo "{0}" es una carga de trabajo de desarrollo concreta, pero no tiene ninguna descripción. + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Clave "{0}" duplicada en el desplazamiento {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Se esperaba un valor booleano en el desplazamiento {0} @@ -37,6 +57,21 @@ El documento finalizó antes de tiempo + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Falta la versión del manifiesto o no es válida @@ -77,9 +112,9 @@ Tipo de paquete de carga de trabajo "{0}" desconocido en el desplazamiento {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 a3785ebf0e94..9612b88017bc 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf @@ -7,11 +7,31 @@ La définition de charge de travail '{0}' est une charge de travail de développement concrète mais n'a aucune description + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Clé dupliquée '{0}' à l'offset {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Valeur booléenne attendue à l'offset {0} @@ -37,6 +57,21 @@ Fin prématurée du document + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Version manquante ou non valide du manifeste @@ -77,9 +112,9 @@ Genre de pack de charge de travail inconnu '{0}' à l'offset {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 31da602f755b..e1b59b28799b 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf @@ -7,11 +7,31 @@ La definizione del carico di lavoro '{0}' è un carico di lavoro di sviluppo concreto ma non include alcuna descrizione + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Chiave '{0}' duplicata alla posizione di offset {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} È prevista un valore booleano alla posizione di offset {0} @@ -37,6 +57,21 @@ Il documento è stato interrotto prima del completamento + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Versione del manifesto mancante o non valida @@ -77,9 +112,9 @@ Tipo di pacchetto del carico di lavoro '{0}' sconosciuto alla posizione di offset {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 31179702791d..1451665b0c97 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf @@ -7,11 +7,31 @@ ワークロード定義 '{0}' は実在の開発ワークロードですが、説明がありません + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} オフセット {1} のキー '{0}' が重複しています + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} オフセット {0} にはブール値が必要です @@ -37,6 +57,21 @@ ドキュメントが途中で終了しました + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version マニフェストのバージョンがないか、無効です @@ -77,9 +112,9 @@ オフセット {1} に不明なワークロード パックの種類 '{0}' があります - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 3d98adb5472e..69f87c1950d7 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf @@ -7,11 +7,31 @@ Workload definition '{0}' is a concrete dev workload but has no description + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Duplicate key '{0}' at offset {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Expected boolean value at offset {0} @@ -37,6 +57,21 @@ Document ended prematurely + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Missing or invalid manifest version @@ -77,9 +112,9 @@ Unknown workload pack kind '{0}' at offset {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 b664bf148d90..8274977a1a6e 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf @@ -7,11 +7,31 @@ Definicja obciążenia pracą „{0}” jest konkretnym obciążeniem deweloperskim, ale nie ma opisu + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Zduplikowany klucz „{0}” pod przesunięciem {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Oczekiwano wartości logicznej pod przesunięciem {0} @@ -37,6 +57,21 @@ Dokument zakończony przedwcześnie + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Brak wersji manifestu lub jest ona nieprawidłowa @@ -77,9 +112,9 @@ Nieznany rodzaj pakietu obciążenia „{0}” pod przesunięciem {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 16d6a2192caf..a6ecb917a372 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 @@ -7,11 +7,31 @@ A definição de carga de trabalho '{0}' é uma carga de trabalho de desenvolvimento concreta, mas não tem nenhuma descrição + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Chave duplicada '{0}' no deslocamento {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Valor booliano esperado no deslocamento {0} @@ -37,6 +57,21 @@ O documento terminou prematuramente + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Versão do manifesto ausente ou inválida @@ -77,9 +112,9 @@ Tipo de pacote de carga de trabalho '{0}' desconhecido no deslocamento {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 04a06fe54999..7da21b2f024c 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf @@ -7,11 +7,31 @@ Определение рабочей нагрузки "{0}" является конкретной рабочей нагрузкой разработки, но не имеет описания. + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} Повторяющийся ключ "{0}" в смещении {1} + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} Ожидается логическое значение в смещении {0} @@ -37,6 +57,21 @@ Документ завершен преждевременно + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Версия манифеста отсутствует или недопустима @@ -77,9 +112,9 @@ Неизвестный тип пакета рабочей нагрузки "{0}" в смещении {1} - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 eb4c40fa81c7..1d246610b895 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf @@ -7,11 +7,31 @@ '{0}' iş yükü tanımı, somut bir geliştirici iş yükü ancak açıklaması yok + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} {1} uzaklığında yinelenen '{0}' anahtarı + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} {0} uzaklığında boolean değeri bekleniyordu @@ -37,6 +57,21 @@ Belge zamanından önce sonlandırıldı + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version Bildirim sürümü eksik veya geçersiz @@ -77,9 +112,9 @@ {1} uzaklığında bilinmeyen '{0}' iş yükü paketi tipi - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 dac807caebe9..5b8e2db5ea66 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 @@ -7,11 +7,31 @@ 工作负载定义“{0}”是一个具体的开发工作负载,但没有说明 + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} 偏移为 {1} 时的重复键“{0}” + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} 移量为 {0} 时所需的布尔值 @@ -37,6 +57,21 @@ 文档过早结束 + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version 清单版本缺失或无效 @@ -77,9 +112,9 @@ 偏移为 {1} 时的未知工作负载包类型“{0}” - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] 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 3ca30463c9d5..33eeb3c71d86 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 @@ -7,11 +7,31 @@ 工作負載定義 '{0}' 為實體開發工作負載,但沒有任何描述 + + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + + + + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + Cyclic workload redirect '{0}' in manifest '{1}' [{2}] + + Duplicate key '{0}' at offset {1} 位移 {1} 有重複的金鑰 '{0}' + + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] + + Expected boolean value at offset {0} 位移 {0} 有預期的布林值 @@ -37,6 +57,21 @@ 文件已提前結束 + + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}] + + + + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + Workload manifest dependency '{0}' version '{1}' is lower than version '{2}' required by manifest '{3}' [{4}] + + + + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + Could not find workload '{0}' extended by workload '{1}' in manifest '{2}' [{3}] + + Missing or invalid manifest version 缺少資訊清單版本或其無效 @@ -77,9 +112,9 @@ 位移 {1} 有不明的工作負載套件種類 '{0}' - - One or more workload redirects failed to resolve: {0} - One or more workload redirects failed to resolve: {0} + + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] + Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] From d75137c2eb0ac85f2ad6ade989b0c27be9f7bfee Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Tue, 13 Jul 2021 20:51:45 -0400 Subject: [PATCH 18/26] Simplify WorkloadResolver.GetInstalledManifests We now have a collection of the manifests that are loaded, so use that rather than rescanning. This makes it behave correctly for correct for overlay resolvers. Also return an "Info" object to be consistent with other API. We may want to add more information onto this object in future. --- .../IWorkloadResolver.cs | 2 +- .../WorkloadResolver.cs | 34 ++++++------------- .../MockWorkloadResolver.cs | 2 +- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index 7fcbcab2dfb4..da226c390d91 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -13,7 +13,7 @@ public interface IWorkloadResolver IEnumerable GetAvailableWorkloads(); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); - IDictionary GetInstalledManifests(); + IEnumerable GetInstalledManifests(); /// /// Resolve the pack for this resolver's SDK band. diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index d003198f7449..31cb6a375a0f 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -615,34 +615,22 @@ private bool IsWorkloadPlatformCompatible(WorkloadDefinition workload, WorkloadM private bool IsWorkloadImplicitlyAbstract(WorkloadDefinition workload, WorkloadManifest manifest) => !GetPacksInWorkload(workload, manifest).Any(); - public string GetManifestVersion(string manifestId) - { - (_, Stream manifestStream) = _manifestProvider.GetManifests().FirstOrDefault(manifest => manifest.manifestId.Contains(manifestId)); - - if (manifestStream == null) - { - throw new Exception($"Manifest with id {manifestId} does not exist."); - } + public string GetManifestVersion(string manifestId) => + (_manifests.TryGetValue(manifestId, out WorkloadManifest? value)? value : null)?.Version + ?? throw new Exception($"Manifest with id {manifestId} does not exist."); - using (manifestStream) - { - var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); - return manifest.Version; - } - } + public IEnumerable GetInstalledManifests() => _manifests.Select(m => new ManifestInfo(m.Value.Id, m.Value.Version)); - public IDictionary GetInstalledManifests() + public class ManifestInfo { - var manifests = new Dictionary(); - foreach ((string manifestId, Stream manifestStream) in _manifestProvider.GetManifests()) + public ManifestInfo(string id, string version) { - using (manifestStream) - { - var manifest = WorkloadManifestReader.ReadWorkloadManifest(manifestId, manifestStream); - manifests.Add(manifestId, manifest.Version); - } + Id = id; + Version = version; } - return manifests; + + public string Id { get; } + public string Version { get; } } } diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index 3d215e97f7b3..8c7fa4ad427c 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -25,7 +25,7 @@ public MockWorkloadResolver(IEnumerable available public WorkloadResolver.PackInfo TryGetPackInfo(WorkloadPackId packId) => throw new NotImplementedException(); public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) => throw new NotImplementedException(); public string GetManifestVersion(string manifestId) => throw new NotImplementedException(); - public IDictionary GetInstalledManifests() => throw new NotImplementedException(); + public IEnumerable GetInstalledManifests() => throw new NotImplementedException(); public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) => throw new NotImplementedException(); } } From c9d64aa4f7ad70cec9e4e69e1216a86ff8a49572 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 15 Jul 2021 17:52:15 -0400 Subject: [PATCH 19/26] Fix ResolvePackPath returning empty workload pack ids Fallout from the switch from string to id structs --- .../WorkloadResolver.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 31cb6a375a0f..3e9750c4982f 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -270,12 +270,13 @@ internal void ReplaceFilesystemChecksForTest(Func fileExists, Func out WorkloadPackId resolvedId, out bool isInstalled) { - resolvedId = ResolveId(pack) ?? default; - if (resolvedId is WorkloadPackId resolved) + if (ResolveId(pack) is WorkloadPackId resolved) { + resolvedId = resolved; return GetPackPath(resolved, pack.Version, pack.Kind, out isInstalled); } + resolvedId = default; isInstalled = false; return null; From 48720b8fc124017aa75de29af2a2a6092589f012 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Thu, 15 Jul 2021 17:53:53 -0400 Subject: [PATCH 20/26] Check updated composition error messages in workload tests --- .../ManifestTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs index dfc83699e12a..62c0be9a9060 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/ManifestTests.cs @@ -191,7 +191,7 @@ string MakeManifest(string version, params (string id, string version)[] depends }; var missingManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(missingManifestProvider, new[] { fakeRootPath })); - Assert.Contains("missing dependency", missingManifestEx.Message); + Assert.StartsWith("Did not find workload manifest dependency 'BBB' required by manifest 'AAA'", missingManifestEx.Message); var inconsistentManifestProvider = new InMemoryFakeManifestProvider { @@ -202,7 +202,7 @@ string MakeManifest(string version, params (string id, string version)[] depends }; var inconsistentManifestEx = Assert.Throws(() => WorkloadResolver.CreateForTests(inconsistentManifestProvider, new[] { fakeRootPath })); - Assert.Contains("Inconsistency in workload manifest", inconsistentManifestEx.Message); + Assert.StartsWith("Workload manifest dependency 'DDD' version '39.0.0' is lower than version '30.0.0' required by manifest 'BBB'", inconsistentManifestEx.Message); } [Fact] From 0537ca735f887dff79b59e1dc34d02d2f6a84800 Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Sat, 17 Jul 2021 04:06:53 -0400 Subject: [PATCH 21/26] Don't assume missing workload packs can always be satisfied When getting a suggestion for workloads to satisfy missing packs, first determine which cannot be installed on the current machine, and report them with a specific error code NETSDK1178. --- .../IWorkloadResolver.cs | 2 +- .../WorkloadResolver.cs | 32 +++++++++++++---- .../WorkloadSuggestionFinder.cs | 5 +++ src/Tasks/Common/Resources/Strings.resx | 7 +++- src/Tasks/Common/Resources/xlf/Strings.cs.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.de.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.es.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.fr.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.it.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.ja.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.ko.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.pl.xlf | 7 ++++ .../Common/Resources/xlf/Strings.pt-BR.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.ru.xlf | 7 ++++ src/Tasks/Common/Resources/xlf/Strings.tr.xlf | 7 ++++ .../Common/Resources/xlf/Strings.zh-Hans.xlf | 7 ++++ .../Common/Resources/xlf/Strings.zh-Hant.xlf | 7 ++++ .../ShowMissingWorkloads.cs | 35 ++++++++++++------- .../WorkloadSuggestionFinderTests.cs | 35 +++++++++++++------ .../MockWorkloadResolver.cs | 2 +- 20 files changed, 178 insertions(+), 31 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index da226c390d91..7b03e842d3d5 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -9,7 +9,7 @@ public interface IWorkloadResolver { IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind); IEnumerable GetPacksInWorkload(WorkloadId workloadId); - ISet GetWorkloadSuggestionForMissingPacks(IList packId); + ISet? GetWorkloadSuggestionForMissingPacks(IList packId, out ISet unsatisfiablePacks); IEnumerable GetAvailableWorkloads(); bool IsWorkloadPlatformCompatible(WorkloadId workloadId); string GetManifestVersion(string manifestId); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index 3e9750c4982f..d5eee1aaf4c5 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -451,17 +451,37 @@ public IEnumerable GetPacksInWorkload(WorkloadId workloadId) /// /// Used by the MSBuild workload resolver to emit actionable errors /// - public ISet GetWorkloadSuggestionForMissingPacks(IList packIds) + public ISet? GetWorkloadSuggestionForMissingPacks(IList packIds, out ISet unsatisfiablePacks) { var requestedPacks = new HashSet(packIds); var availableWorkloads = GetAvailableWorkloadDefinitions(); - var expandedWorkloads = availableWorkloads.Select(w => (w.workload.Id, new HashSet(GetPacksInWorkload(w.workload, w.manifest).Select(p => p.packId)))); + + List<(WorkloadId Id, HashSet Packs)>? expandedWorkloads = availableWorkloads + .Select(w => (w.workload.Id, new HashSet(GetPacksInWorkload(w.workload, w.manifest).Select(p => p.packId)))) + .ToList(); + + var unsatisfiable = requestedPacks + .Where(p => !expandedWorkloads.Any(w => w.Packs.Contains(p))) + .ToHashSet(); + + unsatisfiablePacks = unsatisfiable; + + requestedPacks.ExceptWith(unsatisfiable); + if (requestedPacks.Count == 0) + { + return null; + } + + expandedWorkloads = expandedWorkloads + .Where(w => w.Packs.Any(p => requestedPacks.Contains(p))) + .ToList(); + var finder = new WorkloadSuggestionFinder(GetInstalledPacks(), requestedPacks, expandedWorkloads); - return new HashSet - ( - finder.GetBestSuggestion().Workloads.Select(s => new WorkloadInfo(s, _workloads[s].workload.Description)) - ); + return finder.GetBestSuggestion() + .Workloads + .Select(s => new WorkloadInfo(s, _workloads[s].workload.Description)) + .ToHashSet(); } /// diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs index 2f971885eee4..89e4e568e28c 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadSuggestionFinder.cs @@ -30,6 +30,11 @@ public WorkloadSuggestionFinder(HashSet installedPacks, HashSet< return new WorkloadSuggestion(c.Workloads, extraPacks); }) .ToList(); + + if (UnsortedSuggestions.Count == 0) + { + throw new ArgumentException("requestedPacks may only contain packs that exist in expandedWorkloads", "requestedPacks"); + } } /// diff --git a/src/Tasks/Common/Resources/Strings.resx b/src/Tasks/Common/Resources/Strings.resx index 28b56ac220b8..08673edb1db0 100644 --- a/src/Tasks/Common/Resources/Strings.resx +++ b/src/Tasks/Common/Resources/Strings.resx @@ -815,4 +815,9 @@ To install these workloads, run the following command: {1} NETSDK1177: Failed to sign apphost with error code {1}: {0} {StrBegin="NETSDK1177: "} - + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + + \ No newline at end of file diff --git a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf index 0cc433d6e2d1..c11134bceda8 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.cs.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.cs.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1149: Závislý modul byl zkompilován novější verzí Microsoft.Windows.SDK.NET.dll. Pro odkazování na tento modul prosím přejděte na novější verzi .NET SDK. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.de.xlf b/src/Tasks/Common/Resources/xlf/Strings.de.xlf index b9d33b6d1a09..6865fa914d19 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.de.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.de.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.es.xlf b/src/Tasks/Common/Resources/xlf/Strings.es.xlf index e1b551283a5c..5ed642ba3109 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.es.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.es.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf index daf4cd8361a1..7a67edfaebeb 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.fr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.fr.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.it.xlf b/src/Tasks/Common/Resources/xlf/Strings.it.xlf index 35e633f339f7..814351eb43a9 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.it.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.it.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf index 17e73aa949fd..d80316eb8562 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ja.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ja.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf index f54c4424a805..314eca754bf8 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ko.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ko.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf index 0bef6646052f..8763c28b1cc5 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pl.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pl.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf index ef28af09121d..6d0c8608daaf 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf index c70dbd5bd4ec..60da28514bb9 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.ru.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.ru.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf index dc4af3a7ba63..3a53553d7b1f 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.tr.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.tr.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf index 45944a94b25a..0a979192f4e9 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hans.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf index 8fc041319ac7..f199482d1b24 100644 --- a/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Tasks/Common/Resources/xlf/Strings.zh-Hant.xlf @@ -885,6 +885,13 @@ The following are names of parameters or literal values and should not be transl NETSDK1148: A referenced assembly was compiled using a newer version of Microsoft.Windows.SDK.NET.dll. Please update to a newer .NET SDK in order to reference this assembly. {StrBegin="NETSDK1148: "} + + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + NETSDK1178: The project depends on the following workload packs that do not exist in any of the workloads available in this installation: {0} +You may need to build the project on another operating system or architecture, or update the .NET SDK. + {StrBegin="NETSDK1178: "} + NETSDK1147: To build this project, the following workloads must be installed: {0} To install these workloads, run the following command: {1} diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs index 560188eb32ad..e12eff873125 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ShowMissingWorkloads.cs @@ -34,24 +34,35 @@ protected override void ExecuteCore() var workloadManifestProvider = new SdkDirectoryWorkloadManifestProvider(NetCoreRoot, NETCoreSdkVersion); var workloadResolver = WorkloadResolver.Create(workloadManifestProvider, NetCoreRoot, NETCoreSdkVersion); - var suggestedWorkloads = workloadResolver.GetWorkloadSuggestionForMissingPacks(MissingWorkloadPacks.Select(item => new WorkloadPackId (item.ItemSpec)).ToList()); + var suggestedWorkloads = workloadResolver.GetWorkloadSuggestionForMissingPacks( + MissingWorkloadPacks.Select(item => new WorkloadPackId (item.ItemSpec)).ToList(), + out ISet unsatisfiablePacks + ); if (GenerateErrorsForMissingWorkloads) { - var suggestedInstallCommand = "dotnet workload install " + string.Join(" ", suggestedWorkloads.Select(w => w.Id)); - - var errorMessage = string.Format(CultureInfo.CurrentCulture, - Strings.WorkloadNotInstalled, string.Join(" ", suggestedWorkloads.Select(w => w.Id)), suggestedInstallCommand); - - Log.LogError(errorMessage); + if (suggestedWorkloads is not null) + { + var suggestedInstallCommand = "dotnet workload install " + string.Join(" ", suggestedWorkloads.Select(w => w.Id)); + var errorMessage = string.Format(CultureInfo.CurrentCulture, + Strings.WorkloadNotInstalled, string.Join(" ", suggestedWorkloads.Select(w => w.Id)), suggestedInstallCommand); + Log.LogError(errorMessage); + } + else + { + Log.LogError(Strings.WorkloadNotAvailable, string.Join(" ", unsatisfiablePacks)); + } } - SuggestedWorkloads = suggestedWorkloads.Select(suggestedWorkload => + if (suggestedWorkloads is not null) { - var taskItem = new TaskItem(suggestedWorkload.Id); - taskItem.SetMetadata("VisualStudioComponentId", ToSafeId(suggestedWorkload.Id)); - return taskItem; - }).ToArray(); + SuggestedWorkloads = suggestedWorkloads.Select(suggestedWorkload => + { + var taskItem = new TaskItem(suggestedWorkload.Id); + taskItem.SetMetadata("VisualStudioComponentId", ToSafeId(suggestedWorkload.Id)); + return taskItem; + }).ToArray(); + } } } diff --git a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs index f991b37b4c50..2952c04c98ae 100644 --- a/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs +++ b/src/Tests/Microsoft.NET.Sdk.WorkloadManifestReader.Tests/WorkloadSuggestionFinderTests.cs @@ -34,9 +34,14 @@ public void CanSuggestSimpleWorkload() FakeFileSystemChecksSoThesePackagesAppearInstalled(resolver, "Xamarin.Android.Sdk", "Xamarin.Android.BuildTools"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Sdk" }.Select(s => new WorkloadPackId(s)).ToList()); - suggestions.Count().Should().Be(1); - suggestions.First().Id.ToString().Should().Be("xamarin-android-build"); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks( + new[] { "Mono.Android.Sdk" }.Select(s => new WorkloadPackId(s)).ToList(), + out var unsatisfiable); + + unsatisfiable.Count().Should().Be(0); + suggestions.Should().NotBeNull(); + suggestions!.Count().Should().Be(1); + suggestions!.First().Id.ToString().Should().Be("xamarin-android-build"); } [Fact] @@ -53,10 +58,15 @@ public void CanSuggestTwoWorkloadsToFulfilTwoRequirements() "Xamarin.Android.Runtime", "Mono.Android.Sdk"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Mono.Android.Runtime.x86", "Mono.Android.Runtime.Armv7a" }.Select(s => new WorkloadPackId(s)).ToList()); - suggestions.Count().Should().Be(2); - suggestions.Should().Contain(s => s.Id == "xamarin-android-build-armv7a"); - suggestions.Should().Contain(s => s.Id == "xamarin-android-build-x86"); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks( + new[] { "Mono.Android.Runtime.x86", "Mono.Android.Runtime.Armv7a" }.Select(s => new WorkloadPackId(s)).ToList(), + out var unsatisfiable); + + unsatisfiable.Count().Should().Be(0); + suggestions.Should().NotBeNull(); + suggestions!.Count().Should().Be(2); + suggestions!.Should().Contain(s => s.Id == "xamarin-android-build-armv7a"); + suggestions!.Should().Contain(s => s.Id == "xamarin-android-build-x86"); } [Fact] @@ -73,9 +83,14 @@ public void CanSuggestWorkloadThatFulfillsTwoRequirements() "Xamarin.Android.Runtime", "Mono.Android.Sdk"); - var suggestions = resolver.GetWorkloadSuggestionForMissingPacks(new[] { "Xamarin.Android.Templates", "Xamarin.Android.LLVM.Aot.armv7a" }.Select(s => new WorkloadPackId(s)).ToList()); - suggestions.Count().Should().Be(1); - suggestions.First().Id.ToString().Should().Be("xamarin-android-complete"); + var suggestions = resolver.GetWorkloadSuggestionForMissingPacks( + new[] { "Xamarin.Android.Templates", "Xamarin.Android.LLVM.Aot.armv7a" }.Select(s => new WorkloadPackId(s)).ToList(), + out var unsatisfiable); + + unsatisfiable.Count().Should().Be(0); + suggestions.Should().NotBeNull(); + suggestions!.Count().Should().Be(1); + suggestions!.First().Id.ToString().Should().Be("xamarin-android-complete"); } [Fact] diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index 8c7fa4ad427c..b5e017496c36 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -20,7 +20,7 @@ public MockWorkloadResolver(IEnumerable available public IEnumerable GetInstalledWorkloadPacksOfKind(WorkloadPackKind kind) => throw new NotImplementedException(); public IEnumerable GetPacksInWorkload(WorkloadId workloadId) => throw new NotImplementedException(); - public ISet GetWorkloadSuggestionForMissingPacks(IList packId) => throw new NotImplementedException(); + public ISet GetWorkloadSuggestionForMissingPacks(IList packId, out ISet unsatisfiablePacks) => throw new NotImplementedException(); public void RefreshWorkloadManifests() => throw new NotImplementedException(); public WorkloadResolver.PackInfo TryGetPackInfo(WorkloadPackId packId) => throw new NotImplementedException(); public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) => throw new NotImplementedException(); From f4ed4c700bc69f5d88fdccdff895b664c411d5ff Mon Sep 17 00:00:00 2001 From: Mikayla Hutchinson Date: Mon, 19 Jul 2021 02:56:04 -0400 Subject: [PATCH 22/26] Fix accidental removal that broke workload search tests --- .../dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs index c2eb32493fc9..f37d74344949 100644 --- a/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs +++ b/src/Tests/dotnet-workload-search.Tests/GivenDotnetWorkloadSearch.cs @@ -23,6 +23,7 @@ public class GivenDotnetWorkloadSearch : SdkTest { CreateWorkloadInfo("mock-workload-1"), CreateWorkloadInfo("mock-workload-2"), + CreateWorkloadInfo("mock-workload-3"), CreateWorkloadInfo("fake-workload-1"), CreateWorkloadInfo("fake-workload-2", "Fake description 2") }; From b736168646ee740a38b9374a9c9688b0c20942d7 Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Sun, 18 Jul 2021 11:39:56 -0700 Subject: [PATCH 23/26] Fix error message argument indices --- .../Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx | 6 +++--- .../xlf/Strings.cs.xlf | 8 ++++---- .../xlf/Strings.de.xlf | 8 ++++---- .../xlf/Strings.es.xlf | 8 ++++---- .../xlf/Strings.fr.xlf | 8 ++++---- .../xlf/Strings.it.xlf | 8 ++++---- .../xlf/Strings.ja.xlf | 8 ++++---- .../xlf/Strings.ko.xlf | 8 ++++---- .../xlf/Strings.pl.xlf | 8 ++++---- .../xlf/Strings.pt-BR.xlf | 8 ++++---- .../xlf/Strings.ru.xlf | 8 ++++---- .../xlf/Strings.tr.xlf | 8 ++++---- .../xlf/Strings.zh-Hans.xlf | 8 ++++---- .../xlf/Strings.zh-Hant.xlf | 8 ++++---- 14 files changed, 55 insertions(+), 55 deletions(-) diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx index cadeb62d78f4..059af1a6f029 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/Strings.resx @@ -166,10 +166,10 @@ Unresolved target '{0}' for workload redirect '{1}' in manifest '{2}' [{3}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] Manifest provider {0} returned a duplicate manifest ID '{1}' [{2}] that conflicts with existing manifest [{3}] @@ -186,4 +186,4 @@ Cyclic workload redirect '{0}' in manifest '{1}' [{2}] - \ No newline at end of file + 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 62304df730a1..c8c34be15e94 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.cs.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 dde0ff30dec5..b2ba7be72168 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.de.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 88b4346568c0..19d43ff13432 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.es.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 9612b88017bc..0b73d6175ceb 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.fr.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 e1b59b28799b..76fb0ab5373a 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.it.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 1451665b0c97..98446f02784c 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ja.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 69f87c1950d7..195a6eabaefe 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ko.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 8274977a1a6e..1b79c4a64fac 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.pl.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 a6ecb917a372..f248c7b31e75 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 @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 7da21b2f024c..edb704ddbdea 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.ru.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 1d246610b895..3c91092eff17 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/xlf/Strings.tr.xlf @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 5b8e2db5ea66..77ee0fcfab46 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 @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] 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 33eeb3c71d86..9d43e9618705 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 @@ -8,13 +8,13 @@ - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload definition '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload definition '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] - Workload pack '{0}' in manifest '{2}' [{3}] conflicts with manifest '{4}' [{5}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] + Workload pack '{0}' in manifest '{1}' [{2}] conflicts with manifest '{3}' [{4}] From 4d4f3ef4b8101747d00dbf5f6b0528404e013cfd Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Sun, 18 Jul 2021 11:41:02 -0700 Subject: [PATCH 24/26] Fix workload mocks to use correct manifest IDs This prevents it from erroring out because it loads the same manifest twice in the workload update test. --- .../dotnet-workload-install.Tests/MockManifestProvider.cs | 6 +++++- .../MockWorkloadManifestUpdater.cs | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs index 03da94e224cd..1b41eeae0e66 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockManifestProvider.cs @@ -15,7 +15,11 @@ internal class MockManifestProvider : IWorkloadManifestProvider public MockManifestProvider(params string[] manifestPaths) { - _manifests = Array.ConvertAll(manifestPaths, mp => (mp, mp)); + _manifests = Array.ConvertAll(manifestPaths, mp => + { + string manifestId = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(mp)); + return (manifestId, mp); + }); } public MockManifestProvider(params (string name, string path)[] manifests) diff --git a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs index 34df65c0e3b0..80573716d017 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockWorkloadManifestUpdater.cs @@ -52,8 +52,8 @@ public Task ExtractManifestPackagesToTempDirAsync(IEnumerable manifestPa ExtractManifestPackagesToTempDirCallCount++; if (!string.IsNullOrEmpty(_tempDirManifestPath)) { - Directory.CreateDirectory(Path.Combine(tempDir.Value, "mockPath")); - File.Copy(_tempDirManifestPath, Path.Combine(tempDir.Value, "mockPath", "WorkloadManifest.json")); + Directory.CreateDirectory(Path.Combine(tempDir.Value, "SampleManifest")); + File.Copy(_tempDirManifestPath, Path.Combine(tempDir.Value, "SampleManifest", "WorkloadManifest.json")); } return Task.CompletedTask; } From 9f159434e4c3387ba8a23361fa4192220f3d98bf Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Sun, 18 Jul 2021 19:55:00 -0700 Subject: [PATCH 25/26] Update test now that mock workload manifest has right ID --- .../dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs index 777e43b901db..555c4aa60d3b 100644 --- a/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs +++ b/src/Tests/dotnet-workload-update.Tests/GivenDotnetWorkloadUpdate.cs @@ -296,7 +296,7 @@ public void GivenPrintRollbackDefinitionItIncludesAllInstalledManifests() updateCommand.Execute(); _reporter.Lines.Count().Should().Be(3); - string.Join("", _reporter.Lines).Should().Contain("Sample.json"); + string.Join("", _reporter.Lines).Should().Contain("SampleManifest"); } internal (string, WorkloadUpdateCommand, MockPackWorkloadInstaller, IWorkloadResolver, MockWorkloadManifestUpdater, MockNuGetPackageDownloader) GetTestInstallers( From 88fc6b49a01092d93ba5bcd6ab601cc4ff27393a Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Mon, 19 Jul 2021 08:26:51 -0700 Subject: [PATCH 26/26] Generate correct error message when trying to install a workload which isn't supported for the current platform --- .../install/WorkloadInstallCommand.cs | 12 ++++++------ .../IWorkloadResolver.cs | 2 +- .../WorkloadResolver.cs | 7 ++++--- .../MockWorkloadResolver.cs | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs index c64c03ac9f5e..a20b50156eaa 100644 --- a/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-workload/install/WorkloadInstallCommand.cs @@ -104,16 +104,16 @@ private void ValidateWorkloadIdsInput() var availableWorkloads = _workloadResolver.GetAvailableWorkloads(); foreach (var workloadId in _workloadIds) { - if (availableWorkloads.Select(workload => workload.Id.ToString()).Contains(workloadId)) + if (!availableWorkloads.Select(workload => workload.Id.ToString()).Contains(workloadId)) { - if (!_workloadResolver.IsWorkloadPlatformCompatible(new WorkloadId(workloadId))) + if (_workloadResolver.IsPlatformIncompatibleWorkload(new WorkloadId(workloadId))) { throw new GracefulException(string.Format(LocalizableStrings.WorkloadNotSupportedOnPlatform, workloadId)); } - } - else - { - throw new GracefulException(string.Format(LocalizableStrings.WorkloadNotRecognized, workloadId)); + else + { + throw new GracefulException(string.Format(LocalizableStrings.WorkloadNotRecognized, workloadId)); + } } } } diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs index 7b03e842d3d5..cb39fbaceefd 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/IWorkloadResolver.cs @@ -11,7 +11,7 @@ public interface IWorkloadResolver IEnumerable GetPacksInWorkload(WorkloadId workloadId); ISet? GetWorkloadSuggestionForMissingPacks(IList packId, out ISet unsatisfiablePacks); IEnumerable GetAvailableWorkloads(); - bool IsWorkloadPlatformCompatible(WorkloadId workloadId); + bool IsPlatformIncompatibleWorkload(WorkloadId workloadId); string GetManifestVersion(string manifestId); IEnumerable GetInstalledManifests(); diff --git a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs index d5eee1aaf4c5..1a547020a5fd 100644 --- a/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs +++ b/src/Resolvers/Microsoft.NET.Sdk.WorkloadManifestReader/WorkloadResolver.cs @@ -621,13 +621,14 @@ public WorkloadInfo GetWorkloadInfo(WorkloadId workloadId) return new WorkloadInfo(workload.Id, workload.Description); } - public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) + public bool IsPlatformIncompatibleWorkload(WorkloadId workloadId) { if (_workloads.TryGetValue(workloadId) is not (WorkloadDefinition workload, WorkloadManifest manifest)) { - throw new ArgumentException($"Workload '{workloadId}' not found", nameof(workloadId)); + // Not a recognized workload + return false; } - return IsWorkloadPlatformCompatible(workload, manifest); + return !IsWorkloadPlatformCompatible(workload, manifest); } private bool IsWorkloadPlatformCompatible(WorkloadDefinition workload, WorkloadManifest manifest) diff --git a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs index b5e017496c36..f340db076a2f 100644 --- a/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs +++ b/src/Tests/dotnet-workload-search.Tests/MockWorkloadResolver.cs @@ -23,7 +23,7 @@ public MockWorkloadResolver(IEnumerable available public ISet GetWorkloadSuggestionForMissingPacks(IList packId, out ISet unsatisfiablePacks) => throw new NotImplementedException(); public void RefreshWorkloadManifests() => throw new NotImplementedException(); public WorkloadResolver.PackInfo TryGetPackInfo(WorkloadPackId packId) => throw new NotImplementedException(); - public bool IsWorkloadPlatformCompatible(WorkloadId workloadId) => throw new NotImplementedException(); + public bool IsPlatformIncompatibleWorkload(WorkloadId workloadId) => throw new NotImplementedException(); public string GetManifestVersion(string manifestId) => throw new NotImplementedException(); public IEnumerable GetInstalledManifests() => throw new NotImplementedException(); public IWorkloadResolver CreateOverlayResolver(IWorkloadManifestProvider overlayManifestProvider) => throw new NotImplementedException();