diff --git a/VirtualFileSystem/VirtualFileSystem.cs b/VirtualFileSystem/VirtualFileSystem.cs index 6ba583f8..8b425672 100644 --- a/VirtualFileSystem/VirtualFileSystem.cs +++ b/VirtualFileSystem/VirtualFileSystem.cs @@ -28,10 +28,18 @@ namespace VFS static VirtualFileSystem() { VFS = new VirtualFileSystem(); - RootFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + var entry = Assembly.GetEntryAssembly(); + if (entry != null && !string.IsNullOrEmpty(entry.Location)) + { + RootFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + _stagedRoot = Path.Combine(RootFolder, "vfs_staged_files"); + } + } + public static void Reconfigure(string root) + { + RootFolder = root; _stagedRoot = Path.Combine(RootFolder, "vfs_staged_files"); - } public static void Clean() @@ -51,7 +59,7 @@ namespace VFS LoadFromDisk(); } - public static string RootFolder { get; } + public static string RootFolder { get; private set; } public Dictionary> HashIndex { get; private set; } public VirtualFile this[string path] => Lookup(path); diff --git a/Wabbajack.Common/WorkQueue.cs b/Wabbajack.Common/WorkQueue.cs index fcb1b3e2..47baff75 100644 --- a/Wabbajack.Common/WorkQueue.cs +++ b/Wabbajack.Common/WorkQueue.cs @@ -17,6 +17,7 @@ namespace Wabbajack.Common public static int MaxQueueSize; public static int CurrentQueueSize; + private static bool _inited; public static Action ReportFunction { get; private set; } public static Action ReportQueueSize { get; private set; } @@ -28,7 +29,10 @@ namespace Wabbajack.Common ReportFunction = report_function; ReportQueueSize = report_queue_size; ThreadCount = Environment.ProcessorCount; + if (_inited) return; StartThreads(); + _inited = true; + } private static void StartThreads() diff --git a/Wabbajack.Test/Properties/AssemblyInfo.cs b/Wabbajack.Test/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..d81ac109 --- /dev/null +++ b/Wabbajack.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Wabbajack.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Wabbajack.Test")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("a47fff32-782b-4d9f-8704-c98fb32fa8cc")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Wabbajack.Test/SanityTests.cs b/Wabbajack.Test/SanityTests.cs new file mode 100644 index 00000000..419f29dd --- /dev/null +++ b/Wabbajack.Test/SanityTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using Alphaleonis.Win32.Filesystem; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting.Logging; +using VFS; +using Wabbajack.Common; + +namespace Wabbajack.Test +{ + [TestClass] + public class SanityTests + { + public TestContext TestContext { get; set; } + + [TestMethod] + public void TestDirectMatch() + { + var utils = new TestUtils(); + + utils.GameName = "Skyrim Special Edition"; + var profile = utils.AddProfile(); + var mod = utils.AddMod(); + var test_pex = utils.AddModFile(mod, @"Data\scripts\test.pex", 10); + utils.Configure(); + + utils.AddManualDownload( + new Dictionary() {{"/baz/biz.pex", File.ReadAllBytes(test_pex)}}); + + Utils.SetStatusFn((f, idx) => { }); + Utils.SetLoggerFn(f => TestContext.WriteLine(f)); + WorkQueue.Init((x, y, z) => { }, (min, max) => { }); + + VirtualFileSystem.Reconfigure(utils.TestFolder); + var compiler = new Compiler(utils.MO2Folder, msg => TestContext.WriteLine(msg)); + compiler.ShowReportWhenFinished = false; + compiler.MO2Profile = profile; + Assert.IsTrue(compiler.Compile()); + + + var installer = new Installer(compiler.ModList, utils.InstallFolder, TestContext.WriteLine); + installer.DownloadFolder = utils.DownloadsFolder; + installer.GameFolder = utils.GameFolder; + installer.Install(); + + utils.VerifyInstalledFile(mod, @"Data\scripts\test.pex"); + + utils.Dispose(); + + } + } +} diff --git a/Wabbajack.Test/TestUtils.cs b/Wabbajack.Test/TestUtils.cs new file mode 100644 index 00000000..e81bd446 --- /dev/null +++ b/Wabbajack.Test/TestUtils.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Wabbajack.Common; +using Directory = Alphaleonis.Win32.Filesystem.Directory; +using File = Alphaleonis.Win32.Filesystem.File; +using Path = Alphaleonis.Win32.Filesystem.Path; + +namespace Wabbajack.Test +{ + public class TestUtils : IDisposable + { + + public TestUtils() + { + RNG = new Random(); + ID = RandomName(); + WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "tmp_data"); + } + + public string WorkingDirectory { get;} + public string ID { get; } + public Random RNG { get; } + + public string GameName { get; set; } + + public string TestFolder => Path.Combine(WorkingDirectory, ID); + public string GameFolder => Path.Combine(WorkingDirectory, ID, "game_folder"); + + public string MO2Folder => Path.Combine(WorkingDirectory, ID, "mo2_folder"); + public string ModsFolder => Path.Combine(MO2Folder, "mods"); + public string DownloadsFolder => Path.Combine(MO2Folder, "downloads"); + + public string InstallFolder => Path.Combine(TestFolder, "installed"); + + + public void Configure() + { + File.WriteAllLines(Path.Combine(MO2Folder, "ModOrganizer.ini"), new [] + { + "[General]", + $"gameName={GameName}", + $"gamePath={GameFolder.Replace("\\", "\\\\")}", + }); + + Directory.CreateDirectory(DownloadsFolder); + Directory.CreateDirectory(GameFolder); + + Profiles.Do(profile => + { + File.WriteAllLines(Path.Combine(MO2Folder, "profiles", profile, "modlist.txt"), + Mods.Select(s => $"+{s}").ToArray()); + }); + } + + public string AddProfile() + { + string profile_name = RandomName(); + Directory.CreateDirectory(Path.Combine(MO2Folder, "profiles", profile_name)); + Profiles.Add(profile_name); + return profile_name; + } + public HashSet Profiles = new HashSet(); + + public string AddMod() + { + string mod_name = RandomName(); + Directory.CreateDirectory(Path.Combine(MO2Folder, "mods", mod_name)); + Mods.Add(mod_name); + return mod_name; + } + + public List Mods = new List(); + + /// + /// Adds a file to the given mod with a given path in the mod. Fills it with random data unless + /// random_fill == 0; + /// + /// + /// + /// + /// + public string AddModFile(string mod_name, string path, int random_fill=128) + { + byte[] bytes = new byte[0]; + if (random_fill != 0) + { + bytes = new byte[random_fill]; + RNG.NextBytes(bytes); + } + + var full_path = Path.Combine(ModsFolder, mod_name, path); + Directory.CreateDirectory(Path.GetDirectoryName(full_path)); + File.WriteAllBytes(full_path, bytes); + return full_path; + } + + public void Dispose() + { + var exts = new [] {".md", ".exe"}; + Directory.Delete(Path.Combine(WorkingDirectory, ID), true); + Profiles.Do(p => + { + foreach (var ext in exts) { + var path = Path.Combine(Directory.GetCurrentDirectory(), p + ext); + if (File.Exists(path)) + File.Delete(path); + } + }); + } + + + /// + /// Returns a random string name (with spaces) + /// + private char[] _nameChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+=-_ ".ToCharArray(); + public string RandomName() + { + return Guid.NewGuid().ToString(); + } + + public string AddManualDownload(Dictionary contents) + { + var name = RandomName() + ".zip"; + + using(FileStream fs = new FileStream(Path.Combine(DownloadsFolder, name), FileMode.Create)) + using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create)) + { + contents.Do(kv => + { + var entry = archive.CreateEntry(kv.Key); + using (var os = entry.Open()) + os.Write(kv.Value, 0, kv.Value.Length); + }); + } + + File.WriteAllLines(Path.Combine(DownloadsFolder, name+".meta"), + + new string[] + { + "[General]", + "manualURL=" + }); + + return name; + } + + public void VerifyInstalledFile(string mod, string file) + { + var src = Path.Combine(MO2Folder, "mods", mod, file); + Assert.IsTrue(File.Exists(src), src); + + var dest = Path.Combine(InstallFolder, "mods", mod, file); + Assert.IsTrue(File.Exists(dest), dest); + + var src_data = File.ReadAllBytes(src); + var dest_data = File.ReadAllBytes(dest); + + Assert.AreEqual(src_data.Length, dest_data.Length); + + for(int x = 0; x < src_data.Length; x++) + { + if (src_data[x] != dest_data[x]) + Assert.Fail($"Index {x} of {mod}\\{file} are not the same"); + } + } + } +} diff --git a/Wabbajack.Test/Wabbajack.Test.csproj b/Wabbajack.Test/Wabbajack.Test.csproj new file mode 100644 index 00000000..9f48574f --- /dev/null +++ b/Wabbajack.Test/Wabbajack.Test.csproj @@ -0,0 +1,108 @@ + + + + + + Debug + AnyCPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC} + Library + Properties + Wabbajack.Test + Wabbajack.Test + v4.7.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x64 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\AlphaFS.2.2.6\lib\net452\AlphaFS.dll + + + ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + + + + + + + + + + + + + + + + {5128b489-bc28-4f66-9f0b-b4565af36cbc} + VirtualFileSystem + + + {b3f3fb6e-b9eb-4f49-9875-d78578bc7ae5} + Wabbajack.Common + + + {33602679-8484-40c7-a10c-774dff5d8314} + Wabbajack + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/Wabbajack.Test/app.config b/Wabbajack.Test/app.config new file mode 100644 index 00000000..e936cc13 --- /dev/null +++ b/Wabbajack.Test/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Wabbajack.Test/packages.config b/Wabbajack.Test/packages.config new file mode 100644 index 00000000..7beb9668 --- /dev/null +++ b/Wabbajack.Test/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Wabbajack.sln b/Wabbajack.sln index b3243871..307f4027 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -27,61 +27,126 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.WebAutomation", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.WebAutomation.Test", "Wabbajack.WebAutomation.Test\Wabbajack.WebAutomation.Test.csproj", "{73D0B663-A6FB-4A67-B945-EBB4A234C996}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Test", "Wabbajack.Test\Wabbajack.Test.csproj", "{A47FFF32-782B-4D9F-8704-C98FB32FA8CC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug (no commandargs)|Any CPU = Debug (no commandargs)|Any CPU Debug (no commandargs)|x64 = Debug (no commandargs)|x64 + Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|x64.ActiveCfg = Debug|x64 {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|x64.Build.0 = Debug|x64 + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.Build.0 = Release|Any CPU {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.ActiveCfg = Release|x64 {B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|x64.Build.0 = Release|x64 + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug (no commandargs)|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|Any CPU.Build.0 = Debug (no commandargs)|Any CPU {33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|x64.ActiveCfg = Debug (no commandargs)|x64 {33602679-8484-40C7-A10C-774DFF5D8314}.Debug (no commandargs)|x64.Build.0 = Debug (no commandargs)|x64 + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|Any CPU.Build.0 = Debug|Any CPU {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|x64.ActiveCfg = Debug|x64 {33602679-8484-40C7-A10C-774DFF5D8314}.Debug|x64.Build.0 = Debug|x64 + {33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33602679-8484-40C7-A10C-774DFF5D8314}.Release|Any CPU.Build.0 = Release|Any CPU {33602679-8484-40C7-A10C-774DFF5D8314}.Release|x64.ActiveCfg = Release|x64 {33602679-8484-40C7-A10C-774DFF5D8314}.Release|x64.Build.0 = Release|x64 + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|Any CPU.Build.0 = Debug|Any CPU {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|x64.ActiveCfg = Debug|x64 {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Debug|x64.Build.0 = Debug|x64 + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|Any CPU.Build.0 = Release|Any CPU {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|x64.ActiveCfg = Release|x64 {FF5D892F-8FF4-44FC-8F7F-CD58F307AD1B}.Release|x64.Build.0 = Release|x64 + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|x64.ActiveCfg = Debug|x64 {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Debug|x64.Build.0 = Debug|x64 + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|Any CPU.Build.0 = Release|Any CPU {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|x64.ActiveCfg = Release|x64 {BA2CFEA1-072B-42D6-822A-8C6D0E3AE5D9}.Release|x64.Build.0 = Release|x64 + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug (no commandargs)|x64.ActiveCfg = Debug|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug (no commandargs)|x64.Build.0 = Debug|Any CPU + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug|x64.ActiveCfg = Debug|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Debug|x64.Build.0 = Debug|Any CPU + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Release|Any CPU.Build.0 = Release|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Release|x64.ActiveCfg = Release|Any CPU {5128B489-BC28-4F66-9F0B-B4565AF36CBC}.Release|x64.Build.0 = Release|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug (no commandargs)|x64.ActiveCfg = Debug|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug (no commandargs)|x64.Build.0 = Debug|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug|Any CPU.Build.0 = Debug|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug|x64.ActiveCfg = Debug|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Debug|x64.Build.0 = Debug|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Release|Any CPU.Build.0 = Release|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Release|x64.ActiveCfg = Release|Any CPU {A2913DFE-18FF-468B-A6C1-55F7C0CC0CE8}.Release|x64.Build.0 = Release|Any CPU + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug|Any CPU.Build.0 = Debug|Any CPU {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug|x64.ActiveCfg = Debug|Any CPU {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Debug|x64.Build.0 = Debug|Any CPU + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Release|Any CPU.Build.0 = Debug|Any CPU {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Release|x64.ActiveCfg = Debug|Any CPU {E5A6F0E6-F79E-460D-82E2-E6330ACE06BA}.Release|x64.Build.0 = Debug|Any CPU + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug|Any CPU.Build.0 = Debug|Any CPU {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug|x64.ActiveCfg = Debug|Any CPU {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Debug|x64.Build.0 = Debug|Any CPU + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Release|Any CPU.Build.0 = Release|Any CPU {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Release|x64.ActiveCfg = Release|Any CPU {73D0B663-A6FB-4A67-B945-EBB4A234C996}.Release|x64.Build.0 = Release|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug (no commandargs)|Any CPU.ActiveCfg = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug (no commandargs)|Any CPU.Build.0 = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug (no commandargs)|x64.ActiveCfg = Debug|x64 + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug (no commandargs)|x64.Build.0 = Debug|x64 + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug|x64.ActiveCfg = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Debug|x64.Build.0 = Debug|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Release|Any CPU.Build.0 = Release|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Release|x64.ActiveCfg = Release|Any CPU + {A47FFF32-782B-4D9F-8704-C98FB32FA8CC}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Wabbajack/Compiler.cs b/Wabbajack/Compiler.cs index 98487ddd..40af660c 100644 --- a/Wabbajack/Compiler.cs +++ b/Wabbajack/Compiler.cs @@ -47,6 +47,8 @@ namespace Wabbajack public dynamic MO2Ini { get; } public string GamePath { get; } + public bool ShowReportWhenFinished { get; set; } = true; + public bool IgnoreMissingFiles { get; set; } public string MO2DownloadsFolder @@ -105,7 +107,7 @@ namespace Wabbajack throw new Exception(msg); } - public void Compile() + public bool Compile() { VirtualFileSystem.Clean(); Info("Looking for other profiles"); @@ -217,7 +219,7 @@ namespace Wabbajack else { Info("Exiting due to no way to compile these files"); - return; + return false; } } @@ -225,10 +227,13 @@ namespace Wabbajack Info("Getting nexus api_key please click authorize if a browser window appears"); - NexusKey = GetNexusAPIKey(); - User = GetUserStatus(NexusKey); + if (IndexedArchives.OfType().Any()) + { + NexusKey = GetNexusAPIKey(); + User = GetUserStatus(NexusKey); + if (!User.is_premium) Info($"User {User.name} is not a premium Nexus user, cannot continue"); - if (!User.is_premium) Info($"User {User.name} is not a premium Nexus user, cannot continue"); + } zEditIntegration.VerifyMerges(this); @@ -250,10 +255,13 @@ namespace Wabbajack ShowReport(); Info("Done Building Modpack"); + return true; } private void ShowReport() { + if (!ShowReportWhenFinished) return; + var file = Path.GetTempFileName() + ".html"; File.WriteAllText(file, ModList.ReportHTML); Process.Start(file); @@ -445,13 +453,6 @@ namespace Wabbajack result = tmp; } - else if (general.manualURL != null) - { - result = new ManualURLArchive - { - URL = general.manualURL.ToString() - }; - } else if (general.modID != null && general.fileID != null && general.gameName != null) { var nm = new NexusMod @@ -467,6 +468,14 @@ namespace Wabbajack nm.UploaderProfile = info.uploaded_users_profile_url; result = nm; } + else if (general.manualURL != null) + { + result = new ManualArchive + { + URL = general.manualURL, + Notes = general.manualNotes, + }; + } else { Error("No way to handle archive {0} but it's required by the modlist", found.Name); @@ -478,6 +487,8 @@ namespace Wabbajack result.Meta = found.Meta; result.Size = found.File.Size; + if (result is ManualArchive) return result; + Info($"Checking link for {found.Name}"); var installer = new Installer(null, "", Utils.Log); diff --git a/Wabbajack/Data.cs b/Wabbajack/Data.cs index cf904cb5..cc7f520f 100644 --- a/Wabbajack/Data.cs +++ b/Wabbajack/Data.cs @@ -194,6 +194,13 @@ namespace Wabbajack public string Version; } + [Serializable] + public class ManualArchive : Archive + { + public string URL; + public string Notes; + } + [Serializable] public class GoogleDriveMod : Archive { @@ -212,15 +219,6 @@ namespace Wabbajack public string URL; } - /// - /// A URL that cannot be downloaded automatically and has to be downloaded by hand - /// - [Serializable] - public class ManualURLArchive : Archive - { - public string URL; - } - /// /// An archive that requires additional HTTP headers. /// diff --git a/Wabbajack/Installer.cs b/Wabbajack/Installer.cs index 8775f9c7..d39b5912 100644 --- a/Wabbajack/Installer.cs +++ b/Wabbajack/Installer.cs @@ -48,7 +48,7 @@ namespace Wabbajack public string NexusAPIKey { get; set; } public bool IgnoreMissingFiles { get; internal set; } - public string GameFolder { get; private set; } + public string GameFolder { get; set; } public void Info(string msg, params object[] args) { @@ -99,8 +99,7 @@ namespace Wabbajack } } - if (ModList.Directives.OfType().FirstOrDefault() != null || - ModList.Directives.OfType().FirstOrDefault() != null) + if (GameFolder == null) { MessageBox.Show( "In order to do a proper install Wabbajack needs to know where your game folder resides. This is most likely " + @@ -408,15 +407,18 @@ namespace Wabbajack Info("Missing {0} archives", missing.Count); Info("Getting Nexus API Key, if a browser appears, please accept"); - NexusAPIKey = NexusAPI.GetNexusAPIKey(); - - var user_status = NexusAPI.GetUserStatus(NexusAPIKey); - - if (!user_status.is_premium) + if (ModList.Archives.OfType().Any()) { - Info( - $"Automated installs with Wabbajack requires a premium nexus account. {user_status.name} is not a premium account"); - return; + NexusAPIKey = NexusAPI.GetNexusAPIKey(); + + var user_status = NexusAPI.GetUserStatus(NexusAPIKey); + + if (!user_status.is_premium) + { + Info( + $"Automated installs with Wabbajack requires a premium nexus account. {user_status.name} is not a premium account"); + return; + } } DownloadMissingArchives(missing); diff --git a/Wabbajack/zEditIntegration.cs b/Wabbajack/zEditIntegration.cs index 8f1ea4f9..e1b4bf98 100644 --- a/Wabbajack/zEditIntegration.cs +++ b/Wabbajack/zEditIntegration.cs @@ -19,6 +19,7 @@ namespace Wabbajack public static string FindzEditPath(Compiler compiler) { var executables = compiler.MO2Ini.customExecutables; + if (executables.size == null) return null; foreach (var idx in Enumerable.Range(1, int.Parse(executables.size))) {