using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; using Nebula.Shared.Utils; namespace Nebula.Shared.Services; [ServiceRegister] public class DotnetResolverService(DebugService debugService, ConfigurationService configurationService) { private string FullPath => Path.Join(FileService.RootPath, $"dotnet.{configurationService.GetConfigValue(CurrentConVar.DotnetVersion)}", DotnetUrlHelper.GetRuntimeIdentifier()); private string ExecutePath => Path.Join(FullPath, "dotnet" + DotnetUrlHelper.GetExtension()); private readonly HttpClient _httpClient = new(); public async Task EnsureDotnet() { if (!Directory.Exists(FullPath)) await Download(); return ExecutePath; } private async Task Download() { var debugLogger = debugService.GetLogger(this); debugLogger.Log($"Downloading dotnet {DotnetUrlHelper.GetRuntimeIdentifier()}..."); var url = DotnetUrlHelper.GetCurrentPlatformDotnetUrl( configurationService.GetConfigValue(CurrentConVar.DotnetUrl)! ); using var response = await _httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); await using var stream = await response.Content.ReadAsStreamAsync(); Directory.CreateDirectory(FullPath); if (url.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) { using var zipArchive = new ZipArchive(stream); zipArchive.ExtractToDirectory(FullPath, true); } else if (url.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase) || url.EndsWith(".tgz", StringComparison.OrdinalIgnoreCase)) { TarUtils.ExtractTarGz(stream, FullPath); } else { throw new NotSupportedException("Unsupported archive format."); } debugLogger.Log("Downloading dotnet complete."); } } public static class DotnetUrlHelper { [Obsolete("FOR TEST USING ONLY!")] public static string? RidOverrideTest = null; // FOR TEST PURPOSES ONLY!!! public static string GetExtension() { if (OperatingSystem.IsWindows()) return ".exe"; return ""; } public static string GetCurrentPlatformDotnetUrl(Dictionary dotnetUrl) { var rid = GetRuntimeIdentifier(); if (dotnetUrl.TryGetValue(rid, out var url)) return url; throw new PlatformNotSupportedException($"No download URL available for the current platform: {rid}"); } public static string GetRuntimeIdentifier() { if(RidOverrideTest != null) return RidOverrideTest; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return Environment.Is64BitProcess ? "win-x64" : "win-x86"; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return "linux-x64"; throw new PlatformNotSupportedException("Unsupported operating system"); } }