From b79830ad54a78628127465d69af78b2e7a869460 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Wed, 9 Dec 2020 14:46:08 -0700 Subject: [PATCH] Added purge-archive verb --- Wabbajack.CLI/OptionsDefinition.cs | 3 +- Wabbajack.CLI/Verbs/PurgeArchive.cs | 65 ++++++++++++++++++++++++++ Wabbajack.Common/Paths/AbsolutePath.cs | 2 +- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 Wabbajack.CLI/Verbs/PurgeArchive.cs diff --git a/Wabbajack.CLI/OptionsDefinition.cs b/Wabbajack.CLI/OptionsDefinition.cs index 3eba22bd..cb61728d 100644 --- a/Wabbajack.CLI/OptionsDefinition.cs +++ b/Wabbajack.CLI/OptionsDefinition.cs @@ -34,7 +34,8 @@ namespace Wabbajack.CLI typeof(ExportServerGameFiles), typeof(HashGamefiles), typeof(Backup), - typeof(Restore) + typeof(Restore), + typeof(PurgeArchive) }; } } diff --git a/Wabbajack.CLI/Verbs/PurgeArchive.cs b/Wabbajack.CLI/Verbs/PurgeArchive.cs new file mode 100644 index 00000000..e005dbaf --- /dev/null +++ b/Wabbajack.CLI/Verbs/PurgeArchive.cs @@ -0,0 +1,65 @@ +using System.IO.Compression; +using System.Linq; +using System.Threading.Tasks; +using CommandLine; +using Wabbajack.Common; +using Wabbajack.Lib; + +namespace Wabbajack.CLI.Verbs +{ + [Verb("purge-archive", HelpText = "Purges an archive and all directives from a .wabbajack file")] + public class PurgeArchive : AVerb + { + [Option('i', "input", Required = true, HelpText = "Input .wabbajack file")] + public string Input { get; set; } = ""; + private AbsolutePath _Input => (AbsolutePath)Input; + + [Option('o', "output", Required = true, HelpText = "Output .wabbajack file")] + public string Output { get; set; } = ""; + private AbsolutePath _Output => (AbsolutePath)Output; + + [Option('h', "hash", Required = true, HelpText = "Hash to purge")] + public string ArchiveHash { get; set; } = ""; + private Hash _Hash => Hash.Interpret(ArchiveHash); + + protected override async Task Run() + { + Utils.Log("Copying .wabbajack file"); + await _Input.CopyToAsync(_Output); + + Utils.Log("Loading modlist"); + + await using var fs = await _Output.OpenWrite(); + using var ar = new ZipArchive(fs, ZipArchiveMode.Update); + ModList modlist; + await using (var entry = ar.Entries.First(e => e.Name == "modlist").Open()) + { + modlist = entry.FromJson(); + } + + Utils.Log("Purging archives"); + modlist.Archives = modlist.Archives.Where(a => a.Hash != _Hash).ToList(); + modlist.Directives = modlist.Directives.Select(d => + { + if (d is FromArchive a) + { + if (a.ArchiveHashPath.BaseHash == _Hash) return (false, d); + } + return (true, d); + }).Where(d => d.Item1) + .Select(d => d.d) + .ToList(); + + Utils.Log("Writing modlist"); + + await using (var entry = ar.Entries.First(e => e.Name == "modlist").Open()) + { + entry.SetLength(0); + entry.Position = 0; + modlist.ToJson(entry); + } + + return ExitCode.Ok; + } + } +} diff --git a/Wabbajack.Common/Paths/AbsolutePath.cs b/Wabbajack.Common/Paths/AbsolutePath.cs index e7f4a5c6..26d8a27e 100644 --- a/Wabbajack.Common/Paths/AbsolutePath.cs +++ b/Wabbajack.Common/Paths/AbsolutePath.cs @@ -95,7 +95,7 @@ namespace Wabbajack.Common public ValueTask OpenWrite() { var path = _path; - return CircuitBreaker.WithAutoRetryAsync(async () => File.OpenWrite(path)); + return CircuitBreaker.WithAutoRetryAsync(async () => File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite)); } public async Task WriteAllTextAsync(string text)