Case-insensitive roll-forward parsing (#121)

This commit is contained in:
Patrick Stevens
2025-09-16 22:23:15 +01:00
committed by GitHub
parent 4704c471bc
commit cf249fd556
7 changed files with 71 additions and 5 deletions

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace WoofWare.DotnetRuntimeLocator;
@@ -257,6 +258,18 @@ public static class DotnetRuntime
}
}
private static JsonSerializerOptions _options = new() {PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter<RollForward>() }};
/// <summary>
/// Parse a runtimeconfig.json file.
/// </summary>
/// <param name="contents">Contents of the runtimeconfig.json file to parse.</param>
/// <exception cref="NullReferenceException">I think this can't happen, but the docs suggest that deserialization might return null.</exception>
public static RuntimeConfig? DeserializeRuntimeConfig(string contents)
{
return JsonSerializer.Deserialize<RuntimeConfig>(contents, _options);
}
/// <summary>
/// Given a .NET executable DLL, identify the most appropriate .NET runtime to run it.
/// This is pretty half-baked at the moment; test this yourself to make sure it does what you want it to!
@@ -285,9 +298,8 @@ public static class DotnetRuntime
// It appears to be undocumented why this returns a nullable, and the Rider decompiler doesn't suggest there are
// any code paths where it can return null?
var runtimeConfig =
JsonSerializer.Deserialize<RuntimeConfig>(File.ReadAllText(configFilePath)) ??
throw new NullReferenceException($"Failed to parse contents of file {configFilePath} as a runtime config");
var contents = File.ReadAllText(configFilePath);
var runtimeConfig = DeserializeRuntimeConfig(contents) ?? throw new NullReferenceException($"Failed to parse contents of file {configFilePath} as a runtime config");
var availableRuntimes = dotnet == null
? DotnetEnvironmentInfo.Get()

View File

@@ -46,6 +46,7 @@ WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Path [method]: string
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.set_Version [method]: string -> unit
WoofWare.DotnetRuntimeLocator.DotnetEnvironmentSdkInfo.Version [property]: string
WoofWare.DotnetRuntimeLocator.DotnetRuntime inherit obj
WoofWare.DotnetRuntimeLocator.DotnetRuntime.DeserializeRuntimeConfig [static method]: string -> WoofWare.DotnetRuntimeLocator.RuntimeConfig
WoofWare.DotnetRuntimeLocator.DotnetRuntime.SelectForDll [static method]: (string, string) -> string System.Collections.Generic.IReadOnlyList
WoofWare.DotnetRuntimeLocator.RollForward inherit System.Enum
WoofWare.DotnetRuntimeLocator.RollForward.Disable [static field]: WoofWare.DotnetRuntimeLocator.RollForward = Disable

View File

@@ -0,0 +1,21 @@
namespace WoofWare.DotnetRuntimeLocator.Test
open System
open System.IO
open System.Reflection
[<RequireQualifiedAccess>]
module Assembly =
let getEmbeddedResource (assembly : Assembly) (name : string) : string =
let names = assembly.GetManifestResourceNames ()
let names =
names |> Seq.filter (fun s -> s.EndsWith (name, StringComparison.Ordinal))
use s =
names
|> Seq.exactlyOne
|> assembly.GetManifestResourceStream
|> fun s -> new StreamReader (s)
s.ReadToEnd ()

View File

@@ -8,10 +8,12 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Assembly.fs" />
<Compile Include="TestDotnetRuntime.fs" />
<Compile Include="TestRuntimeConfigParse.fs"/>
<Compile Include="TestSurface.fs"/>
<Compile Include="TestDotnetEnvironmentInfo.fs"/>
<EmbeddedResource Include="runtimeconfig1.json" />
</ItemGroup>
<ItemGroup>

View File

@@ -30,3 +30,20 @@ module TestRuntimeConfigParse =
)
actual |> shouldEqual expected
[<Test>]
let ``Example 1`` () =
let content =
Assembly.getEmbeddedResource (Assembly.GetExecutingAssembly ()) "runtimeconfig1.json"
let expected =
RuntimeConfig (
RuntimeOptions =
RuntimeOptions (
Tfm = "net8.0",
RollForward = RollForward.Major,
Framework = RuntimeConfigFramework (Name = "Microsoft.NETCore.App", Version = "8.0.0")
)
)
DotnetRuntime.DeserializeRuntimeConfig content |> shouldEqual expected

View File

@@ -0,0 +1,13 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"rollForward": "Major",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

View File

@@ -1,5 +1,5 @@
{
"version": "0.3",
"version": "0.4",
"publicReleaseRefSpec": [
"^refs/heads/main$"
],
@@ -9,4 +9,4 @@
":/Directory.Build.props",
":/README.md"
]
}
}