From abc761c2c5694e4029fea1a60dc1934951c66e26 Mon Sep 17 00:00:00 2001 Patch-Source: https://github.com/dotnet/runtime/pull/84442 From: Tom Deseyn Date: Thu, 6 Apr 2023 13:18:11 +0200 Subject: [PATCH 1/2] Microsoft.NETCore.Platforms: support adding rids with '-' in the base part. Currently when trying to add a rid like 'linux-musl-x64' the rid is not understood to be base = 'linux-musl', arch = 'x64'. Instead the parser considers a potential optional qualifier. This causes the rid to be parsed as base = 'linux', arch = 'musl', and qualifier = 'x64'. We know the rids being added won't have a qualifier. If we take this into account while parsing, we can parse the rid correctly. --- .../Microsoft.NETCore.Platforms/src/RID.cs | 11 +++- .../src/RuntimeGroupCollection.cs | 2 +- .../tests/RidTests.cs | 50 +++++++++++++------ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs index 6457fd29cadf0..b464d5f0f54e3 100644 --- a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs +++ b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RID.cs @@ -56,7 +56,7 @@ private enum RIDPart : int Max = Qualifier } - public static RID Parse(string runtimeIdentifier) + public static RID Parse(string runtimeIdentifier, bool noQualifier) { string[] parts = new string[(int)RIDPart.Max + 1]; bool omitVersionDelimiter = true; @@ -90,6 +90,15 @@ public static RID Parse(string runtimeIdentifier) // version might be omitted else if (current == ArchitectureDelimiter) { + // The qualifier delimiter and architecture delimiter are the same. + // When there is no qualifier, there will be one delimiter past the base part + // for the architecture. + // So if we see another delimiter later in the string (for the architecture), + // extend the base part instead of starting the architecture part. + if (noQualifier && runtimeIdentifier.IndexOf(ArchitectureDelimiter, i + 1) != -1) + { + break; + } // ensure there's no version later in the string if (runtimeIdentifier.IndexOf(VersionDelimiter, i) != -1) { diff --git a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs index e069508053105..31009a8d28e5e 100644 --- a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs +++ b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs @@ -34,7 +34,7 @@ public RuntimeGroupCollection(ICollection runtimeGroups) /// public void AddRuntimeIdentifier(string runtimeIdentifier, string parent) { - RID rid = RID.Parse(runtimeIdentifier); + RID rid = RID.Parse(runtimeIdentifier, noQualifier: true); AddRuntimeIdentifier(rid, parent); } diff --git a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs index 227bcbdd10d4d..8dee0ebeda17a 100644 --- a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs +++ b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/tests/RidTests.cs @@ -10,35 +10,57 @@ public class RidTests { public static IEnumerable ValidRIDData() { - yield return new object[] { "win10-x64", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10"), Architecture = "x64" } }; - yield return new object[] { "win10", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10")} }; - yield return new object[] { "linux", new RID() { BaseRID = "linux" } }; - yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; - yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; - yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" } }; - yield return new object[] { "linuxmint.19.2-x64", new RID() { BaseRID = "linuxmint", Version = new RuntimeVersion("19.2"), Architecture = "x64" } }; - yield return new object[] { "ubuntu.14.04-x64", new RID() { BaseRID = "ubuntu", Version = new RuntimeVersion("14.04"), Architecture = "x64" } }; - yield return new object[] { "foo-bar.42-arm", new RID() { BaseRID = "foo-bar", Version = new RuntimeVersion("42"), Architecture = "arm" } }; - yield return new object[] { "foo-bar-arm", new RID() { BaseRID = "foo", Architecture = "bar", Qualifier = "arm" } }; // demonstrates ambiguity, avoid using `-` in base - yield return new object[] { "linux-musl-x64", new RID() { BaseRID = "linux", Architecture = "musl", Qualifier = "x64" } }; // yes, we already have ambiguous RIDs + yield return new object[] { "win10-x64", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10"), Architecture = "x64" }, null }; + yield return new object[] { "win10", new RID() { BaseRID = "win", OmitVersionDelimiter = true, Version = new RuntimeVersion("10")}, null }; + yield return new object[] { "linux", new RID() { BaseRID = "linux" }, null }; + yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" }, null }; + yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" }, null }; + yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" }, null }; + yield return new object[] { "linuxmint.19.2-x64", new RID() { BaseRID = "linuxmint", Version = new RuntimeVersion("19.2"), Architecture = "x64" }, null }; + yield return new object[] { "ubuntu.14.04-x64", new RID() { BaseRID = "ubuntu", Version = new RuntimeVersion("14.04"), Architecture = "x64" }, null }; + yield return new object[] { "foo-bar.42-arm", new RID() { BaseRID = "foo-bar", Version = new RuntimeVersion("42"), Architecture = "arm" }, null }; + yield return new object[] { "foo-bar-arm", new RID() { BaseRID = "foo", Architecture = "bar", Qualifier = "arm" }, // demonstrates ambiguity, avoid using `-` in base + new RID() { BaseRID = "foo-bar", Architecture = "arm" } }; + yield return new object[] { "linux-musl-x64", new RID() { BaseRID = "linux", Architecture = "musl", Qualifier = "x64" }, // yes, we already have ambiguous RIDs + new RID() { BaseRID = "linux-musl", Architecture = "x64" } }; } [Theory] [MemberData(nameof(ValidRIDData))] - internal void ParseCorrectly(string input, RID expected) + internal void ParseCorrectly(string input, RID expected, RID? expectedNoQualifier) { - RID actual = RID.Parse(input); + _ = expectedNoQualifier; // unused + + RID actual = RID.Parse(input, noQualifier: false); Assert.Equal(expected, actual); } [Theory] [MemberData(nameof(ValidRIDData))] - internal void ToStringAsExpected(string expected, RID rid) + internal void ParseCorrectlyNoQualifier(string input, RID expected, RID? expectedNoQualifier) + { + expectedNoQualifier ??= expected; + + RID actual = RID.Parse(input, noQualifier: true); + + Assert.Equal(expectedNoQualifier, actual); + } + + [Theory] + [MemberData(nameof(ValidRIDData))] + internal void ToStringAsExpected(string expected, RID rid, RID? expectedNoQualifierRid) { string actual = rid.ToString(); Assert.Equal(expected, actual); + + if (expectedNoQualifierRid is not null) + { + actual = expectedNoQualifierRid.ToString(); + + Assert.Equal(expected, actual); + } } } } From f70da467ca94291039e0ea5b0723cb9db5e090e7 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 6 Apr 2023 18:14:31 +0200 Subject: [PATCH 2/2] Update src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs Co-authored-by: Eric StJohn --- .../Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs index 31009a8d28e5e..ec4762d71424c 100644 --- a/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs +++ b/src/runtime/src/libraries/Microsoft.NETCore.Platforms/src/RuntimeGroupCollection.cs @@ -34,6 +34,7 @@ public RuntimeGroupCollection(ICollection runtimeGroups) /// public void AddRuntimeIdentifier(string runtimeIdentifier, string parent) { + // don't parse qualifier since we don't use them and they are ambiguous with `-` in base RID RID rid = RID.Parse(runtimeIdentifier, noQualifier: true); AddRuntimeIdentifier(rid, parent);