Add TShock.Installer to download dotnet runtime

This will include a new ./TShock.Installer executable that will be for users without the dotnet runtime. This program will download the dotnet runtime, extract it, and then run ./TShock.Server for them using the downloaded runtime.

Note: only tested on osx, likely a no-go for linux/windows until more testing occurs.
This commit is contained in:
Luke 2022-11-17 00:27:14 +10:00
parent 5d84192624
commit 45a378b0f0
4 changed files with 136 additions and 0 deletions

View file

@ -0,0 +1,93 @@
using System.Diagnostics;
using System.IO.Compression;
using System.Runtime.InteropServices;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
Console.WriteLine($"TShock Installer {typeof(Program).GetType().Assembly.GetName().Version}.");
// reference: https://github.com/dotnet/install-scripts/blob/main/src/dotnet-install.sh
// ./dotnet-install.sh -verbose -version 6.0.11 --runtime dotnet
Console.WriteLine("Determining dotnet runtime url...");
string? url = null;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
url = "https://dotnetcli.azureedge.net/dotnet/Runtime/6.0.11/dotnet-runtime-6.0.11-osx-x64.tar.gz";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
url = "https://dotnetcli.azureedge.net/dotnet/Runtime/6.0.11/dotnet-runtime-6.0.11-win-x64.zip";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
url = "https://dotnetcli.azureedge.net/dotnet/Runtime/6.0.11/dotnet-runtime-6.0.11-linux-x64.tar.gz";
if(url is null)
{
Console.WriteLine("Unable to determine .net runtime to install. " +
"Refer to https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script " +
"and install using --install-dir dotnet, so that the dotnet folder is beside TShock.Server.dll");
return;
}
Console.WriteLine("Using url: " + url);
var filename = url.Split('/').Last();
var is_targz = filename.EndsWith(".tar.gz");
var download_info = new FileInfo(filename);
if (!download_info.Exists) // todo hash check
{
Console.WriteLine($"Downloading: {filename}...");
using var client = new HttpClient();
using var resp = await client.GetStreamAsync(url);
using var fs = new FileStream(filename, FileMode.Create);
await resp.CopyToAsync(fs);
}
else
{
Console.WriteLine("Using existing download on disk: " + filename);
}
var dotnet_path = Path.Combine("dotnet", "dotnet" + (is_targz ? "" : ".exe"));
var tshock_path = "TShock.Server" + (is_targz ? "" : ".exe");
if (!File.Exists(dotnet_path))
{
Console.WriteLine("Extracting to ./dotnet/");
if (is_targz)
{
using var srm_dotnet_file = File.OpenRead(filename);
using var srm_gzip = new GZipInputStream(srm_dotnet_file);
using var tar_archive = TarArchive.CreateInputTarArchive(srm_gzip, System.Text.Encoding.UTF8);
tar_archive.ExtractContents("dotnet");
[DllImport("libc", SetLastError = true)]
static extern int chmod(string pathname, int mode);
chmod(dotnet_path, 755);
}
else
{
ZipFile.ExtractToDirectory(filename, "dotnet");
}
}
else
{
Console.WriteLine($"Extract skipped, existing found at: {dotnet_path}");
}
var dotnet_root = System.IO.Path.GetFullPath("dotnet");
Console.WriteLine($"To be able to run {tshock_path} yourself set the environment variable DOTNET_ROOT={dotnet_root}");
Environment.SetEnvironmentVariable("DOTNET_ROOT", dotnet_root);
Console.WriteLine($"Extracted, launching: {tshock_path}");
var proc = new Process();
proc.StartInfo = new()
{
FileName = tshock_path,
};
foreach (var arg in args)
proc.StartInfo.ArgumentList.Add(arg);
proc.Start();
await proc.WaitForExitAsync();