mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
First Native compilation test passes
This commit is contained in:
parent
c5c444b707
commit
18ac41729d
@ -180,7 +180,7 @@ namespace Wabbajack.Lib
|
||||
{
|
||||
if (UseGamePaths)
|
||||
{
|
||||
foreach (var ag in Settings.IncludedGames)
|
||||
foreach (var ag in Settings.IncludedGames.Cons(CompilingGame.Game))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ namespace Wabbajack.Lib.CompilationSteps
|
||||
{
|
||||
}
|
||||
|
||||
public static int GetFilePriority(MO2Compiler compiler, VirtualFile file)
|
||||
public static int GetFilePriority(ACompiler compiler, VirtualFile file)
|
||||
{
|
||||
var archive = file.TopParent;
|
||||
var adata = compiler.ArchivesByFullPath[archive.AbsoluteName];
|
||||
@ -26,12 +26,11 @@ namespace Wabbajack.Lib.CompilationSteps
|
||||
|
||||
public override async ValueTask<Directive?> Run(RawSourceFile source)
|
||||
{
|
||||
var mo2Compiler = (MO2Compiler)_compiler;
|
||||
if (!_compiler.IndexedFiles.TryGetValue(source.Hash, out var found)) return null;
|
||||
var result = source.EvolveTo<FromArchive>();
|
||||
|
||||
var match = found.Where(f => f.Name.FileName == source.Path.FileName)
|
||||
.OrderBy(f => GetFilePriority(mo2Compiler, f))
|
||||
.OrderBy(f => GetFilePriority(_compiler, f))
|
||||
.ThenBy(f => f.NestingFactor)
|
||||
.FirstOrDefault()
|
||||
?? found.OrderBy(f => f.NestingFactor).FirstOrDefault();
|
||||
|
@ -77,7 +77,7 @@ namespace Wabbajack.Lib
|
||||
|
||||
Info("Using Profiles: " + string.Join(", ", SelectedProfiles.OrderBy(p => p)));
|
||||
|
||||
Utils.Log($"Compiling Game: {CompilingGame}");
|
||||
Utils.Log($"Compiling Game: {CompilingGame.Game}");
|
||||
Utils.Log("Games from setting files:");
|
||||
foreach (var game in Settings.IncludedGames)
|
||||
{
|
||||
|
289
Wabbajack.Lib/NativeCompiler.cs
Normal file
289
Wabbajack.Lib/NativeCompiler.cs
Normal file
@ -0,0 +1,289 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.CompilationSteps;
|
||||
using Wabbajack.Lib.Validation;
|
||||
using Wabbajack.VirtualFileSystem;
|
||||
|
||||
namespace Wabbajack.Lib
|
||||
{
|
||||
public class NativeCompiler : ACompiler
|
||||
{
|
||||
public NativeCompiler(NativeCompilerSettings settings, AbsolutePath sourcePath, AbsolutePath downloadsPath, AbsolutePath outputModListPath)
|
||||
: base(3, settings.ModListName, sourcePath, downloadsPath, outputModListPath)
|
||||
{
|
||||
CompilingGame = settings.CompilingGame.MetaData();
|
||||
GamePath = CompilingGame.GameLocation();
|
||||
NativeSettings = settings;
|
||||
}
|
||||
|
||||
public NativeCompilerSettings NativeSettings { get; set; }
|
||||
|
||||
protected override async Task<bool> _Begin(CancellationToken cancel)
|
||||
{
|
||||
await Metrics.Send("begin_compiling", ModListName ?? "unknown");
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DesiredThreads.OnNext(DiskThreads);
|
||||
FileExtractor2.FavorPerfOverRAM = FavorPerfOverRam;
|
||||
|
||||
UpdateTracker.Reset();
|
||||
UpdateTracker.NextStep("Gathering information");
|
||||
|
||||
Utils.Log($"Compiling Game: {CompilingGame.Game}");
|
||||
Utils.Log("Games from setting files:");
|
||||
foreach (var game in Settings.IncludedGames)
|
||||
{
|
||||
Utils.Log($"- {game}");
|
||||
}
|
||||
|
||||
Utils.Log($"VFS File Location: {VFSCacheName}");
|
||||
Utils.Log($"MO2 Folder: {SourcePath}");
|
||||
Utils.Log($"Downloads Folder: {DownloadsPath}");
|
||||
Utils.Log($"Game Folder: {GamePath}");
|
||||
|
||||
var watcher = new DiskSpaceWatcher(cancel,
|
||||
new[] {SourcePath, DownloadsPath, GamePath, AbsolutePath.EntryPoint}, (long)2 << 31,
|
||||
drive =>
|
||||
{
|
||||
Utils.Log($"Aborting due to low space on {drive.Name}");
|
||||
Abort();
|
||||
});
|
||||
var watcherTask = watcher.Start();
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
List<AbsolutePath> roots = new List<AbsolutePath> {SourcePath, GamePath, DownloadsPath};
|
||||
roots.AddRange(Settings.IncludedGames.Select(g => g.MetaData().GameLocation()));
|
||||
|
||||
UpdateTracker.NextStep("Indexing folders");
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await VFS.AddRoots(roots);
|
||||
|
||||
UpdateTracker.NextStep("Cleaning output folder");
|
||||
await ModListOutputFolder.DeleteDirectory();
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateTracker.NextStep("Inferring metas for game file downloads");
|
||||
await InferMetas();
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateTracker.NextStep("Reindexing downloads after meta inferring");
|
||||
await VFS.AddRoot(DownloadsPath);
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateTracker.NextStep("Pre-validating Archives");
|
||||
|
||||
|
||||
// Find all Downloads
|
||||
IndexedArchives = (await DownloadsPath.EnumerateFiles()
|
||||
.Where(f => f.WithExtension(Consts.MetaFileExtension).Exists)
|
||||
.PMap(Queue,
|
||||
async f => new IndexedArchive(VFS.Index.ByRootPath[f])
|
||||
{
|
||||
Name = (string)f.FileName,
|
||||
IniData = f.WithExtension(Consts.MetaFileExtension).LoadIniFile(),
|
||||
Meta = await f.WithExtension(Consts.MetaFileExtension).ReadAllTextAsync()
|
||||
})).ToList();
|
||||
|
||||
|
||||
await IndexGameFileHashes();
|
||||
|
||||
IndexedArchives = IndexedArchives.DistinctBy(a => a.File.AbsoluteName).ToList();
|
||||
|
||||
await CleanInvalidArchivesAndFillState();
|
||||
|
||||
UpdateTracker.NextStep("Finding Install Files");
|
||||
ModListOutputFolder.CreateDirectory();
|
||||
|
||||
var mo2Files = SourcePath.EnumerateFiles()
|
||||
.Where(p => p.IsFile)
|
||||
.Select(p =>
|
||||
{
|
||||
if (!VFS.Index.ByRootPath.ContainsKey(p))
|
||||
{
|
||||
Utils.Log($"WELL THERE'S YOUR PROBLEM: {p} {VFS.Index.ByRootPath.Count}");
|
||||
}
|
||||
|
||||
return new RawSourceFile(VFS.Index.ByRootPath[p], p.RelativeTo(SourcePath));
|
||||
});
|
||||
|
||||
// If Game Folder Files exists, ignore the game folder
|
||||
IndexedFiles = IndexedArchives.SelectMany(f => f.File.ThisAndAllChildren)
|
||||
.OrderBy(f => f.NestingFactor)
|
||||
.GroupBy(f => f.Hash)
|
||||
.ToDictionary(f => f.Key, f => f.AsEnumerable());
|
||||
|
||||
AllFiles.SetTo(mo2Files
|
||||
.DistinctBy(f => f.Path));
|
||||
|
||||
Info($"Found {AllFiles.Count} files to build into mod list");
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateTracker.NextStep("Verifying destinations");
|
||||
|
||||
var dups = AllFiles.GroupBy(f => f.Path)
|
||||
.Where(fs => fs.Count() > 1)
|
||||
.Select(fs =>
|
||||
{
|
||||
Utils.Log(
|
||||
$"Duplicate files installed to {fs.Key} from : {String.Join(", ", fs.Select(f => f.AbsolutePath))}");
|
||||
return fs;
|
||||
}).ToList();
|
||||
|
||||
if (dups.Count > 0)
|
||||
{
|
||||
Error($"Found {dups.Count} duplicates, exiting");
|
||||
}
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateTracker.NextStep("Loading INIs");
|
||||
|
||||
ArchivesByFullPath = IndexedArchives.ToDictionary(a => a.File.AbsoluteName);
|
||||
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var stack = MakeStack();
|
||||
UpdateTracker.NextStep("Running Compilation Stack");
|
||||
var results = await AllFiles.PMap(Queue, UpdateTracker, f => RunStack(stack, f));
|
||||
|
||||
// Add the extra files that were generated by the stack
|
||||
if (cancel.IsCancellationRequested)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var noMatch = results.OfType<NoMatch>().ToArray();
|
||||
PrintNoMatches(noMatch);
|
||||
if (CheckForNoMatchExit(noMatch))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var ignored in results.OfType<IgnoredDirectly>())
|
||||
{
|
||||
Utils.Log($"Ignored {ignored.To} because {ignored.Reason}");
|
||||
}
|
||||
|
||||
InstallDirectives.SetTo(results.Where(i => !(i is IgnoredDirectly)));
|
||||
|
||||
Info("Getting Nexus api_key, please click authorize if a browser window appears");
|
||||
|
||||
UpdateTracker.NextStep("Building Patches");
|
||||
await BuildPatches();
|
||||
|
||||
UpdateTracker.NextStep("Gathering Archives");
|
||||
await GatherArchives();
|
||||
|
||||
UpdateTracker.NextStep("Gathering Metadata");
|
||||
await GatherMetaData();
|
||||
|
||||
ModList = new ModList
|
||||
{
|
||||
GameType = CompilingGame.Game,
|
||||
WabbajackVersion = Consts.CurrentMinimumWabbajackVersion,
|
||||
Archives = SelectedArchives.ToList(),
|
||||
ModManager = ModManager.MO2,
|
||||
Directives = InstallDirectives,
|
||||
Name = ModListName ?? "untitled",
|
||||
Author = ModListAuthor ?? "",
|
||||
Description = ModListDescription ?? "",
|
||||
Readme = ModlistReadme ?? "",
|
||||
Image = ModListImage != default ? ModListImage.FileName : default,
|
||||
Website = !string.IsNullOrWhiteSpace(ModListWebsite) ? new Uri(ModListWebsite) : null,
|
||||
Version = ModlistVersion ?? new Version(1, 0, 0, 0),
|
||||
IsNSFW = ModlistIsNSFW
|
||||
};
|
||||
|
||||
UpdateTracker.NextStep("Including required files");
|
||||
await InlineFiles();
|
||||
|
||||
UpdateTracker.NextStep("Running Validation");
|
||||
|
||||
await ValidateModlist.RunValidation(ModList);
|
||||
UpdateTracker.NextStep("Generating Report");
|
||||
|
||||
GenerateManifest();
|
||||
|
||||
UpdateTracker.NextStep("Exporting Modlist");
|
||||
await ExportModList();
|
||||
|
||||
ResetMembers();
|
||||
|
||||
UpdateTracker.NextStep("Done Building Modlist");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear references to lists that hold a lot of data.
|
||||
/// </summary>
|
||||
private void ResetMembers()
|
||||
{
|
||||
AllFiles = new List<RawSourceFile>();
|
||||
InstallDirectives = new List<Directive>();
|
||||
SelectedArchives = new List<Archive>();
|
||||
}
|
||||
|
||||
public override AbsolutePath GamePath { get; }
|
||||
public override IEnumerable<ICompilationStep> GetStack()
|
||||
{
|
||||
return MakeStack();
|
||||
}
|
||||
|
||||
public override IEnumerable<ICompilationStep> MakeStack()
|
||||
{
|
||||
List<ICompilationStep> steps = NativeSettings.CompilationSteps.Select(InterpretStep).ToList();
|
||||
steps.Add(new DropAll(this));
|
||||
return steps;
|
||||
}
|
||||
|
||||
public ICompilationStep InterpretStep(string[] step)
|
||||
{
|
||||
return step[0] switch
|
||||
{
|
||||
"IgnoreStartsWith" => new IgnoreStartsWith(this, step[1]),
|
||||
"IncludeConfigs" => new IncludeAllConfigs(this),
|
||||
"IncludeDirectMatches" => new DirectMatch(this),
|
||||
"IncludePatches" => new IncludePatches(this),
|
||||
_ => throw new ArgumentException($"No interpretation for step {step[0]}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
14
Wabbajack.Lib/NativeCompilerSettings.cs
Normal file
14
Wabbajack.Lib/NativeCompilerSettings.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.Lib
|
||||
{
|
||||
public class NativeCompilerSettings : CompilerSettings
|
||||
{
|
||||
public Game CompilingGame { get; set; }
|
||||
|
||||
public string ModListName { get; set; } = "untitled";
|
||||
|
||||
public string[][] CompilationSteps = new string[0][];
|
||||
|
||||
}
|
||||
}
|
@ -36,8 +36,8 @@ namespace Wabbajack.Test
|
||||
protected async Task<MO2Compiler> ConfigureAndRunCompiler(string profile, bool useGameFiles= false)
|
||||
{
|
||||
var compiler = new MO2Compiler(
|
||||
sourcePath: utils.MO2Folder,
|
||||
downloadsPath: utils.DownloadsFolder,
|
||||
sourcePath: utils.SourcePath,
|
||||
downloadsPath: utils.DownloadsPath,
|
||||
mo2Profile: profile,
|
||||
outputFile: OutputFile(profile));
|
||||
compiler.UseGamePaths = useGameFiles;
|
||||
@ -52,13 +52,35 @@ namespace Wabbajack.Test
|
||||
await Install(compiler);
|
||||
return compiler.ModList;
|
||||
}
|
||||
|
||||
protected async Task<NativeCompiler> ConfigureAndRunCompiler(AbsolutePath configPath, bool useGameFiles= false)
|
||||
{
|
||||
var settings = configPath.FromJson<NativeCompilerSettings>();
|
||||
var profile = utils.AddProfile();
|
||||
|
||||
var compiler = new NativeCompiler(
|
||||
settings: settings,
|
||||
sourcePath: utils.SourcePath,
|
||||
downloadsPath: utils.DownloadsPath,
|
||||
outputModListPath: OutputFile(profile))
|
||||
{UseGamePaths = useGameFiles};
|
||||
Assert.True(await compiler.Begin());
|
||||
return compiler;
|
||||
}
|
||||
protected async Task<ModList> CompileAndInstall(AbsolutePath settingsPath, bool useGameFiles = false)
|
||||
{
|
||||
var compiler = await ConfigureAndRunCompiler(settingsPath, useGameFiles: useGameFiles);
|
||||
Utils.Log("Finished Compiling");
|
||||
await Install(compiler);
|
||||
return compiler.ModList;
|
||||
}
|
||||
|
||||
private static AbsolutePath OutputFile(string profile)
|
||||
{
|
||||
return ((RelativePath)profile).RelativeToEntryPoint().WithExtension(Consts.ModListExtension);
|
||||
}
|
||||
|
||||
protected async Task Install(MO2Compiler compiler)
|
||||
protected async Task Install(ACompiler compiler)
|
||||
{
|
||||
Utils.Log("Loading Modlist");
|
||||
var modlist = AInstaller.LoadFromFile(compiler.ModListOutputFile);
|
||||
@ -66,8 +88,8 @@ namespace Wabbajack.Test
|
||||
var installer = new MO2Installer(
|
||||
archive: compiler.ModListOutputFile,
|
||||
modList: modlist,
|
||||
outputFolder: utils.InstallFolder,
|
||||
downloadFolder: utils.DownloadsFolder,
|
||||
outputFolder: utils.InstallPath,
|
||||
downloadFolder: utils.DownloadsPath,
|
||||
parameters: CreateDummySystemParameters());
|
||||
installer.WarnOnOverwrite = false;
|
||||
installer.GameFolder = utils.GameFolder;
|
||||
|
@ -52,7 +52,7 @@ namespace Wabbajack.Test
|
||||
await DownloadAndInstall(
|
||||
"https://github.com/ModOrganizer2/modorganizer/releases/download/v2.2.1/Mod.Organizer.2.2.1.7z",
|
||||
"Mod.Organizer.2.2.1.7z");
|
||||
await utils.DownloadsFolder.Combine("Mod.Organizer.2.2.1.7z.meta").WriteAllLinesAsync(
|
||||
await utils.DownloadsPath.Combine("Mod.Organizer.2.2.1.7z.meta").WriteAllLinesAsync(
|
||||
"[General]",
|
||||
"directURL=https://github.com/ModOrganizer2/modorganizer/releases/download/v2.2.1/Mod.Organizer.2.2.1.7z"
|
||||
);
|
||||
@ -75,7 +75,7 @@ namespace Wabbajack.Test
|
||||
$"matchAll= {modfiles[2].Download.FileName}"
|
||||
);
|
||||
|
||||
await utils.MO2Folder.Combine("startup.bat").WriteAllLinesAsync(
|
||||
await utils.SourcePath.Combine("startup.bat").WriteAllLinesAsync(
|
||||
"ModOrganizer2.exe SKSE"
|
||||
);
|
||||
|
||||
@ -83,11 +83,11 @@ namespace Wabbajack.Test
|
||||
await CompileAndInstall(profile);
|
||||
await utils.VerifyAllFiles();
|
||||
|
||||
await utils.InstallFolder.Combine(Consts.LOOTFolderFilesDir).DeleteDirectory();
|
||||
await utils.InstallPath.Combine(Consts.LOOTFolderFilesDir).DeleteDirectory();
|
||||
|
||||
var compiler = new MO2Compiler(
|
||||
sourcePath: utils.InstallFolder,
|
||||
downloadsPath: utils.DownloadsFolder,
|
||||
sourcePath: utils.InstallPath,
|
||||
downloadsPath: utils.DownloadsPath,
|
||||
mo2Profile: profile,
|
||||
outputFile: profile.RelativeTo(AbsolutePath.EntryPoint).WithExtension(Consts.ModListExtension));
|
||||
Assert.True(await compiler.Begin());
|
||||
@ -105,12 +105,12 @@ namespace Wabbajack.Test
|
||||
await state.Download(new Archive(state: null!) { Name = "Unknown"}, src);
|
||||
}
|
||||
|
||||
utils.DownloadsFolder.CreateDirectory();
|
||||
utils.DownloadsPath.CreateDirectory();
|
||||
|
||||
var destFile = utils.DownloadsFolder.Combine(filename);
|
||||
var destFile = utils.DownloadsPath.Combine(filename);
|
||||
await src.CopyToAsync(destFile);
|
||||
|
||||
var modFolder = modName == null ? utils.MO2Folder : utils.ModsFolder.Combine(modName);
|
||||
var modFolder = modName == null ? utils.SourcePath : utils.ModsPath.Combine(modName);
|
||||
await FileExtractor2.ExtractAll(Queue, src, modFolder);
|
||||
return (destFile, modFolder);
|
||||
}
|
||||
@ -140,12 +140,12 @@ namespace Wabbajack.Test
|
||||
await state.Download(src);
|
||||
}
|
||||
|
||||
utils.DownloadsFolder.CreateDirectory();
|
||||
utils.DownloadsPath.CreateDirectory();
|
||||
|
||||
var dest = utils.DownloadsFolder.Combine(file.file_name);
|
||||
var dest = utils.DownloadsPath.Combine(file.file_name);
|
||||
await src.CopyToAsync(dest);
|
||||
|
||||
var modFolder = utils.ModsFolder.Combine(modName);
|
||||
var modFolder = utils.ModsPath.Combine(modName);
|
||||
await FileExtractor2.ExtractAll(Queue, src, modFolder);
|
||||
|
||||
await dest.WithExtension(Consts.MetaFileExtension).WriteAllTextAsync(ini);
|
||||
@ -165,8 +165,8 @@ namespace Wabbajack.Test
|
||||
var installer = new MO2Installer(
|
||||
archive: compiler.ModListOutputFile,
|
||||
modList: modlist,
|
||||
outputFolder: utils.InstallFolder,
|
||||
downloadFolder: utils.DownloadsFolder,
|
||||
outputFolder: utils.InstallPath,
|
||||
downloadFolder: utils.DownloadsPath,
|
||||
parameters: ACompilerTest.CreateDummySystemParameters())
|
||||
{
|
||||
UseCompression = true
|
||||
@ -178,8 +178,8 @@ namespace Wabbajack.Test
|
||||
private async Task<MO2Compiler> ConfigureAndRunCompiler(string profile)
|
||||
{
|
||||
var compiler = new MO2Compiler(
|
||||
sourcePath: utils.MO2Folder,
|
||||
downloadsPath: utils.DownloadsFolder,
|
||||
sourcePath: utils.SourcePath,
|
||||
downloadsPath: utils.DownloadsPath,
|
||||
mo2Profile: profile,
|
||||
outputFile: profile.RelativeTo(AbsolutePath.EntryPoint).WithExtension(Consts.ModListExtension));
|
||||
Assert.True(await compiler.Begin());
|
||||
|
@ -54,7 +54,7 @@ namespace Wabbajack.Test
|
||||
await utils.AddManualDownload(
|
||||
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
|
||||
|
||||
await utils.DownloadsFolder.Combine("some_other_file.7z").WriteAllTextAsync("random data");
|
||||
await utils.DownloadsPath.Combine("some_other_file.7z").WriteAllTextAsync("random data");
|
||||
|
||||
await CompileAndInstall(profile);
|
||||
|
||||
@ -90,14 +90,14 @@ namespace Wabbajack.Test
|
||||
|
||||
await utils.Configure();
|
||||
|
||||
utils.MO2Folder.Combine(Consts.GameFolderFilesDir).CreateDirectory();
|
||||
utils.SourcePath.Combine(Consts.GameFolderFilesDir).CreateDirectory();
|
||||
|
||||
await utils.AddManualDownload(
|
||||
new Dictionary<string, byte[]> {{"/baz/biz.pex", await testPex.ReadAllBytesAsync()}});
|
||||
|
||||
await CompileAndInstall(profile);
|
||||
|
||||
Assert.False(utils.InstallFolder.Combine(Consts.GameFolderFilesDir, (RelativePath)@"enbstuff\test.pex").IsFile);
|
||||
Assert.False(utils.InstallPath.Combine(Consts.GameFolderFilesDir, (RelativePath)@"enbstuff\test.pex").IsFile);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -188,12 +188,12 @@ namespace Wabbajack.Test
|
||||
var profile = utils.AddProfile();
|
||||
var mod = await utils.AddMod("dummy");
|
||||
|
||||
var saveFolder = utils.MO2Folder.Combine("profiles", profile, "saves");
|
||||
var saveFolder = utils.SourcePath.Combine("profiles", profile, "saves");
|
||||
saveFolder.CreateDirectory();
|
||||
await saveFolder.Combine("incompilation").WriteAllTextAsync("ignore this");
|
||||
|
||||
var installSaveFolderThisProfile = utils.InstallFolder.Combine("profiles", profile, "saves");
|
||||
var installSaveFolderOtherProfile = utils.InstallFolder.Combine("profiles", "Other Profile", "saves");
|
||||
var installSaveFolderThisProfile = utils.InstallPath.Combine("profiles", profile, "saves");
|
||||
var installSaveFolderOtherProfile = utils.InstallPath.Combine("profiles", "Other Profile", "saves");
|
||||
installSaveFolderThisProfile.CreateDirectory();
|
||||
installSaveFolderOtherProfile.CreateDirectory();
|
||||
|
||||
@ -215,7 +215,7 @@ namespace Wabbajack.Test
|
||||
var mod = await utils.AddMod("dummy");
|
||||
|
||||
await utils.Configure();
|
||||
await utils.MO2Folder.Combine("profiles", profile, "somegameprefs.ini").WriteAllLinesAsync(
|
||||
await utils.SourcePath.Combine("profiles", profile, "somegameprefs.ini").WriteAllLinesAsync(
|
||||
// Beth inis are messy, let's make ours just as messy to catch some parse failures
|
||||
"[Display]",
|
||||
"foo=4",
|
||||
@ -231,7 +231,7 @@ namespace Wabbajack.Test
|
||||
|
||||
var modlist = await CompileAndInstall(profile);
|
||||
|
||||
var ini = utils.InstallFolder.Combine("profiles", profile, "somegameprefs.ini").LoadIniFile();
|
||||
var ini = utils.InstallPath.Combine("profiles", profile, "somegameprefs.ini").LoadIniFile();
|
||||
|
||||
var sysinfo = CreateDummySystemParameters();
|
||||
|
||||
@ -511,7 +511,7 @@ namespace Wabbajack.Test
|
||||
await new CompilerSettings()
|
||||
{
|
||||
IncludedGames = new []{Game.Morrowind}
|
||||
}.ToJsonAsync(utils.MO2Folder.Combine("profiles", profile, CompilerSettings.FileName), true);
|
||||
}.ToJsonAsync(utils.SourcePath.Combine("profiles", profile, CompilerSettings.FileName), true);
|
||||
|
||||
Game.SkyrimSpecialEdition.MetaData().CanSourceFrom = new[] {Game.Morrowind, Game.Skyrim};
|
||||
|
||||
@ -540,7 +540,7 @@ namespace Wabbajack.Test
|
||||
await utils.VerifyInstalledFile(mod, @"Data\SkyrimSE\Update.esm.old");
|
||||
await utils.VerifyInstalledFile(mod, @"Data\SkyrimSE\Update.esm");
|
||||
|
||||
Assert.False(utils.InstallFolder.Combine(Consts.GameFolderFilesDir).IsDirectory);
|
||||
Assert.False(utils.InstallPath.Combine(Consts.GameFolderFilesDir).IsDirectory);
|
||||
|
||||
}
|
||||
|
||||
@ -554,8 +554,8 @@ namespace Wabbajack.Test
|
||||
|
||||
await utils.Configure();
|
||||
|
||||
utils.MO2Folder.Combine(Consts.GameFolderFilesDir).CreateDirectory();
|
||||
await utils.MO2Folder.Combine(Consts.GameFolderFilesDir).Combine("dx4242.dll")
|
||||
utils.SourcePath.Combine(Consts.GameFolderFilesDir).CreateDirectory();
|
||||
await utils.SourcePath.Combine(Consts.GameFolderFilesDir).Combine("dx4242.dll")
|
||||
.WriteAllBytesAsync(utils.RandomData());
|
||||
|
||||
await utils.AddManualDownload(
|
||||
@ -580,7 +580,7 @@ namespace Wabbajack.Test
|
||||
var disabledMod = await utils.AddMod();
|
||||
var disabledTestPex = await utils.AddModFile(disabledMod, @"Data\scripts\disabledTestPex.pex", 10);
|
||||
|
||||
await disabledMod.RelativeTo(utils.ModsFolder).Combine("meta.ini").WriteAllLinesAsync(
|
||||
await disabledMod.RelativeTo(utils.ModsPath).Combine("meta.ini").WriteAllLinesAsync(
|
||||
"[General]",
|
||||
$"notes={Consts.WABBAJACK_ALWAYS_ENABLE}");
|
||||
|
||||
@ -602,7 +602,7 @@ namespace Wabbajack.Test
|
||||
await utils.VerifyInstalledFile(enabledMod, @"Data\scripts\enabledTestPex.pex");
|
||||
await utils.VerifyInstalledFile(disabledMod, @"Data\scripts\disabledTestPex.pex");
|
||||
|
||||
var modlistTxt = await utils.InstallFolder.Combine("profiles", profile, "modlist.txt").ReadAllLinesAsync();
|
||||
var modlistTxt = await utils.InstallPath.Combine("profiles", profile, "modlist.txt").ReadAllLinesAsync();
|
||||
Assert.Equal(new string[]
|
||||
{
|
||||
$"-{disabledMod}",
|
||||
@ -610,5 +610,43 @@ namespace Wabbajack.Test
|
||||
}, modlistTxt.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanCompileFromNativeSource()
|
||||
{
|
||||
utils.CreatePaths();
|
||||
|
||||
var gameFolder = Game.SkyrimSpecialEdition.MetaData().GameLocation();
|
||||
await gameFolder.Combine("SkyrimSE.exe").CopyToAsync(utils.SourcePath.Combine("SkyrimSE.exe"));
|
||||
|
||||
var some_dds = utils.SourcePath.Combine("some_file.dds");
|
||||
await some_dds.WriteAllBytesAsync(utils.RandomData());
|
||||
|
||||
await utils.AddManualDownload(
|
||||
new Dictionary<string, byte[]>
|
||||
{
|
||||
{"/file1.blerg", await some_dds.ReadAllBytesAsync()},
|
||||
});
|
||||
|
||||
var settings = new NativeCompilerSettings
|
||||
{
|
||||
CompilingGame = Game.SkyrimSpecialEdition,
|
||||
CompilationSteps = new []
|
||||
{
|
||||
new []{"IgnoreStartsWith", "downloads"},
|
||||
new []{"IncludeConfigs"},
|
||||
new []{"IncludeDirectMatches"},
|
||||
}
|
||||
};
|
||||
|
||||
var settingsPath = utils.SourcePath.Combine("native_compiler_settings.json");
|
||||
await settings.ToJsonAsync(utils.SourcePath.Combine("native_compiler_settings.json"), true);
|
||||
|
||||
await CompileAndInstall(settingsPath, true);
|
||||
|
||||
Assert.Equal(await some_dds.FileHashAsync(), await utils.InstallPath.Combine("some_file.dds").FileHashAsync());
|
||||
Assert.Equal(await gameFolder.Combine("SkyrimSE.exe").FileHashAsync(),
|
||||
await utils.InstallPath.Combine("SkyrimSE.exe").FileHashAsync());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,11 @@ namespace Wabbajack.Test
|
||||
public AbsolutePath TestFolder => WorkingDirectory.Combine(ID);
|
||||
public AbsolutePath GameFolder => WorkingDirectory.Combine(ID, "game_folder");
|
||||
|
||||
public AbsolutePath MO2Folder => WorkingDirectory.Combine(ID, "mo2_folder");
|
||||
public AbsolutePath ModsFolder => MO2Folder.Combine(Consts.MO2ModFolderName);
|
||||
public AbsolutePath DownloadsFolder => MO2Folder.Combine("downloads");
|
||||
public AbsolutePath SourcePath => WorkingDirectory.Combine(ID, "source_folder");
|
||||
public AbsolutePath ModsPath => SourcePath.Combine(Consts.MO2ModFolderName);
|
||||
public AbsolutePath DownloadsPath => SourcePath.Combine("downloads");
|
||||
|
||||
public AbsolutePath InstallFolder => TestFolder.Combine("installed");
|
||||
public AbsolutePath InstallPath => TestFolder.Combine("installed");
|
||||
|
||||
public HashSet<string> Profiles = new HashSet<string>();
|
||||
|
||||
@ -44,20 +44,20 @@ namespace Wabbajack.Test
|
||||
|
||||
public async Task Configure(IEnumerable<(string ModName, bool IsEnabled)> enabledMods = null)
|
||||
{
|
||||
await MO2Folder.Combine("ModOrganizer.ini").WriteAllLinesAsync(
|
||||
await SourcePath.Combine("ModOrganizer.ini").WriteAllLinesAsync(
|
||||
"[General]",
|
||||
$"gameName={Game.MetaData().MO2Name}",
|
||||
$"gamePath={((string)GameFolder).Replace("\\", "\\\\")}",
|
||||
$"download_directory={DownloadsFolder}");
|
||||
$"download_directory={DownloadsPath}");
|
||||
|
||||
DownloadsFolder.CreateDirectory();
|
||||
DownloadsPath.CreateDirectory();
|
||||
GameFolder.Combine("Data").CreateDirectory();
|
||||
|
||||
if (enabledMods == null)
|
||||
{
|
||||
Profiles.Do(profile =>
|
||||
{
|
||||
MO2Folder.Combine("profiles", profile, "modlist.txt").WriteAllLinesAsync(
|
||||
SourcePath.Combine("profiles", profile, "modlist.txt").WriteAllLinesAsync(
|
||||
Mods.Select(s => $"+{s}").ToArray());
|
||||
});
|
||||
}
|
||||
@ -65,7 +65,7 @@ namespace Wabbajack.Test
|
||||
{
|
||||
Profiles.Do(profile =>
|
||||
{
|
||||
MO2Folder.Combine("profiles", profile, "modlist.txt").WriteAllLinesAsync(
|
||||
SourcePath.Combine("profiles", profile, "modlist.txt").WriteAllLinesAsync(
|
||||
enabledMods.Select(s => $"{(s.IsEnabled ? "+" : "-")}{s.ModName}").ToArray());
|
||||
});
|
||||
}
|
||||
@ -74,7 +74,7 @@ namespace Wabbajack.Test
|
||||
public string AddProfile(string name = null)
|
||||
{
|
||||
string profile_name = name ?? RandomName();
|
||||
MO2Folder.Combine("profiles", profile_name).CreateDirectory();
|
||||
SourcePath.Combine("profiles", profile_name).CreateDirectory();
|
||||
Profiles.Add(profile_name);
|
||||
return profile_name;
|
||||
}
|
||||
@ -82,7 +82,7 @@ namespace Wabbajack.Test
|
||||
public async Task<string> AddMod(string name = null)
|
||||
{
|
||||
string mod_name = name ?? RandomName();
|
||||
var mod_folder = MO2Folder.Combine(Consts.MO2ModFolderName, (RelativePath)mod_name);
|
||||
var mod_folder = SourcePath.Combine(Consts.MO2ModFolderName, (RelativePath)mod_name);
|
||||
mod_folder.CreateDirectory();
|
||||
await mod_folder.Combine("meta.ini").WriteAllTextAsync("[General]");
|
||||
Mods.Add(mod_name);
|
||||
@ -99,7 +99,7 @@ namespace Wabbajack.Test
|
||||
/// <returns></returns>
|
||||
public async Task<AbsolutePath> AddModFile(string mod_name, string path, int random_fill=128)
|
||||
{
|
||||
var full_path = ModsFolder.Combine(mod_name, path);
|
||||
var full_path = ModsPath.Combine(mod_name, path);
|
||||
full_path.Parent.CreateDirectory();
|
||||
await GenerateRandomFileData(full_path, random_fill);
|
||||
return full_path;
|
||||
@ -161,7 +161,7 @@ namespace Wabbajack.Test
|
||||
{
|
||||
var name = RandomName() + ".zip";
|
||||
|
||||
await using FileStream fs = await DownloadsFolder.Combine(name).Create();
|
||||
await using FileStream fs = await DownloadsPath.Combine(name).Create();
|
||||
using ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create);
|
||||
contents.Do(kv =>
|
||||
{
|
||||
@ -170,7 +170,7 @@ namespace Wabbajack.Test
|
||||
os.Write(kv.Value, 0, kv.Value.Length);
|
||||
});
|
||||
|
||||
await DownloadsFolder.Combine(name + Consts.MetaFileExtension).WriteAllLinesAsync(
|
||||
await DownloadsPath.Combine(name + Consts.MetaFileExtension).WriteAllLinesAsync(
|
||||
"[General]",
|
||||
"manualURL=<TESTING>"
|
||||
);
|
||||
@ -180,10 +180,10 @@ namespace Wabbajack.Test
|
||||
|
||||
public async Task VerifyInstalledFile(string mod, string file)
|
||||
{
|
||||
var src = MO2Folder.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
var src = SourcePath.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
Assert.True(src.Exists);
|
||||
|
||||
var dest = InstallFolder.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
var dest = InstallPath.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
Assert.True(dest.Exists, $"Destination {dest} doesn't exist");
|
||||
|
||||
var srcData = await src.ReadAllBytesAsync();
|
||||
@ -203,7 +203,7 @@ namespace Wabbajack.Test
|
||||
var src = GameFolder.Combine(file);
|
||||
Assert.True(src.Exists);
|
||||
|
||||
var dest = InstallFolder.Combine((string)Consts.GameFolderFilesDir, file);
|
||||
var dest = InstallPath.Combine((string)Consts.GameFolderFilesDir, file);
|
||||
Assert.True(dest.Exists);
|
||||
|
||||
var srcData = await src.ReadAllBytesAsync();
|
||||
@ -219,7 +219,7 @@ namespace Wabbajack.Test
|
||||
}
|
||||
public AbsolutePath PathOfInstalledFile(string mod, string file)
|
||||
{
|
||||
return InstallFolder.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
return InstallPath.Combine((string)Consts.MO2ModFolderName, mod, file);
|
||||
}
|
||||
|
||||
public async ValueTask VerifyAllFiles(bool gameFileShouldNotExistInGameFolder = true)
|
||||
@ -228,32 +228,32 @@ namespace Wabbajack.Test
|
||||
{
|
||||
foreach (var file in Game.MetaData().RequiredFiles!)
|
||||
{
|
||||
Assert.False(InstallFolder.Combine(Consts.GameFolderFilesDir, (RelativePath)file).Exists);
|
||||
Assert.False(InstallPath.Combine(Consts.GameFolderFilesDir, (RelativePath)file).Exists);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var skipFiles = new []{"portable.txt"}.Select(e => (RelativePath)e).ToHashSet();
|
||||
foreach (var destFile in InstallFolder.EnumerateFiles())
|
||||
foreach (var destFile in InstallPath.EnumerateFiles())
|
||||
{
|
||||
var relFile = destFile.RelativeTo(InstallFolder);
|
||||
if (destFile.InFolder(Consts.LOOTFolderFilesDir.RelativeTo(MO2Folder)) || destFile.InFolder(Consts.GameFolderFilesDir.RelativeTo(MO2Folder)))
|
||||
var relFile = destFile.RelativeTo(InstallPath);
|
||||
if (destFile.InFolder(Consts.LOOTFolderFilesDir.RelativeTo(SourcePath)) || destFile.InFolder(Consts.GameFolderFilesDir.RelativeTo(SourcePath)))
|
||||
continue;
|
||||
|
||||
if (!skipFiles.Contains(relFile))
|
||||
Assert.True(MO2Folder.Combine(relFile).Exists, $"Only in Destination: {relFile}");
|
||||
Assert.True(SourcePath.Combine(relFile).Exists, $"Only in Destination: {relFile}");
|
||||
}
|
||||
|
||||
var skipExtensions = new []{".txt", ".ini"}.Select(e => new Extension(e)).ToHashSet();
|
||||
|
||||
foreach (var srcFile in MO2Folder.EnumerateFiles())
|
||||
foreach (var srcFile in SourcePath.EnumerateFiles())
|
||||
{
|
||||
var relFile = srcFile.RelativeTo(MO2Folder);
|
||||
var relFile = srcFile.RelativeTo(SourcePath);
|
||||
|
||||
if (relFile.StartsWith("downloads\\"))
|
||||
continue;
|
||||
|
||||
var destFile = InstallFolder.Combine(relFile);
|
||||
var destFile = InstallPath.Combine(relFile);
|
||||
Assert.True(destFile.Exists, $"Only in Source: {relFile}");
|
||||
|
||||
if (!skipExtensions.Contains(srcFile.Extension))
|
||||
@ -271,5 +271,12 @@ namespace Wabbajack.Test
|
||||
await GenerateRandomFileData(fullPath, i);
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public void CreatePaths()
|
||||
{
|
||||
SourcePath.CreateDirectory();
|
||||
DownloadsPath.CreateDirectory();
|
||||
InstallPath.CreateDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ namespace Wabbajack.VirtualFileSystem
|
||||
}
|
||||
|
||||
}
|
||||
await filesByParent[top].PMap(queue, async file => await HandleFile(file, new ExtractedNativeFile(file.AbsoluteName)));
|
||||
await filesByParent[top].PMap(queue, async file => await HandleFile(file, new ExtractedNativeFile(file.AbsoluteName) {CanMove = false}));
|
||||
}
|
||||
|
||||
#region KnownFiles
|
||||
|
Loading…
Reference in New Issue
Block a user