diff --git a/osu.Game/Database/LegacyImportManager.cs b/osu.Game/Database/LegacyImportManager.cs index 20738f859e..7e1641d16f 100644 --- a/osu.Game/Database/LegacyImportManager.cs +++ b/osu.Game/Database/LegacyImportManager.cs @@ -3,6 +3,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework; @@ -54,6 +57,49 @@ namespace osu.Game.Database public void UpdateStorage(string stablePath) => cachedStorage = new StableStorage(stablePath, gameHost as DesktopGameHost); + /// + /// Checks whether a valid location to run a stable import from can be determined starting from the supplied . + /// + /// The directory to check for stable import eligibility. + /// + /// If the return value is , + /// this parameter will contain the to use as the root directory for importing. + /// + public bool IsUsableForStableImport(DirectoryInfo? directory, [NotNullWhen(true)] out DirectoryInfo? stableRoot) + { + if (directory == null) + { + stableRoot = null; + return false; + } + + // A full stable installation will have a configuration file present. + // This is the best case scenario, as it may contain a custom beatmap directory we need to traverse to. + if (directory.GetFiles(@"osu!.*.cfg").Any()) + { + stableRoot = directory; + return true; + } + + // The user may only have their songs or skins folders left. + // We still want to allow them to import based on this. + if (directory.GetDirectories(@"Songs").Any() || directory.GetDirectories(@"Skins").Any()) + { + stableRoot = directory; + return true; + } + + // The user may have traversed *inside* their songs or skins folders. + if (directory.Parent != null && (directory.Name == @"Songs" || directory.Name == @"Skins")) + { + stableRoot = directory.Parent; + return true; + } + + stableRoot = null; + return false; + } + public bool CheckSongsFolderHardLinkAvailability() { var stableStorage = GetCurrentStableStorage(); diff --git a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs index 23f3b3e1af..185a47c371 100644 --- a/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs +++ b/osu.Game/Overlays/FirstRunSetup/ScreenImportFromStable.cs @@ -269,11 +269,11 @@ namespace osu.Game.Overlays.FirstRunSetup if (directory.OldValue?.FullName == directory.NewValue.FullName) return; - if (directory.NewValue?.GetFiles(@"osu!.*.cfg").Any() ?? false) + if (legacyImportManager.IsUsableForStableImport(directory.NewValue, out var stableRoot)) { this.HidePopover(); - string path = directory.NewValue.FullName; + string path = stableRoot.FullName; legacyImportManager.UpdateStorage(path); Current.Value = path; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs index 17f09ade4e..3f12b9c0df 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/StableDirectorySelectScreen.cs @@ -1,11 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.IO; -using System.Linq; using System.Threading.Tasks; +using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Screens; +using osu.Game.Database; namespace osu.Game.Overlays.Settings.Sections.Maintenance { @@ -13,18 +15,12 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance { private readonly TaskCompletionSource taskCompletionSource; + [Resolved] + private LegacyImportManager legacyImportManager { get; set; } = null!; + protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; - protected override bool IsValidDirectory(DirectoryInfo? info) => - // A full stable installation will have a configuration file present. - // This is the best case scenario, as it may contain a custom beatmap directory we need to traverse to. - info?.GetFiles("osu!.*.cfg").Any() == true || - // The user may only have their songs or skins folders left. - // We still want to allow them to import based on this. - info?.GetDirectories("Songs").Any() == true || - info?.GetDirectories("Skins").Any() == true || - // The user may have traverse *inside* their songs or skins folders. - shouldUseParentDirectory(info); + protected override bool IsValidDirectory(DirectoryInfo? info) => legacyImportManager.IsUsableForStableImport(info, out _); public override LocalisableString HeaderText => "Please select your osu!stable install location"; @@ -35,7 +31,10 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance protected override void OnSelection(DirectoryInfo directory) { - taskCompletionSource.TrySetResult(shouldUseParentDirectory(directory) ? directory.Parent!.FullName : directory.FullName); + if (!legacyImportManager.IsUsableForStableImport(directory, out var stableRoot)) + throw new InvalidOperationException($@"{nameof(OnSelection)} was called on an invalid directory. This should never happen."); + + taskCompletionSource.TrySetResult(stableRoot.FullName); this.Exit(); } @@ -44,8 +43,5 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance taskCompletionSource.TrySetCanceled(); return base.OnExiting(e); } - - private bool shouldUseParentDirectory(DirectoryInfo? info) - => info?.Parent != null && (info.Name == "Songs" || info.Name == "Skins"); } }