import all shipped nuget packages as built-in
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (SharedCringe) (push) Successful in 53s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 1m0s
Build / Build Nuget package (NuGet) (push) Successful in 58s
Build / Build Nuget package (CringePlugins) (push) Successful in 1m13s
Build / Build Launcher (push) Successful in 1m42s
All checks were successful
Build / Compute Version (push) Successful in 6s
Build / Build Nuget package (SharedCringe) (push) Successful in 53s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 1m0s
Build / Build Nuget package (NuGet) (push) Successful in 58s
Build / Build Nuget package (CringePlugins) (push) Successful in 1m13s
Build / Build Launcher (push) Successful in 1m42s
also would now throw if version gets changed
This commit is contained in:
@@ -10,6 +10,7 @@ using NLog;
|
|||||||
using NuGet;
|
using NuGet;
|
||||||
using NuGet.Deps;
|
using NuGet.Deps;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
using NuGet.Models;
|
||||||
using NuGet.Versioning;
|
using NuGet.Versioning;
|
||||||
using SharedCringe.Loader;
|
using SharedCringe.Loader;
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ public class PluginsLifetime(string gameFolder) : ILoadingStage
|
|||||||
private ImmutableArray<PluginInstance> _plugins = [];
|
private ImmutableArray<PluginInstance> _plugins = [];
|
||||||
// TODO move this as api for other plugins
|
// TODO move this as api for other plugins
|
||||||
private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher"));
|
private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher"));
|
||||||
private readonly NuGetFramework _runtimeFramework = NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0");
|
private readonly NuGetRuntimeFramework _runtimeFramework = new(NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0"), RuntimeInformation.RuntimeIdentifier);
|
||||||
|
|
||||||
public async ValueTask Load(ISplashProgress progress)
|
public async ValueTask Load(ISplashProgress progress)
|
||||||
{
|
{
|
||||||
@@ -54,13 +55,14 @@ public class PluginsLifetime(string gameFolder) : ILoadingStage
|
|||||||
progress.Report("Resolving packages");
|
progress.Report("Resolving packages");
|
||||||
|
|
||||||
var sourceMapping = new PackageSourceMapping(packagesConfig.Sources);
|
var sourceMapping = new PackageSourceMapping(packagesConfig.Sources);
|
||||||
var resolver = new PackageResolver(_runtimeFramework, packagesConfig.Packages, sourceMapping);
|
// TODO take into account the target framework runtime identifier
|
||||||
|
var resolver = new PackageResolver(_runtimeFramework.Framework, packagesConfig.Packages, sourceMapping);
|
||||||
|
|
||||||
var packages = await resolver.ResolveAsync();
|
var packages = await resolver.ResolveAsync();
|
||||||
|
|
||||||
progress.Report("Downloading packages");
|
progress.Report("Downloading packages");
|
||||||
|
|
||||||
var builtInPackages = BuiltInPackages.GetPackages(_runtimeFramework).ToImmutableDictionary(package => package.Package.Id);
|
var builtInPackages = await BuiltInPackages.GetPackagesAsync(_runtimeFramework);
|
||||||
var cachedPackages = await resolver.DownloadPackagesAsync(_dir.CreateSubdirectory("cache"), packages, builtInPackages.Keys.ToHashSet(), progress);
|
var cachedPackages = await resolver.DownloadPackagesAsync(_dir.CreateSubdirectory("cache"), packages, builtInPackages.Keys.ToHashSet(), progress);
|
||||||
|
|
||||||
progress.Report("Loading plugins");
|
progress.Report("Loading plugins");
|
||||||
|
@@ -7,12 +7,14 @@ using dnlib.DotNet;
|
|||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NuGet.Deps;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
using NuGet.Models;
|
using NuGet.Models;
|
||||||
using NuGet.Versioning;
|
using NuGet.Versioning;
|
||||||
using Sandbox.Game;
|
using Sandbox.Game;
|
||||||
using SpaceEngineers.Game;
|
using SpaceEngineers.Game;
|
||||||
using VRage.Utils;
|
using VRage.Utils;
|
||||||
|
using Dependency = NuGet.Models.Dependency;
|
||||||
|
|
||||||
namespace CringePlugins.Resolver;
|
namespace CringePlugins.Resolver;
|
||||||
|
|
||||||
@@ -22,18 +24,25 @@ public static class BuiltInPackages
|
|||||||
private const string ImGui = "ImGui.NET.DirectX";
|
private const string ImGui = "ImGui.NET.DirectX";
|
||||||
private const string Harmony = "Lib.Harmony.Thin";
|
private const string Harmony = "Lib.Harmony.Thin";
|
||||||
private const string Steamworks = "Steamworks.NET";
|
private const string Steamworks = "Steamworks.NET";
|
||||||
|
private const string NLog = "NLog";
|
||||||
|
|
||||||
public static ImmutableArray<ResolvedPackage> GetPackages(NuGetFramework runtimeFramework)
|
public static async ValueTask<ImmutableDictionary<string, ResolvedPackage>> GetPackagesAsync(NuGetRuntimeFramework runtimeFramework)
|
||||||
{
|
{
|
||||||
var nlog = FromAssembly<LogFactory>(runtimeFramework, version: new(5, 3, 4));
|
ImmutableDictionary<ManifestPackageKey, DependencyLibrary> libraries;
|
||||||
|
await using (var stream = File.OpenRead(Path.ChangeExtension(Assembly.GetEntryAssembly()!.Location, "deps.json")))
|
||||||
|
(_, _, _, libraries) = await DependencyManifestSerializer.DeserializeAsync(stream);
|
||||||
|
|
||||||
|
var framework = runtimeFramework.Framework;
|
||||||
|
|
||||||
|
var nlog = FromAssembly<LogFactory>(framework, version: libraries.Keys.Single(b => b.Id == NLog).Version);
|
||||||
Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
|
Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
|
||||||
|
|
||||||
var se = FromAssembly<SpaceEngineersGame>(runtimeFramework, [
|
var se = FromAssembly<SpaceEngineersGame>(framework, [
|
||||||
nlog.AsDependency()
|
nlog.AsDependency(libraries)
|
||||||
], SeReferenceAssemblies, new(seVersion));
|
], SeReferenceAssemblies, new(seVersion));
|
||||||
var imGui = FromAssembly<ImGuiKey>(runtimeFramework, id: ImGui);
|
var imGui = FromAssembly<ImGuiKey>(framework, id: ImGui);
|
||||||
var harmony = FromAssembly<HarmonyLib.Harmony>(runtimeFramework, id: Harmony);
|
var harmony = FromAssembly<HarmonyLib.Harmony>(framework, id: Harmony, version: NuGetVersion.Parse("2.3.4-torch"));
|
||||||
var steam = FromAssembly<Steamworks.CSteamID>(runtimeFramework, id: Steamworks);
|
var steam = FromAssembly<Steamworks.CSteamID>(framework, id: Steamworks);
|
||||||
|
|
||||||
BuiltInSdkPackage MapSdkPackage(
|
BuiltInSdkPackage MapSdkPackage(
|
||||||
(string FileName, byte[] ImageBytes, PortableExecutableReference Reference, Guid Mvid) r)
|
(string FileName, byte[] ImageBytes, PortableExecutableReference Reference, Guid Mvid) r)
|
||||||
@@ -43,29 +52,60 @@ public static class BuiltInPackages
|
|||||||
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
|
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
|
||||||
|
|
||||||
return new BuiltInSdkPackage(
|
return new BuiltInSdkPackage(
|
||||||
new(0, Path.GetFileNameWithoutExtension(r.FileName), version), runtimeFramework,
|
new(0, Path.GetFileNameWithoutExtension(r.FileName), version), framework,
|
||||||
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(runtimeFramework, [])], null, []));
|
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(framework, [])], null, []));
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
BuiltInPackage MapPackage(ManifestPackageKey key)
|
||||||
|
{
|
||||||
|
return new(new(0, key.Id, key.Version), framework,
|
||||||
|
new(key.Id, key.Version, [new(framework, [])], null, []));
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvedPackage[] packages =
|
||||||
[
|
[
|
||||||
..Net90.ReferenceInfos.AllValues.Select(MapSdkPackage),
|
..Net90.ReferenceInfos.AllValues.Select(MapSdkPackage),
|
||||||
// ..Net80Windows.ReferenceInfos.AllValues.Select(MapSdkPackage),
|
|
||||||
nlog,
|
|
||||||
se,
|
se,
|
||||||
imGui,
|
|
||||||
harmony,
|
..libraries.Where(kvp =>
|
||||||
steam,
|
{
|
||||||
FromAssembly<PluginsLifetime>(runtimeFramework,
|
if (kvp.Value.Type != LibraryType.Package) return false;
|
||||||
[se.AsDependency(), imGui.AsDependency(), harmony.AsDependency()]
|
|
||||||
|
// Special case as we want to claim we have currently running version of package
|
||||||
|
// so that even if launcher is built with older version, plugins could still take explicit dependency on it
|
||||||
|
if (kvp.Key.Id == SeReferenceAssemblies) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}).Select(kvp => MapPackage(kvp.Key)),
|
||||||
|
|
||||||
|
// CringePlugins package itself
|
||||||
|
FromAssembly<PluginsLifetime>(framework,
|
||||||
|
[
|
||||||
|
se.AsDependency(libraries),
|
||||||
|
imGui.AsDependency(libraries),
|
||||||
|
harmony.AsDependency(libraries),
|
||||||
|
steam.AsDependency(libraries)
|
||||||
|
]
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
, version: new(0, 1, 21)
|
, version: new(0, 1, 21)
|
||||||
#endif
|
#endif
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var builder = ImmutableDictionary.CreateBuilder<string, ResolvedPackage>();
|
||||||
|
foreach (var package in packages)
|
||||||
|
builder.TryAdd(package.Package.Id, package);
|
||||||
|
|
||||||
|
return builder.ToImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dependency AsDependency(this ResolvedPackage package) => new(package.Package.Id, new(package.Package.Version));
|
private static Dependency AsDependency(this ResolvedPackage package, ImmutableDictionary<ManifestPackageKey, DependencyLibrary> libraries)
|
||||||
|
{
|
||||||
|
if (!libraries.ContainsKey(new(package.Package.Id, package.Package.Version)))
|
||||||
|
throw new KeyNotFoundException($"Package {package.Package} not found in root dependencies manifest");
|
||||||
|
|
||||||
|
return new Dependency(package.Package.Id, new(package.Package.Version));
|
||||||
|
}
|
||||||
|
|
||||||
private static BuiltInPackage FromAssembly<T>(NuGetFramework runtimeFramework, ImmutableArray<Dependency>? dependencies = null, string? id = null, NuGetVersion? version = null)
|
private static BuiltInPackage FromAssembly<T>(NuGetFramework runtimeFramework, ImmutableArray<Dependency>? dependencies = null, string? id = null, NuGetVersion? version = null)
|
||||||
{
|
{
|
||||||
|
@@ -10,7 +10,7 @@ public class FrameworkJsonConverter(FrameworkNameFormat format) : JsonConverter<
|
|||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType != JsonTokenType.String)
|
||||||
throw new JsonException("Invalid framework string");
|
throw new JsonException("Invalid framework string");
|
||||||
|
|
||||||
var s = reader.GetString()!;
|
var s = reader.GetString()!;
|
||||||
return format switch
|
return format switch
|
||||||
{
|
{
|
||||||
|
@@ -8,7 +8,7 @@ public class ManifestPackageKeyJsonConverter : JsonConverter<ManifestPackageKey>
|
|||||||
{
|
{
|
||||||
public override ManifestPackageKey Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override ManifestPackageKey Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.String)
|
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
||||||
throw new JsonException("Invalid package key string");
|
throw new JsonException("Invalid package key string");
|
||||||
|
|
||||||
return ManifestPackageKey.Parse(reader.GetString()!);
|
return ManifestPackageKey.Parse(reader.GetString()!);
|
||||||
|
29
NuGet/Converters/RuntimeFrameworkJsonConverter.cs
Normal file
29
NuGet/Converters/RuntimeFrameworkJsonConverter.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using NuGet.Models;
|
||||||
|
|
||||||
|
namespace NuGet.Converters;
|
||||||
|
|
||||||
|
public class RuntimeFrameworkJsonConverter : JsonConverter<NuGetRuntimeFramework>
|
||||||
|
{
|
||||||
|
public override NuGetRuntimeFramework Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType is not (JsonTokenType.String or JsonTokenType.PropertyName))
|
||||||
|
throw new JsonException("Invalid runtime framework string");
|
||||||
|
|
||||||
|
return NuGetRuntimeFramework.Parse(reader.GetString()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, NuGetRuntimeFramework value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override NuGetRuntimeFramework ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert,
|
||||||
|
JsonSerializerOptions options) => Read(ref reader, typeToConvert, options);
|
||||||
|
|
||||||
|
public override void WriteAsPropertyName(Utf8JsonWriter writer, NuGetRuntimeFramework value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName(value.ToString());
|
||||||
|
}
|
||||||
|
}
|
@@ -10,9 +10,10 @@ using NuGet.Versioning;
|
|||||||
|
|
||||||
namespace NuGet.Deps;
|
namespace NuGet.Deps;
|
||||||
|
|
||||||
public record DependenciesManifest(RuntimeTarget RuntimeTarget,
|
public record DependenciesManifest(
|
||||||
ImmutableDictionary<NuGetFramework, string> CompilationOptions,
|
RuntimeTarget RuntimeTarget,
|
||||||
ImmutableDictionary<NuGetFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>> Targets,
|
ImmutableDictionary<NuGetRuntimeFramework, string> CompilationOptions,
|
||||||
|
ImmutableDictionary<NuGetRuntimeFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>> Targets,
|
||||||
ImmutableDictionary<ManifestPackageKey, DependencyLibrary> Libraries);
|
ImmutableDictionary<ManifestPackageKey, DependencyLibrary> Libraries);
|
||||||
|
|
||||||
public record DependencyLibrary(
|
public record DependencyLibrary(
|
||||||
@@ -26,7 +27,9 @@ public record DependencyLibrary(
|
|||||||
public enum LibraryType
|
public enum LibraryType
|
||||||
{
|
{
|
||||||
Project,
|
Project,
|
||||||
Package
|
Package,
|
||||||
|
Reference,
|
||||||
|
Runtimepack
|
||||||
}
|
}
|
||||||
|
|
||||||
public record DependencyTarget(ImmutableDictionary<string, NuGetVersion>? Dependencies,
|
public record DependencyTarget(ImmutableDictionary<string, NuGetVersion>? Dependencies,
|
||||||
@@ -39,7 +42,7 @@ public record Dependency(Version? FileVersion = null);
|
|||||||
|
|
||||||
public record RuntimeDependency(Version? AssemblyVersion = null, Version? FileVersion = null) : Dependency(FileVersion);
|
public record RuntimeDependency(Version? AssemblyVersion = null, Version? FileVersion = null) : Dependency(FileVersion);
|
||||||
|
|
||||||
public record RuntimeTarget([property: JsonPropertyName("name")] NuGetFramework Framework, string Signature = "");
|
public record RuntimeTarget([property: JsonPropertyName("name")] NuGetRuntimeFramework RuntimeFramework, string Signature = "");
|
||||||
|
|
||||||
[JsonConverter(typeof(ManifestPackageKeyJsonConverter))]
|
[JsonConverter(typeof(ManifestPackageKeyJsonConverter))]
|
||||||
public record ManifestPackageKey(string Id, NuGetVersion Version)
|
public record ManifestPackageKey(string Id, NuGetVersion Version)
|
||||||
@@ -56,7 +59,7 @@ public record ManifestPackageKey(string Id, NuGetVersion Version)
|
|||||||
public override string ToString() => $"{Id}/{Version}";
|
public override string ToString() => $"{Id}/{Version}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSourceMapping packageSources, Func<Models.Dependency, CatalogEntry?> catalogEntryResolver)
|
public static class DependencyManifestSerializer
|
||||||
{
|
{
|
||||||
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
|
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
|
||||||
{
|
{
|
||||||
@@ -68,8 +71,15 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
new VersionJsonConverter()
|
new VersionJsonConverter()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static Task SerializeAsync(Stream stream, DependenciesManifest manifest) => JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions);
|
||||||
|
|
||||||
|
public static ValueTask<DependenciesManifest> DeserializeAsync(Stream stream) => JsonSerializer.DeserializeAsync<DependenciesManifest>(stream, SerializerOptions)!;
|
||||||
|
}
|
||||||
|
|
||||||
public async ValueTask WriteDependencyManifestAsync(Stream stream, CatalogEntry catalogEntry, NuGetFramework targetFramework)
|
public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSourceMapping packageSources, Func<Models.Dependency, CatalogEntry?> catalogEntryResolver)
|
||||||
|
{
|
||||||
|
public async ValueTask WriteDependencyManifestAsync(Stream stream, CatalogEntry catalogEntry, NuGetRuntimeFramework targetFramework)
|
||||||
{
|
{
|
||||||
var runtimeTarget = new RuntimeTarget(targetFramework);
|
var runtimeTarget = new RuntimeTarget(targetFramework);
|
||||||
|
|
||||||
@@ -77,21 +87,22 @@ public class DependencyManifestBuilder(DirectoryInfo cacheDirectory, PackageSour
|
|||||||
|
|
||||||
await MapCatalogEntryAsync(catalogEntry, targetFramework, targets);
|
await MapCatalogEntryAsync(catalogEntry, targetFramework, targets);
|
||||||
|
|
||||||
var manifest = new DependenciesManifest(runtimeTarget, ImmutableDictionary<NuGetFramework, string>.Empty,
|
var manifest = new DependenciesManifest(runtimeTarget, ImmutableDictionary<NuGetRuntimeFramework, string>.Empty,
|
||||||
ImmutableDictionary<NuGetFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>>.Empty
|
ImmutableDictionary<NuGetRuntimeFramework, ImmutableDictionary<ManifestPackageKey, DependencyTarget>>.Empty
|
||||||
.Add(targetFramework, targets.ToImmutable()),
|
.Add(targetFramework, targets.ToImmutable()),
|
||||||
ImmutableDictionary<ManifestPackageKey, DependencyLibrary>.Empty);
|
ImmutableDictionary<ManifestPackageKey, DependencyLibrary>.Empty);
|
||||||
|
|
||||||
await JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions);
|
await DependencyManifestSerializer.SerializeAsync(stream, manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task MapCatalogEntryAsync(CatalogEntry catalogEntry, NuGetFramework targetFramework,
|
private async Task MapCatalogEntryAsync(CatalogEntry catalogEntry, NuGetRuntimeFramework targetFramework,
|
||||||
ImmutableDictionary<ManifestPackageKey, DependencyTarget>.Builder targets)
|
ImmutableDictionary<ManifestPackageKey, DependencyTarget>.Builder targets)
|
||||||
{
|
{
|
||||||
if (targets.ContainsKey(new(catalogEntry.Id, catalogEntry.Version)) || !catalogEntry.DependencyGroups.HasValue)
|
if (targets.ContainsKey(new(catalogEntry.Id, catalogEntry.Version)) || !catalogEntry.DependencyGroups.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var nearest = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, targetFramework,
|
// TODO take into account the target framework runtime identifier
|
||||||
|
var nearest = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups.Value, targetFramework.Framework,
|
||||||
group => group.TargetFramework);
|
group => group.TargetFramework);
|
||||||
|
|
||||||
if (nearest is null)
|
if (nearest is null)
|
||||||
|
27
NuGet/Models/NuGetRuntimeFramework.cs
Normal file
27
NuGet/Models/NuGetRuntimeFramework.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using NuGet.Converters;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace NuGet.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a NuGetFramework with a runtime identifier
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(RuntimeFrameworkJsonConverter))]
|
||||||
|
public record NuGetRuntimeFramework(NuGetFramework Framework, string? RuntimeIdentifier)
|
||||||
|
{
|
||||||
|
public static NuGetRuntimeFramework Parse(string str)
|
||||||
|
{
|
||||||
|
var index = str.IndexOf('/');
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
return new NuGetRuntimeFramework(NuGetFramework.Parse(str), null);
|
||||||
|
|
||||||
|
return new NuGetRuntimeFramework(NuGetFramework.Parse(str[..index]), str[(index + 1)..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(RuntimeIdentifier) ? Framework.ToString() : $"{Framework}/{RuntimeIdentifier}";
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user