wabbajack/Wabbajack.Lib/ReportBuilder.cs

130 lines
5.0 KiB
C#
Raw Normal View History

2019-08-31 05:07:31 +00:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Wabbajack.Common;
using Wabbajack.Lib.NexusApi;
using File = Alphaleonis.Win32.Filesystem.File;
using Path = Alphaleonis.Win32.Filesystem.Path;
2019-08-31 05:07:31 +00:00
namespace Wabbajack.Lib
2019-08-31 05:07:31 +00:00
{
public class ReportBuilder : IDisposable
{
2019-09-14 04:35:42 +00:00
private const int WRAP_SIZE = 80;
private readonly StreamWriter wtr;
private string _output_folder;
2019-09-14 04:35:42 +00:00
public ReportBuilder(Stream str, string output_folder)
2019-08-31 05:07:31 +00:00
{
_output_folder = output_folder;
2019-08-31 05:07:31 +00:00
wtr = new StreamWriter(str);
}
2019-09-14 04:35:42 +00:00
public void Dispose()
{
wtr.Flush();
wtr?.Dispose();
}
2019-08-31 05:07:31 +00:00
public void Text(string txt)
{
2019-09-14 04:35:42 +00:00
var offset = 0;
2019-08-31 05:07:31 +00:00
while (offset + WRAP_SIZE < txt.Length)
{
wtr.WriteLine(txt.Substring(offset, WRAP_SIZE));
offset += WRAP_SIZE;
}
2019-09-14 04:35:42 +00:00
if (offset < txt.Length) wtr.WriteLine(txt.Substring(offset, txt.Length - offset));
2019-08-31 05:07:31 +00:00
}
public void NoWrapText(string txt)
{
wtr.WriteLine(txt);
}
2019-10-01 23:06:15 +00:00
public void Build(Compiler c, ModList lst)
2019-08-31 05:07:31 +00:00
{
Text($"### {lst.Name} by {lst.Author} - Installation Summary");
2019-10-23 17:00:45 +00:00
Text($"Build with Wabbajack Version {lst.WabbajackVersion}");
Text(lst.Description);
Text($"#### Website:");
NoWrapText($"[{lst.Website}]({lst.Website})");
2019-10-01 23:06:15 +00:00
var readme_file = Path.Combine(c.MO2ProfileDir, "readme.md");
if (File.Exists(readme_file))
File.ReadAllLines(readme_file)
.Do(NoWrapText);
2019-09-14 04:35:42 +00:00
Text(
$"#### Download Summary ({lst.Archives.Count} archives - {lst.Archives.Sum(a => a.Size).ToFileSizeString()})");
2019-08-31 05:07:31 +00:00
foreach (var archive in SortArchives(lst.Archives))
{
var hash = archive.Hash.FromBase64().ToHEX();
NoWrapText(archive.State.GetReportEntry(archive));
NoWrapText($" * Size : {archive.Size.ToFileSizeString()}");
NoWrapText($" * SHA256 : [{hash}](https://www.virustotal.com/gui/file/{hash})");
2019-08-31 05:07:31 +00:00
}
2019-09-14 04:35:42 +00:00
Text("\n\n");
2019-08-31 05:07:31 +00:00
var patched = lst.Directives.OfType<PatchedFromArchive>().OrderBy(p => p.To).ToList();
Text($"#### Summary of ({patched.Count}) patches");
foreach (var directive in patched)
2019-09-14 04:35:42 +00:00
NoWrapText(
$"* Applying {SizeForID(directive.PatchID)} byte patch `{directive.FullPath}` to create `{directive.To}`");
2019-09-14 04:35:42 +00:00
2019-08-31 05:07:31 +00:00
var files = lst.Directives.OrderBy(d => d.To).ToList();
Text($"\n\n### Install Plan of ({files.Count}) files");
2019-09-14 04:35:42 +00:00
Text("(ignoring files that are directly copied from archives or listed in the patches section above)");
2019-09-02 22:36:57 +00:00
foreach (var directive in files.OrderBy(f => f.GetType().Name).ThenByDescending(f => f.To))
2019-08-31 05:07:31 +00:00
switch (directive)
{
2019-10-11 11:09:34 +00:00
case PropertyFile i:
NoWrapText($"* `{i.SourceDataID}` as a `{Enum.GetName(typeof(PropertyType),i.Type)}`");
2019-10-11 11:09:34 +00:00
break;
2019-08-31 05:07:31 +00:00
case FromArchive f:
//NoWrapText($"* `{f.To}` from `{f.FullPath}`");
break;
case CleanedESM i:
NoWrapText($"* `{i.To}` by applying a patch to a game ESM ({i.SourceESMHash})");
break;
case RemappedInlineFile i:
2019-09-02 22:36:57 +00:00
NoWrapText($"* `{i.To}` by remapping the contents of an inline file");
2019-08-31 05:07:31 +00:00
break;
case InlineFile i:
NoWrapText($"* `{i.To}` from `{SizeForID(i.SourceDataID).ToFileSizeString()}` file included in modlist");
2019-08-31 05:07:31 +00:00
break;
case CreateBSA i:
2019-09-14 04:35:42 +00:00
NoWrapText(
$"* `{i.To}` by creating a BSA of files found in `{Consts.BSACreationDir}\\{i.TempID}`");
2019-08-31 05:07:31 +00:00
break;
}
var inlined = lst.Directives.OfType<InlineFile>()
.Select(f => (f.To, "inlined", SizeForID(f.SourceDataID)))
.Concat(lst.Directives
.OfType<PatchedFromArchive>()
.Select(f => (f.To, "patched", SizeForID(f.PatchID))))
.ToHashSet()
.OrderByDescending(f => f.Item3);
NoWrapText("\n\n### Summary of inlined files in this installer");
foreach (var inline in inlined)
{
NoWrapText($"* {inline.Item3.ToFileSizeString()} for {inline.Item2} file {inline.To}");
}
2019-08-31 05:07:31 +00:00
}
private long SizeForID(string id)
{
return File.GetSize(Path.Combine(_output_folder, id));
}
2019-08-31 05:07:31 +00:00
private IEnumerable<Archive> SortArchives(List<Archive> lstArchives)
{
2019-10-13 03:06:44 +00:00
return lstArchives.OrderByDescending(a => a.Size);
2019-08-31 05:07:31 +00:00
}
}
2019-09-14 04:35:42 +00:00
}