From b1eefa6a41cea78f1b5537e71371a4764dad660a Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Tue, 11 Feb 2020 22:31:42 -0700 Subject: [PATCH 1/2] Rename old log files. Don't overwrite downloads with the same name --- Wabbajack.Common/Utils.cs | 20 ++++++++++++++++++-- Wabbajack.Lib/AInstaller.cs | 20 +++++++++++++++----- Wabbajack.Test/DownloaderTests.cs | 5 +++-- Wabbajack.Test/EndToEndTests.cs | 1 - 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index a3cc2e73..a11db29f 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -54,11 +54,15 @@ namespace Wabbajack.Common Directory.CreateDirectory(Consts.LocalAppDataPath); var programName = Assembly.GetEntryAssembly()?.Location ?? "Wabbajack"; - LogFile = Path.GetFileNameWithoutExtension(programName) + DateTime.Now.ToString(" yyyy-MM-dd HH_mm_ss") + ".log"; + LogFile = Path.GetFileNameWithoutExtension(programName) + ".current.log"; _startTime = DateTime.Now; + if (LogFile.FileExists()) - File.Delete(LogFile); + { + var new_path = Path.GetFileNameWithoutExtension(programName) + (new FileInfo(LogFile)).LastWriteTime.ToString(" yyyy-MM-dd HH_mm_ss") + ".log"; + File.Move(LogFile, new_path, MoveOptions.ReplaceExisting); + } var watcher = new FileSystemWatcher(Consts.LocalAppDataPath); AppLocalEvents = Observable.Merge(Observable.FromEventPattern(h => watcher.Changed += h, h => watcher.Changed -= h).Select(e => (FileEventType.Changed, e.EventArgs)), @@ -182,6 +186,18 @@ namespace Wabbajack.Common return sha.Hash.ToBase64(); } + + public static string StringSHA256Hex(this string s) + { + var sha = new SHA256Managed(); + using (var o = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write)) + { + using var i = new MemoryStream(Encoding.UTF8.GetBytes(s)); + i.CopyTo(o); + } + + return sha.Hash.ToHex(); + } public static string FileHash(this string file, bool nullOnIOError = false) { diff --git a/Wabbajack.Lib/AInstaller.cs b/Wabbajack.Lib/AInstaller.cs index c171c760..42acbfc8 100644 --- a/Wabbajack.Lib/AInstaller.cs +++ b/Wabbajack.Lib/AInstaller.cs @@ -258,20 +258,30 @@ namespace Wabbajack.Lib var outputPath = Path.Combine(DownloadFolder, archive.Name); if (download) + { if (outputPath.FileExists()) - File.Delete(outputPath); + { + var orig_name = Path.GetFileNameWithoutExtension(archive.Name); + var ext = Path.GetExtension(archive.Name); + var unique_key = archive.State.PrimaryKeyString.StringSHA256Hex(); + outputPath = Path.Combine(DownloadFolder, orig_name + "_" + unique_key + "_" + ext); + if (outputPath.FileExists()) + File.Delete(outputPath); + } + } return await DownloadArchive(archive, download); }); } - public async Task DownloadArchive(Archive archive, bool download) + public async Task DownloadArchive(Archive archive, bool download, string destination = null) { try { - var path = Path.Combine(DownloadFolder, archive.Name); - await archive.State.Download(archive, path); - path.FileHashCached(); + if (destination == null) + destination = Path.Combine(DownloadFolder, archive.Name); + await archive.State.Download(archive, destination); + destination.FileHashCached(); } catch (Exception ex) diff --git a/Wabbajack.Test/DownloaderTests.cs b/Wabbajack.Test/DownloaderTests.cs index f421adc6..654cdfee 100644 --- a/Wabbajack.Test/DownloaderTests.cs +++ b/Wabbajack.Test/DownloaderTests.cs @@ -4,6 +4,8 @@ using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Threading; using Alphaleonis.Win32.Filesystem; using Microsoft.VisualStudio.TestTools.UnitTesting; using Wabbajack.Common; @@ -13,6 +15,7 @@ using Wabbajack.Lib.Downloaders; using Wabbajack.Lib.LibCefHelpers; using Wabbajack.Lib.NexusApi; using Wabbajack.Lib.Validation; +using Directory = System.IO.Directory; using File = Alphaleonis.Win32.Filesystem.File; using Game = Wabbajack.Common.Game; @@ -463,8 +466,6 @@ namespace Wabbajack.Test var entries = archive.Entries.Select(e => e.FullName).ToList(); CollectionAssert.AreEqual(entries, new List {@"Data\TestCK.esp", @"Data\TestCK.ini"}); } - - } diff --git a/Wabbajack.Test/EndToEndTests.cs b/Wabbajack.Test/EndToEndTests.cs index 9218b2bc..02801164 100644 --- a/Wabbajack.Test/EndToEndTests.cs +++ b/Wabbajack.Test/EndToEndTests.cs @@ -80,7 +80,6 @@ namespace Wabbajack.Test var modlist = await CompileAndInstall(profile); - utils.VerifyAllFiles(); var loot_folder = Path.Combine(utils.InstallFolder, "LOOT Config Files"); From 05eb427ce5a1535b8ed6b9e11c81099a926b5264 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Wed, 12 Feb 2020 05:37:24 -0700 Subject: [PATCH 2/2] Write a test to verify file download renaming behavior --- Wabbajack.Lib/AInstaller.cs | 4 +- Wabbajack.Test/DownloaderTests.cs | 72 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Wabbajack.Lib/AInstaller.cs b/Wabbajack.Lib/AInstaller.cs index 42acbfc8..1f2a474e 100644 --- a/Wabbajack.Lib/AInstaller.cs +++ b/Wabbajack.Lib/AInstaller.cs @@ -240,7 +240,7 @@ namespace Wabbajack.Lib await DownloadMissingArchives(missing); } - private async Task DownloadMissingArchives(List missing, bool download = true) + public async Task DownloadMissingArchives(List missing, bool download = true) { if (download) { @@ -270,7 +270,7 @@ namespace Wabbajack.Lib } } - return await DownloadArchive(archive, download); + return await DownloadArchive(archive, download, outputPath); }); } diff --git a/Wabbajack.Test/DownloaderTests.cs b/Wabbajack.Test/DownloaderTests.cs index 654cdfee..1b6dbc44 100644 --- a/Wabbajack.Test/DownloaderTests.cs +++ b/Wabbajack.Test/DownloaderTests.cs @@ -466,6 +466,78 @@ namespace Wabbajack.Test var entries = archive.Entries.Select(e => e.FullName).ToList(); CollectionAssert.AreEqual(entries, new List {@"Data\TestCK.esp", @"Data\TestCK.ini"}); } + + + /// + /// Tests that files from different sources don't overwrite eachother when downloaded by AInstaller + /// + /// + [TestMethod] + public async Task DownloadRenamingTests() + { + // Test mode off for this test + Consts.TestMode = false; + + + var inia = $@"[General] + gameName={Game.SkyrimSpecialEdition.MetaData().MO2ArchiveName} + gameFile=Data/Update.esm"; + + var statea = (GameFileSourceDownloader.State)await DownloadDispatcher.ResolveArchive(inia.LoadIniString()); + + var inib = $@"[General] + gameName={Game.SkyrimSpecialEdition.MetaData().MO2ArchiveName} + gameFile=Data/Skyrim.esm"; + var stateb = (GameFileSourceDownloader.State)await DownloadDispatcher.ResolveArchive(inib.LoadIniString()); + + var archivesa = new List() + { + new Archive {Hash = statea.Hash, Name = "Download.esm", State = statea} + }; + + var archivesb = new List() + { + new Archive {Hash = stateb.Hash, Name = "Download.esm", State = stateb} + }; + + if (Directory.Exists("DownloadTests")) + Utils.DeleteDirectory("DownloadTests"); + Directory.CreateDirectory("DownloadTests"); + + var inst = new TestInstaller(null, null, null, "DownloadTests", null); + + await inst.DownloadMissingArchives(archivesa, true); + await inst.DownloadMissingArchives(archivesb, true); + + CollectionAssert.AreEqual(Directory.EnumerateFiles("DownloadTests").Select(Path.GetFileName).OrderBy(a => a).ToArray(), + new string[] + { + @"Download.esm", + @"Download.esm.xxHash", + @"Download_f80ee6d109516018308f62e2c862b7f061987ac4a8c2327a101ac6b8f80ec4ae_.esm", + @"Download_f80ee6d109516018308f62e2c862b7f061987ac4a8c2327a101ac6b8f80ec4ae_.esm.xxHash" + }.OrderBy(a => a).ToArray()); + + Consts.TestMode = true; + + } + + class TestInstaller : AInstaller + { + public TestInstaller(string archive, ModList modList, string outputFolder, string downloadFolder, SystemParameters parameters) : base(archive, modList, outputFolder, downloadFolder, parameters) + { + ConfigureProcessor(1, new Subject().StartWith(1)); + } + + protected override Task _Begin(CancellationToken cancel) + { + throw new NotImplementedException(); + } + + public override ModManager ModManager { get => ModManager.MO2; } + } + + }