feat: Add installing

It can install now.
Requires pexec to be present

This may be due to an upstream issue with spectre.console affecting how
stdin/stdout are handled.

TODO:
 - Add backup/restore functionality
 - Refactor sections for neatness
 - Improve UX
This commit is contained in:
Robert Morrison 2023-06-08 11:22:00 +01:00
parent 60e06b2144
commit 79063f97ee
Signed by: robert
GPG Key ID: 73E012EB3F4EC696
3 changed files with 84 additions and 41 deletions

View File

@ -123,7 +123,7 @@ sealed class DebEntry
throw new ArgumentException("buffer too short");
}
name = Encoding.ASCII.GetString(buffer[0..16]);
name = Encoding.ASCII.GetString(buffer[0..16]).Trim(); // Trim any trailing whitespace
mtime = long.Parse(Encoding.ASCII.GetString(buffer[16..28]));
mode = int.Parse(Encoding.ASCII.GetString(buffer[28..34]));
gid = int.Parse(Encoding.ASCII.GetString(buffer[34..40]));

View File

@ -3,6 +3,9 @@ using Serilog;
using Spectre.Console;
using System.Text.Json;
using System.Text;
using SharpCompress.Compressors.Xz;
using System.Formats.Tar;
using System.Diagnostics;
namespace EdgeInstaller;
@ -222,15 +225,12 @@ public static partial class EdgeInstall
RenderPackageAsTable(LatestVersion);
var versionPath = LatestVersion.Filename
.Replace("pool/main/m/", "")
.Replace(".deb", "");
var versionsDir = Path.Join(Archdir, "Versions");
var versionDir = Path.Join(versionsDir, LatestVersion.PackageName, LatestVersion.Version.ToString());
Directory.CreateDirectory(versionDir);
// Let's get and unpack the latest version
if (true)//!Directory.Exists(Path.Join(versionsDir, versionPath)))
{
// for the moment we will always just grab
using (MemoryStream debStream =
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
@ -257,37 +257,80 @@ public static partial class EdgeInstall
using (DebFile debfile = new DebFile(debStream))
{
foreach (var fileEntry in debfile.fileEntries)
{
AnsiConsole.MarkupLineInterpolated($"FileName: {fileEntry.name}");
AnsiConsole.MarkupLineInterpolated($"FilePos: {fileEntry.offset}");
AnsiConsole.MarkupLineInterpolated($"FileSize: {fileEntry.sizeBytes}");
// NOTE: This is dumb test code
// to verify the files are actually being "extracted" properly
// NOTE: deb entries have trailing /
DebEntry? dataEntry = debfile.fileEntries.Find(file => file.name == "data.tar.xz/");
if (!debfile.getFile(fileEntry, out Stream contents))
if (dataEntry is null)
{
return 1;
AnsiConsole.MarkupLine("[red b]ERROR:[/] debfile does not contain data.tar.xz");
Environment.Exit(1);
}
// Now we write this to tmp.
// WARN: Without deleting these you will fill up your ram
// Looks like we have a hit. Lets try and extract it
var temp = Path.GetTempFileName();
using (var tmpfile = File.Open(temp, FileMode.Open))
if (!debfile.getFile(dataEntry, out Stream dataStream))
{
contents.CopyTo(tmpfile);
contents.Dispose();
AnsiConsole.MarkupLine("[red b]ERROR:[/] couldn't get stream for data.tar.xz");
Environment.Exit(1);
}
using (XZStream dataXZStream = new(dataStream))
{
using (TarReader reader = new(dataXZStream))
{
while (true)
{
var tarEntry = reader.GetNextEntry();
if (tarEntry is null)
{
break; // TarReader returns null when we hit the end of the stream
}
AnsiConsole.MarkupLineInterpolated($"TarEntry {tarEntry.Name}");
// work out where we need to put the extracted file
var filepath = Path.Combine(versionDir, tarEntry.Name);
if (tarEntry.EntryType == TarEntryType.Directory)
{
// createDirectory doesn't fail if already exists
Directory.CreateDirectory(filepath);
continue;
}
if (tarEntry.LinkName != "")
{
// Handle links manually
if (File.Exists(filepath))
{
File.Delete(filepath);
}
File.CreateSymbolicLink(filepath, tarEntry.LinkName);
continue; // we are done with this file so keep going
}
tarEntry.ExtractToFile(filepath, overwrite: true);
}
}
}
// Now assuming nothing broke before now we can copy the files into the system directories.
// WARN: This is dangerous stuff and involves making system calls.
// NOTE: be sure when calling to other programs to wait until they exit.
var Mover = new ProcessStartInfo();
Mover.FileName = "pkexec";
Mover.Arguments = $"cp -dri {versionDir}/opt {versionDir}/usr /";
Mover.UseShellExecute = true;
var pr = Process.Start(Mover);
pr?.WaitForExit();
}
}
return 0;
}
}
/*TODO:
- Check version
- Offer update

View File

@ -9,9 +9,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CST.RecursiveExtractor" Version="1.2.13" />
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="SharpCompress" Version="0.33.0" />
<PackageReference Include="Spectre.Console" Version="0.47.0" />
<PackageReference Include="System.Commandline" Version="2.0.0-beta4.22272.1" />
</ItemGroup>