edge-install/ReleaseData.cs
Robert Morrison f650e6a3c9 HELL COMMIT
Commit sins to add all code into repo
2023-05-28 15:11:41 +01:00

135 lines
4.9 KiB
C#

// TODO: Refactor to be more like Package code. This is messy
// Substring should be replaced with a .split(": ")
// Also Directly assign to the values instead of using temporary variables.
using Serilog;
using System.Text.Json.Serialization;
namespace EdgeInstaller;
sealed class ReleaseData
{
public DateTime Date { get; private set; }
public List<string> Architectures { get; private set; }
public List<PackageFile> PackageFiles { get; private set; }
[JsonConstructor]
public ReleaseData(DateTime date, List<string> architectures, List<PackageFile> packageFiles)
{
this.Date = date;
this.Architectures = architectures;
this.PackageFiles = packageFiles;
}
public ReleaseData(string Release)
{
Log.Information("Creating new ReleaseData object");
if (Release == "")
{
throw new ArgumentException(
message: "Empty release provided to ReleaseData",
paramName: "Release");
}
Architectures = new();
PackageFiles = new();
// Pull release apart
List<string> ReleaseLines = Release.Split("\n", StringSplitOptions.RemoveEmptyEntries).ToList();
Log.Debug("ReleaseLines = {@releaselines}", ReleaseLines);
// Safely find and parse the Date field
string DateLine =
ReleaseLines.Where(
Line => Line.Contains("Date:"))
.FirstOrDefault("").Substring(5);
Log.Debug("DateLine = {DateLine}", DateLine);
if (DateTime.TryParse(DateLine, out DateTime result))
{
Log.Debug("Extracted date {@date}", result);
Date = result;
}
else
{
throw _lineFormatException("date");
}
// Safely find and add the possible architectures
string ArchitecturesLine =
ReleaseLines.Where(
Line => Line.Contains("Architectures:"))
.FirstOrDefault("");
Log.Debug("Arch line: {archline}", ArchitecturesLine);
if (ArchitecturesLine == "")
{
throw _lineFormatException("architectures");
}
Architectures = ArchitecturesLine
.Substring(ArchitecturesLine.IndexOf(":") + 1) // We only want items after the label
.Split(" ", StringSplitOptions.RemoveEmptyEntries) // Space delimited list
.ToList(); // Convert to the superior collection type
Log.Debug("Extracted architectures {@architectures}", Architectures);
// Time to process the package files.. This is gonna be fun..
// WARNING: this code is a little hacky
// scope for possible optimisation
// First split the Lines to only get the file data
List<string> SHA256FileData = ReleaseLines.Where((value, index) =>
index > ReleaseLines.IndexOf("SHA256:") && index < ReleaseLines.IndexOf("SHA512:")
).ToList();
Log.Debug("SHA256FileData = {@data}", SHA256FileData);
// Now process these lines to get the data we need
List<PackageFile> releasePackageFiles = new();
foreach (var fileData in SHA256FileData)
{
Log.Debug("fileData = {filedata}", fileData);
string[] splitData = fileData.Split(' ', StringSplitOptions.RemoveEmptyEntries);
Log.Debug("splitData = {@splitData}", splitData);
string checksum = splitData[0];
int size = int.Parse(splitData[1]);
string filename = splitData[2];
releasePackageFiles.Add(new PackageFile(filename, checksum, size));
}
// remove any empty files (and the .gz version of them)
// NOTE: I do this since empty gz files have a size
// WARN: The `.ToList` is essential to ensure we COPY the list and not use references to the original items
var emptyFiles = releasePackageFiles.Where(package => package.size == 0).ToList();
foreach (var file in emptyFiles)
{
releasePackageFiles.RemoveAll(package =>
package.filename == file.filename ||
package.filename == $"{file.filename}.gz"
);
}
PackageFiles = releasePackageFiles;
// After removing the empty files we need to make sure that we remove the architectures that don't have any files
foreach (var arch in Architectures.ToList())
// WARN: `.ToList` is used again to copy the list so we can iterate and operate
{
if (PackageFiles.Where(file => file.filename.Contains(arch)).Count() == 0)
{
Architectures.Remove(arch);
}
}
}
private static FormatException _lineFormatException(string field)
{
return new FormatException($"Release does not contain a valid {field} line");
}
}
public record PackageFile(string filename, string Checksum, int size);