Merge pull request #1453 from Unnoen/omni-1

Miscellaneous fixes and improvements.
This commit is contained in:
Timothy Baldridge 2021-05-21 08:09:48 -07:00 committed by GitHub
commit 760a920eb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 90 additions and 46 deletions

View File

@ -75,7 +75,7 @@ namespace Wabbajack.CLI.Verbs
var mdText = var mdText =
$"## {update.Version}\n\n" + $"## {update.Version}\n\n" +
$"**Build at:** `{File.GetCreationTime(Update)}`\n\n" + $"**Build at:** `{File.GetLastWriteTime(Update)}`\n\n" +
"**Info**:\n\n" + "**Info**:\n\n" +
$"- Download Size change: {downloadSizeChanges.ToFileSizeString()} (Total: {update.DownloadSize.ToFileSizeString()})\n" + $"- Download Size change: {downloadSizeChanges.ToFileSizeString()} (Total: {update.DownloadSize.ToFileSizeString()})\n" +
$"- Install Size change: {installSizeChanges.ToFileSizeString()} (Total: {update.InstallSize.ToFileSizeString()})\n\n"; $"- Install Size change: {installSizeChanges.ToFileSizeString()} (Total: {update.InstallSize.ToFileSizeString()})\n\n";

View File

@ -30,7 +30,7 @@ namespace Wabbajack.Common
private static readonly Subject<IStatusMessage> LoggerSubj = new Subject<IStatusMessage>(); private static readonly Subject<IStatusMessage> LoggerSubj = new Subject<IStatusMessage>();
public static IObservable<IStatusMessage> LogMessages => LoggerSubj; public static IObservable<IStatusMessage> LogMessages => LoggerSubj;
public static async Task InitalizeLogging() public static async Task InitializeLogging()
{ {
_startTime = DateTime.Now; _startTime = DateTime.Now;
@ -126,7 +126,7 @@ namespace Wabbajack.Common
if (!LoggingSettings.LogToFile || LogFile == default) return; if (!LoggingSettings.LogToFile || LogFile == default) return;
lock (_logLock) lock (_logLock)
{ {
File.AppendAllText(LogFile.ToString(), $"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}\r\n"); File.AppendAllText(LogFile.ToString(), $"{(DateTime.Now - _startTime).TotalSeconds:0.##} - {msg}\r\n", new UTF8Encoding(false, true));
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -209,6 +209,21 @@ namespace Wabbajack.Common
return new RelativePath(relPath); return new RelativePath(relPath);
} }
public bool IsChildOf(AbsolutePath? parent)
{
if (parent is null) return false;
var child = this;
if (child == parent) return true;
while (child.Parent.Exists)
{
if (child.Parent == parent)
{
return true;
}
child = child.Parent;
}
return false;
}
public async Task<string> ReadAllTextAsync() public async Task<string> ReadAllTextAsync()
{ {

View File

@ -38,7 +38,7 @@ namespace Wabbajack.Common
static Utils() static Utils()
{ {
InitalizeLogging().Wait(); InitializeLogging().Wait();
} }
private static readonly string[] Suffix = {"B", "KB", "MB", "GB", "TB", "PB", "EB"}; // Longs run out around EB private static readonly string[] Suffix = {"B", "KB", "MB", "GB", "TB", "PB", "EB"}; // Longs run out around EB

View File

@ -174,7 +174,12 @@ namespace Wabbajack.Lib
{ {
Utils.Log("Installation has Started"); Utils.Log("Installation has Started");
_isRunning.OnNext(true); _isRunning.OnNext(true);
return await _Begin(_cancel.Token); var task = await _Begin(_cancel.Token);
Utils.Log("Vacuuming databases");
HashCache.VacuumDatabase();
VirtualFile.VacuumDatabase();
Utils.Log("Vacuuming completed");
return task;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -183,10 +188,6 @@ namespace Wabbajack.Lib
} }
finally finally
{ {
Utils.Log("Vacuuming databases");
HashCache.VacuumDatabase();
VirtualFile.VacuumDatabase();
Utils.Log("Vacuuming completed");
_isRunning.OnNext(false); _isRunning.OnNext(false);
} }
}); });

View File

@ -1,4 +1,4 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@ -22,6 +22,7 @@ using File = Alphaleonis.Win32.Filesystem.File;
using Path = Alphaleonis.Win32.Filesystem.Path; using Path = Alphaleonis.Win32.Filesystem.Path;
using SectionData = Wabbajack.Common.SectionData; using SectionData = Wabbajack.Common.SectionData;
using System.Collections.Generic; using System.Collections.Generic;
using Wabbajack.Common.IO;
using Wabbajack.Lib.ModListRegistry; using Wabbajack.Lib.ModListRegistry;
using Wabbajack.VirtualFileSystem; using Wabbajack.VirtualFileSystem;
@ -69,21 +70,19 @@ namespace Wabbajack.Lib
var otherGame = Game.CommonlyConfusedWith.Where(g => g.MetaData().IsInstalled).Select(g => g.MetaData()).FirstOrDefault(); var otherGame = Game.CommonlyConfusedWith.Where(g => g.MetaData().IsInstalled).Select(g => g.MetaData()).FirstOrDefault();
if (otherGame != null) if (otherGame != null)
{ {
await Utils.Log(new CriticalFailureIntervention( Utils.Error(new CriticalFailureIntervention(
$"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed, we did however find a installed " + $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed, we did however find an installed " +
$"copy of {otherGame.HumanFriendlyGameName}, did you install the wrong game?", $"copy of {otherGame.HumanFriendlyGameName}, did you install the wrong game?",
$"Could not locate {Game.HumanFriendlyGameName}")) $"Could not locate {Game.HumanFriendlyGameName}"));
.Task;
} }
else else
{ {
await Utils.Log(new CriticalFailureIntervention( Utils.Error(new CriticalFailureIntervention(
$"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed", $"In order to do a proper install Wabbajack needs to know where your {Game.HumanFriendlyGameName} folder resides. However this game doesn't seem to be installed.",
$"Could not locate {Game.HumanFriendlyGameName}")) $"Could not locate {Game.HumanFriendlyGameName}"));
.Task;
} }
Utils.Log("Exiting because we couldn't find the game folder."); Utils.Error("Exiting because we couldn't find the game folder.");
return false; return false;
} }
@ -503,14 +502,24 @@ namespace Wabbajack.Lib
await OutputFolder.Combine(directive.To).WriteAllTextAsync(data); await OutputFolder.Combine(directive.To).WriteAllTextAsync(data);
} }
public static IErrorResponse CheckValidInstallPath(AbsolutePath path, AbsolutePath? downloadFolder) public static IErrorResponse CheckValidInstallPath(AbsolutePath path, AbsolutePath? downloadFolder, GameMetaData? game)
{ {
// Check if null path
if (string.IsNullOrEmpty(path.ToString())) return ErrorResponse.Fail("Please select an install directory.");
// Check if child of game folder
if (game?.TryGetGameLocation() != null && path.IsChildOf(game.TryGetGameLocation())) return ErrorResponse.Fail("Cannot install to game directory.");
// Check if child of Program Files
if (path.IsChildOf(new AbsolutePath(KnownFolders.ProgramFiles.Path))) return ErrorResponse.Fail("Cannot install to Program Files directory.");
// If the folder doesn't exist, it's empty so we don't need to check further
if (!path.Exists) return ErrorResponse.Success; if (!path.Exists) return ErrorResponse.Success;
// Check folder does not have a Wabbajack ModList // Check folder does not have a Wabbajack ModList
if (path.EnumerateFiles(false).Where(file => file.Exists).Any(file => file.Extension == Consts.ModListExtension)) if (path.EnumerateFiles(false).Where(file => file.Exists).Any(file => file.Extension == Consts.ModListExtension))
{ {
return ErrorResponse.Fail($"Cannot install into a folder with a Wabbajack ModList inside of it"); return ErrorResponse.Fail($"Cannot install into a folder with a Wabbajack ModList inside of it.");
} }
// Check if folder is empty // Check if folder is empty

View File

@ -12,13 +12,17 @@ namespace Wabbajack.Lib
private TaskCompletionSource<ConfirmationIntervention.Choice> _source = new TaskCompletionSource<ConfirmationIntervention.Choice>(); private TaskCompletionSource<ConfirmationIntervention.Choice> _source = new TaskCompletionSource<ConfirmationIntervention.Choice>();
public Task<ConfirmationIntervention.Choice> Task => _source.Task; public Task<ConfirmationIntervention.Choice> Task => _source.Task;
public CriticalFailureIntervention(string description, string title) public CriticalFailureIntervention(string description, string title, bool exit = false)
{ {
ExtendedDescription = description; ExtendedDescription = description;
ShortDescription = title; ShortDescription = title;
ExitApplication = exit;
} }
public override string ShortDescription { get; } public override string ShortDescription { get; }
public override string ExtendedDescription { get; } public override string ExtendedDescription { get; }
public bool ExitApplication { get; }
public void Cancel() public void Cancel()
{ {
_source.SetResult(ConfirmationIntervention.Choice.Abort); _source.SetResult(ConfirmationIntervention.Choice.Abort);

View File

@ -13,14 +13,14 @@ namespace Wabbajack.Test
public async Task CheckValidInstallPath_Empty() public async Task CheckValidInstallPath_Empty()
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
public async Task CheckValidInstallPath_DoesNotExist() public async Task CheckValidInstallPath_DoesNotExist()
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir.Combine("Subfolder"), downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir.Combine("Subfolder"), null, null).Succeeded);
} }
[Fact] [Fact]
@ -29,7 +29,7 @@ namespace Wabbajack.Test
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
await using var mo2 = await tempDir.Dir.Combine("ModOrganizer.exe").Create(); await using var mo2 = await tempDir.Dir.Combine("ModOrganizer.exe").Create();
await using var molist = await tempDir.Dir.Combine(((RelativePath)"modlist")).WithExtension(Consts.ModListExtension).Create(); await using var molist = await tempDir.Dir.Combine(((RelativePath)"modlist")).WithExtension(Consts.ModListExtension).Create();
Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -37,7 +37,7 @@ namespace Wabbajack.Test
{ {
await using var tempDir = await TempFolder.Create(); await using var tempDir = await TempFolder.Create();
await using var tmp = await tempDir.Dir.Combine(Consts.ModOrganizer2Exe).Create(); await using var tmp = await tempDir.Dir.Combine(Consts.ModOrganizer2Exe).Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -47,7 +47,7 @@ namespace Wabbajack.Test
await tempDir.Dir.DeleteDirectory(); await tempDir.Dir.DeleteDirectory();
tempDir.Dir.CreateDirectory(); tempDir.Dir.CreateDirectory();
await using var tmp = await tempDir.Dir.Combine($"someFile.txt").Create(); await using var tmp = await tempDir.Dir.Combine($"someFile.txt").Create();
Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: null).Succeeded); Assert.False(MO2Installer.CheckValidInstallPath(tempDir.Dir, null, null).Succeeded);
} }
[Fact] [Fact]
@ -57,7 +57,14 @@ namespace Wabbajack.Test
var downloadsFolder = tempDir.Dir.Combine("downloads"); var downloadsFolder = tempDir.Dir.Combine("downloads");
downloadsFolder.CreateDirectory(); downloadsFolder.CreateDirectory();
await using var tmp = await tempDir.Dir.Combine($"downloads/someFile.txt").Create(); await using var tmp = await tempDir.Dir.Combine($"downloads/someFile.txt").Create();
Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadFolder: downloadsFolder).Succeeded); Assert.True(MO2Installer.CheckValidInstallPath(tempDir.Dir, downloadsFolder, null).Succeeded);
}
[Fact]
public async Task CheckValidInstallPath_NullPath()
{
var tempDir = new AbsolutePath("", true);
Assert.True(MO2Installer.CheckValidInstallPath(tempDir, null, null).Succeeded == false);
} }
#endregion #endregion
} }

View File

@ -16,7 +16,7 @@ namespace Wabbajack
Consts.LogsFolder.CreateDirectory(); Consts.LogsFolder.CreateDirectory();
LoggingSettings.LogToFile = true; LoggingSettings.LogToFile = true;
Utils.InitalizeLogging().Wait(); Utils.InitializeLogging().Wait();
CLIOld.ParseOptions(Environment.GetCommandLineArgs()); CLIOld.ParseOptions(Environment.GetCommandLineArgs());
if (CLIArguments.Help) if (CLIArguments.Help)

View File

@ -97,13 +97,19 @@ namespace Wabbajack
public InstallerVM(MainWindowVM mainWindowVM) : base(mainWindowVM) public InstallerVM(MainWindowVM mainWindowVM) : base(mainWindowVM)
{ {
if (AbsolutePath.EntryPoint.IsChildOf(new AbsolutePath(KnownFolders.Downloads.Path)))
if (Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.ToLower()) == KnownFolders.Downloads.Path.ToLower())
{ {
Utils.Error(new CriticalFailureIntervention( Utils.Error(new CriticalFailureIntervention(
"Wabbajack is running inside your Downloads folder. This folder is often highly monitored by antivirus software and these can often " + "Wabbajack is running inside your Downloads folder. This folder is often highly monitored by antivirus software and these can often " +
"conflict with the operations Wabbajack needs to perform. Please move this executable outside of your Downloads folder and then restart the app.", "conflict with the operations Wabbajack needs to perform. Please move Wabbajack outside of your Downloads folder and then restart the app.",
"Cannot run inside Downloads")); "Cannot run inside Downloads", true));
}
else if (AbsolutePath.EntryPoint.IsChildOf(new AbsolutePath(KnownFolders.SkyDrive.Path)))
{
Utils.Error(new CriticalFailureIntervention(
$"Wabbajack is running inside a OneDrive folder \"{new AbsolutePath(KnownFolders.SkyDrive.Path)}\". This folder is known to cause issues with Wabbajack. " +
"Please move Wabbajack outside of your OneDrive folder and then restart the app.",
"Cannot run inside OneDrive", true));
} }
MWVM = mainWindowVM; MWVM = mainWindowVM;

View File

@ -63,7 +63,7 @@ namespace Wabbajack
this.WhenAny(x => x.DownloadLocation.TargetPath), this.WhenAny(x => x.DownloadLocation.TargetPath),
resultSelector: (target, download) => (target, download)) resultSelector: (target, download) => (target, download))
.ObserveOn(RxApp.TaskpoolScheduler) .ObserveOn(RxApp.TaskpoolScheduler)
.Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download)) .Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download, Parent.ModList?.SourceModList.GameType.MetaData()))
.ObserveOnGuiThread(); .ObserveOnGuiThread();
_CanInstall = Observable.CombineLatest( _CanInstall = Observable.CombineLatest(
@ -83,7 +83,7 @@ namespace Wabbajack
{ {
if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath) if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath)
{ {
DownloadLocation.TargetPath = installPath.Combine("downloads"); if (installPath.Exists) DownloadLocation.TargetPath = installPath.Combine("downloads");
} }
}) })
.DisposeWith(CompositeDisposable); .DisposeWith(CompositeDisposable);

View File

@ -79,7 +79,7 @@ namespace Wabbajack
.DisposeWith(CompositeDisposable); .DisposeWith(CompositeDisposable);
Utils.LogMessages Utils.LogMessages
.OfType<IUserIntervention>() .Where(a => a is IUserIntervention or CriticalFailureIntervention)
.ObserveOnGuiThread() .ObserveOnGuiThread()
.SelectTask(async msg => .SelectTask(async msg =>
{ {
@ -93,9 +93,9 @@ namespace Wabbajack
Utils.Error(ex, $"Error while handling user intervention of type {msg?.GetType()}"); Utils.Error(ex, $"Error while handling user intervention of type {msg?.GetType()}");
try try
{ {
if (!msg.Handled) if (msg is IUserIntervention {Handled: false} intervention)
{ {
msg.Cancel(); intervention.Cancel();
} }
} }
catch (Exception cancelEx) catch (Exception cancelEx)

View File

@ -10,6 +10,7 @@ using System.Windows.Threading;
using CefSharp; using CefSharp;
using ReactiveUI; using ReactiveUI;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.Common.StatusFeed;
using Wabbajack.Lib; using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders; using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.LibCefHelpers; using Wabbajack.Lib.LibCefHelpers;
@ -57,12 +58,12 @@ namespace Wabbajack
MainWindow.NavigateTo(oldPane); MainWindow.NavigateTo(oldPane);
} }
public async Task Handle(IUserIntervention msg) public async Task Handle(IStatusMessage msg)
{ {
switch (msg) switch (msg)
{ {
case RequestNexusAuthorization c: case RequestNexusAuthorization c:
await WrapBrowserJob(msg, async (vm, cancel) => await WrapBrowserJob(c, async (vm, cancel) =>
{ {
await vm.Driver.WaitForInitialized(); await vm.Driver.WaitForInitialized();
var key = await NexusApiClient.SetupNexusLogin(new CefSharpWrapper(vm.Browser), m => vm.Instructions = m, cancel.Token); var key = await NexusApiClient.SetupNexusLogin(new CefSharpWrapper(vm.Browser), m => vm.Instructions = m, cancel.Token);
@ -70,13 +71,13 @@ namespace Wabbajack
}); });
break; break;
case ManuallyDownloadNexusFile c: case ManuallyDownloadNexusFile c:
await WrapBrowserJob(msg, (vm, cancel) => HandleManualNexusDownload(vm, cancel, c)); await WrapBrowserJob(c, (vm, cancel) => HandleManualNexusDownload(vm, cancel, c));
break; break;
case ManuallyDownloadFile c: case ManuallyDownloadFile c:
await WrapBrowserJob(msg, (vm, cancel) => HandleManualDownload(vm, cancel, c)); await WrapBrowserJob(c, (vm, cancel) => HandleManualDownload(vm, cancel, c));
break; break;
case AbstractNeedsLoginDownloader.RequestSiteLogin c: case AbstractNeedsLoginDownloader.RequestSiteLogin c:
await WrapBrowserJob(msg, async (vm, cancel) => await WrapBrowserJob(c, async (vm, cancel) =>
{ {
await vm.Driver.WaitForInitialized(); await vm.Driver.WaitForInitialized();
var data = await c.Downloader.GetAndCacheCookies(new CefSharpWrapper(vm.Browser), m => vm.Instructions = m, cancel.Token); var data = await c.Downloader.GetAndCacheCookies(new CefSharpWrapper(vm.Browser), m => vm.Instructions = m, cancel.Token);
@ -87,6 +88,7 @@ namespace Wabbajack
MessageBox.Show(c.ExtendedDescription, c.ShortDescription, MessageBoxButton.OK, MessageBox.Show(c.ExtendedDescription, c.ShortDescription, MessageBoxButton.OK,
MessageBoxImage.Error); MessageBoxImage.Error);
c.Cancel(); c.Cancel();
if (c.ExitApplication) await MainWindow.ShutdownApplication();
break; break;
case ConfirmationIntervention c: case ConfirmationIntervention c:
break; break;