135 lines
4.9 KiB
C#
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);
|