feature: first
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 2m47s
Build / Build Nuget package (CringePlugins) (push) Successful in 5m31s
Build / Build Nuget package (NuGet) (push) Successful in 6m2s
Build / Build Nuget package (SharedCringe) (push) Successful in 7m25s
Build / Build Launcher (push) Successful in 9m11s
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 2m47s
Build / Build Nuget package (CringePlugins) (push) Successful in 5m31s
Build / Build Nuget package (NuGet) (push) Successful in 6m2s
Build / Build Nuget package (SharedCringe) (push) Successful in 7m25s
Build / Build Launcher (push) Successful in 9m11s
This commit is contained in:
78
CringePlugins/Resolver/BuiltInPackages.cs
Normal file
78
CringePlugins/Resolver/BuiltInPackages.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Reflection;
|
||||
using Basic.Reference.Assemblies;
|
||||
using CringePlugins.Loader;
|
||||
using CringePlugins.Utils;
|
||||
using dnlib.DotNet;
|
||||
using ImGuiNET;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using NLog;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Models;
|
||||
using NuGet.Versioning;
|
||||
using Sandbox.Game;
|
||||
using SpaceEngineers.Game;
|
||||
using VRage.Utils;
|
||||
|
||||
namespace CringePlugins.Resolver;
|
||||
|
||||
public static class BuiltInPackages
|
||||
{
|
||||
private const string SeReferenceAssemblies = "SpaceEngineersDedicated.ReferenceAssemblies";
|
||||
private const string ImGui = "ImGui.NET.DirectX";
|
||||
|
||||
public static ImmutableArray<ResolvedPackage> GetPackages(NuGetFramework runtimeFramework)
|
||||
{
|
||||
var nlog = FromAssembly<LogFactory>(runtimeFramework, version: new(5, 3, 4));
|
||||
Version seVersion = new MyVersion(MyPerGameSettings.BasicGameInfo.GameVersion!.Value);
|
||||
|
||||
var se = FromAssembly<SpaceEngineersGame>(runtimeFramework, [
|
||||
nlog.AsDependency()
|
||||
], SeReferenceAssemblies, new(seVersion));
|
||||
var imGui = FromAssembly<ImGuiKey>(runtimeFramework, id: ImGui);
|
||||
|
||||
BuiltInSdkPackage MapSdkPackage(
|
||||
(string FileName, byte[] ImageBytes, PortableExecutableReference Reference, Guid Mvid) r)
|
||||
{
|
||||
var def = ModuleDefMD.Load(r.ImageBytes, IntrospectionContext.Global.Context);
|
||||
var attribute = def.CustomAttributes.Find(typeof(AssemblyFileVersionAttribute).FullName);
|
||||
var version = attribute is null ? new(99, 0, 0) : NuGetVersion.Parse((string)attribute.ConstructorArguments[0].Value);
|
||||
|
||||
return new BuiltInSdkPackage(
|
||||
new(0, Path.GetFileNameWithoutExtension(r.FileName), version, []), runtimeFramework,
|
||||
new(Path.GetFileNameWithoutExtension(r.FileName), version, [new(runtimeFramework, [])], null, []));
|
||||
}
|
||||
|
||||
return
|
||||
[
|
||||
..Net80.ReferenceInfos.AllValues.Select(MapSdkPackage),
|
||||
..Net80Windows.ReferenceInfos.AllValues.Select(MapSdkPackage),
|
||||
nlog,
|
||||
se,
|
||||
imGui,
|
||||
FromAssembly<PluginsLifetime>(runtimeFramework, [se.AsDependency(), imGui.AsDependency()]),
|
||||
];
|
||||
}
|
||||
|
||||
private static Dependency AsDependency(this ResolvedPackage package) => new(package.Package.Id, new(package.Package.Version));
|
||||
|
||||
private static BuiltInPackage FromAssembly<T>(NuGetFramework runtimeFramework, ImmutableArray<Dependency>? dependencies = null, string? id = null, NuGetVersion? version = null)
|
||||
{
|
||||
var assembly = typeof(T).Assembly.GetName();
|
||||
id ??= assembly.Name!;
|
||||
version ??= new NuGetVersion(assembly.Version ?? new(0, 0, 0));
|
||||
dependencies ??= [];
|
||||
|
||||
return new(
|
||||
new(0, id, version, [..dependencies.Value.Select(b => b.Id)]),
|
||||
runtimeFramework,
|
||||
new(id, version, [
|
||||
new(runtimeFramework, dependencies.Value)
|
||||
], null, [])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public record BuiltInPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry) : ResolvedPackage(Package, ResolvedFramework, Entry);
|
||||
|
||||
public record BuiltInSdkPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry) : BuiltInPackage(Package, ResolvedFramework, Entry);
|
144
CringePlugins/Resolver/PackageResolver.cs
Normal file
144
CringePlugins/Resolver/PackageResolver.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.IO.Compression;
|
||||
using NuGet;
|
||||
using NuGet.Frameworks;
|
||||
using NuGet.Models;
|
||||
using NuGet.Versioning;
|
||||
|
||||
namespace CringePlugins.Resolver;
|
||||
|
||||
public class PackageResolver(NuGetFramework runtimeFramework, ImmutableArray<PackageReference> references, PackageSourceMapping packageSources)
|
||||
{
|
||||
public async Task<ImmutableHashSet<ResolvedPackage>> ResolveAsync()
|
||||
{
|
||||
var order = 0;
|
||||
var packages = new SortedDictionary<Package, CatalogEntry>();
|
||||
|
||||
foreach (var reference in references)
|
||||
{
|
||||
var client = await packageSources.GetClientAsync(reference.Id);
|
||||
|
||||
var registrationRoot = await client.GetPackageRegistrationRootAsync(reference.Id);
|
||||
|
||||
var items = registrationRoot.Items.SelectMany(page =>
|
||||
page.Items.Where(b => b.CatalogEntry.PackageTypes is ["CringePlugin"]))
|
||||
.ToImmutableDictionary(b => b.CatalogEntry.Version);
|
||||
|
||||
var version = reference.Range.FindBestMatch(items.Values.Select(b => b.CatalogEntry.Version));
|
||||
|
||||
if (version is null)
|
||||
throw new Exception($"Unable to find version for package {reference.Id}");
|
||||
|
||||
var package = new Package(order, reference.Id, version, []); // todo resolve dependencies
|
||||
|
||||
if (packages.TryAdd(package, items[version].CatalogEntry))
|
||||
continue;
|
||||
|
||||
if (!packages.TryGetValue(package, out _))
|
||||
throw new Exception($"Duplicate package {package.Id}");
|
||||
|
||||
var existingPackage = packages.Keys.First(b => b.Version == package.Version && b.Id == package.Id);
|
||||
|
||||
if (package.Version < existingPackage.Version)
|
||||
throw new Exception($"Package reference {package.Id} has lower version {package.Version} than already resolved {existingPackage.Version}");
|
||||
|
||||
if (package.Version == existingPackage.Version)
|
||||
continue;
|
||||
|
||||
packages.Remove(existingPackage);
|
||||
packages.Add(package with
|
||||
{
|
||||
Order = ++order
|
||||
}, items[version].CatalogEntry);
|
||||
}
|
||||
|
||||
var set = ImmutableHashSet<ResolvedPackage>.Empty.ToBuilder();
|
||||
foreach (var (package, catalogEntry) in packages)
|
||||
{
|
||||
var client = await packageSources.GetClientAsync(package.Id);
|
||||
|
||||
var nearestGroup = NuGetFrameworkUtility.GetNearest(catalogEntry.DependencyGroups, runtimeFramework,
|
||||
g => g.TargetFramework);
|
||||
|
||||
if (nearestGroup is null)
|
||||
throw new Exception($"Unable to find compatible dependency group for package {package.Id}");
|
||||
|
||||
set.Add(new RemotePackage(package, nearestGroup.TargetFramework, client, catalogEntry));
|
||||
}
|
||||
|
||||
return set.ToImmutable();
|
||||
}
|
||||
|
||||
public async Task<ImmutableHashSet<CachedPackage>> DownloadPackagesAsync(DirectoryInfo baseDirectory,
|
||||
IReadOnlySet<ResolvedPackage> resolvedPackages, IProgress<float>? progress = null)
|
||||
{
|
||||
var packages = ImmutableHashSet<CachedPackage>.Empty.ToBuilder();
|
||||
|
||||
var i = 0f;
|
||||
foreach (var package in resolvedPackages)
|
||||
{
|
||||
switch (package)
|
||||
{
|
||||
case RemotePackage remotePackage:
|
||||
{
|
||||
var dir = new DirectoryInfo(Path.Join(baseDirectory.FullName, package.Package.Id, package.Package.Version.ToString()));
|
||||
if (!dir.Exists)
|
||||
{
|
||||
dir.Create();
|
||||
|
||||
await using var stream = await remotePackage.Client.GetPackageContentStreamAsync(remotePackage.Package.Id, remotePackage.Package.Version);
|
||||
using var memStream = new MemoryStream();
|
||||
await stream.CopyToAsync(memStream);
|
||||
memStream.Position = 0;
|
||||
using var archive = new ZipArchive(memStream, ZipArchiveMode.Read);
|
||||
archive.ExtractToDirectory(dir.FullName);
|
||||
}
|
||||
|
||||
packages.Add(new CachedPackage(package.Package, package.ResolvedFramework, dir, package.Entry));
|
||||
break;
|
||||
}
|
||||
case CachedPackage cachedPackage:
|
||||
packages.Add(cachedPackage);
|
||||
break;
|
||||
}
|
||||
|
||||
progress?.Report(i++ / resolvedPackages.Count);
|
||||
}
|
||||
|
||||
return packages.ToImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
public record CachedPackage(Package Package, NuGetFramework ResolvedFramework, DirectoryInfo Directory, CatalogEntry Entry) : ResolvedPackage(Package, ResolvedFramework, Entry);
|
||||
public record RemotePackage(Package Package, NuGetFramework ResolvedFramework, NuGetClient Client, CatalogEntry Entry) : ResolvedPackage(Package, ResolvedFramework, Entry);
|
||||
|
||||
public abstract record ResolvedPackage(Package Package, NuGetFramework ResolvedFramework, CatalogEntry Entry);
|
||||
|
||||
public record Package(int Order, string Id, NuGetVersion Version, ImmutableArray<string> Dependencies) : IComparable<Package>, IComparable
|
||||
{
|
||||
public int CompareTo(Package? other)
|
||||
{
|
||||
if (ReferenceEquals(this, other)) return 0;
|
||||
if (other is null) return 1;
|
||||
var orderComparison = Order.CompareTo(other.Order);
|
||||
if (orderComparison != 0) return orderComparison;
|
||||
return string.Compare(Id, other.Id, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is null) return 1;
|
||||
if (ReferenceEquals(this, obj)) return 0;
|
||||
return obj is Package other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(Package)}");
|
||||
}
|
||||
|
||||
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Id);
|
||||
|
||||
public virtual bool Equals(Package? other)
|
||||
{
|
||||
if (other is null) return false;
|
||||
return Id.Equals(other.Id, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public record PackageReference(string Id, VersionRange Range);
|
Reference in New Issue
Block a user