diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0594cd131696..2cca3ceaeb28 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -225,11 +225,6 @@ public bool IsAvailableLocally(BeatmapSetInfo model) remove => beatmapModelManager.ItemRemoved -= value; } - public Task ImportFromStableAsync(StableStorage stableStorage) - { - return beatmapModelManager.ImportFromStableAsync(stableStorage); - } - public void Export(BeatmapSetInfo item) { beatmapModelManager.Export(item); diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs index ae395c6da613..63cdd0b85233 100644 --- a/osu.Game/Beatmaps/BeatmapModelManager.cs +++ b/osu.Game/Beatmaps/BeatmapModelManager.cs @@ -58,10 +58,6 @@ public class BeatmapModelManager : ArchiveModelManager new[] { ".osu" }; - protected override string ImportFromStablePath => "."; - - protected override Storage PrepareStableStorage(StableStorage stableStorage) => stableStorage.GetSongStorage(); - private readonly BeatmapStore beatmaps; private readonly RulesetStore rulesets; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index adbb71c8daa8..e5919cb5c4ed 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -728,17 +728,6 @@ private IEnumerable<(string original, string shortened)> getShortenedFilenames(A #region osu-stable import - /// - /// The relative path from osu-stable's data directory to import items from. - /// - protected virtual string ImportFromStablePath => null; - - /// - /// Select paths to import from stable where all paths should be absolute. Default implementation iterates all directories in . - /// - protected virtual IEnumerable GetStableImportPaths(Storage storage) => storage.GetDirectories(ImportFromStablePath) - .Select(path => storage.GetFullPath(path)); - /// /// Whether this specified path should be removed after successful import. /// @@ -746,29 +735,6 @@ protected virtual IEnumerable GetStableImportPaths(Storage storage) => s /// Whether to perform deletion. protected virtual bool ShouldDeleteArchive(string path) => false; - public Task ImportFromStableAsync(StableStorage stableStorage) - { - var storage = PrepareStableStorage(stableStorage); - - // Handle situations like when the user does not have a Skins folder. - if (!storage.ExistsDirectory(ImportFromStablePath)) - { - string fullPath = storage.GetFullPath(ImportFromStablePath); - - Logger.Log(@$"Folder ""{fullPath}"" not available in the target osu!stable installation to import {HumanisedModelName}s.", LoggingTarget.Information, LogLevel.Error); - return Task.CompletedTask; - } - - return Task.Run(async () => await Import(GetStableImportPaths(storage).ToArray()).ConfigureAwait(false)); - } - - /// - /// Run any required traversal operations on the stable storage location before performing operations. - /// - /// The stable storage. - /// The usable storage. Return the unchanged if no traversal is required. - protected virtual Storage PrepareStableStorage(StableStorage stableStorage) => stableStorage; - #endregion /// diff --git a/osu.Game/Database/IModelManager.cs b/osu.Game/Database/IModelManager.cs index 15ad455f217c..6c9cca7c7a9f 100644 --- a/osu.Game/Database/IModelManager.cs +++ b/osu.Game/Database/IModelManager.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Threading.Tasks; -using osu.Game.IO; namespace osu.Game.Database { @@ -26,11 +24,6 @@ public interface IModelManager /// event Action ItemRemoved; - /// - /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. - /// - Task ImportFromStableAsync(StableStorage stableStorage); - /// /// Exports an item to a legacy (.zip based) package. /// diff --git a/osu.Game/Database/StableBeatmapImporter.cs b/osu.Game/Database/StableBeatmapImporter.cs new file mode 100644 index 000000000000..7aaa8ba01357 --- /dev/null +++ b/osu.Game/Database/StableBeatmapImporter.cs @@ -0,0 +1,18 @@ +using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.IO; + +namespace osu.Game.Database +{ + public class StableBeatmapImporter : StableImporter + { + protected override string ImportFromStablePath => "."; + + protected override Storage PrepareStableStorage(StableStorage stableStorage) => stableStorage.GetSongStorage(); + + public StableBeatmapImporter(IModelImporter importer) + : base(importer) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/Database/StableImportManager.cs b/osu.Game/Database/StableImportManager.cs index fe8c14c08527..0a30fcb2be94 100644 --- a/osu.Game/Database/StableImportManager.cs +++ b/osu.Game/Database/StableImportManager.cs @@ -51,18 +51,22 @@ public async Task ImportFromStableAsync(StableContent content) var stableStorage = await getStableStorage().ConfigureAwait(false); var importTasks = new List(); + var beatmapImporter = new StableBeatmapImporter(beatmaps); + var skinImporter = new StableSkinImporter(skins); + var scoreImporter = new StableScoreImporter(scores); + Task beatmapImportTask = Task.CompletedTask; if (content.HasFlagFast(StableContent.Beatmaps)) - importTasks.Add(beatmapImportTask = beatmaps.ImportFromStableAsync(stableStorage)); + importTasks.Add(beatmapImportTask = beatmapImporter.ImportFromStableAsync(stableStorage)); if (content.HasFlagFast(StableContent.Skins)) - importTasks.Add(skins.ImportFromStableAsync(stableStorage)); + importTasks.Add(skinImporter.ImportFromStableAsync(stableStorage)); if (content.HasFlagFast(StableContent.Collections)) importTasks.Add(beatmapImportTask.ContinueWith(_ => collections.ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion)); if (content.HasFlagFast(StableContent.Scores)) - importTasks.Add(beatmapImportTask.ContinueWith(_ => scores.ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion)); + importTasks.Add(beatmapImportTask.ContinueWith(_ => scoreImporter.ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion)); await Task.WhenAll(importTasks.ToArray()).ConfigureAwait(false); } diff --git a/osu.Game/Database/StableImporter.cs b/osu.Game/Database/StableImporter.cs new file mode 100644 index 000000000000..e56737959e5d --- /dev/null +++ b/osu.Game/Database/StableImporter.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.IO; + +namespace osu.Game.Database +{ + /// + /// A class which handled importing various user data from osu-stable. + /// + public class StableImporter + where TModel : class + { + /// + /// The relative path from osu-stable's data directory to import items from. + /// + protected virtual string ImportFromStablePath => null; + + /// + /// Select paths to import from stable where all paths should be absolute. Default implementation iterates all directories in . + /// + protected virtual IEnumerable GetStableImportPaths(Storage storage) => storage.GetDirectories(ImportFromStablePath) + .Select(path => storage.GetFullPath(path)); + + protected readonly IModelImporter Importer; + + public StableImporter(IModelImporter importer) + { + Importer = importer; + } + + public Task ImportFromStableAsync(StableStorage stableStorage) + { + var storage = PrepareStableStorage(stableStorage); + + // Handle situations like when the user does not have a Skins folder. + if (!storage.ExistsDirectory(ImportFromStablePath)) + { + string fullPath = storage.GetFullPath(ImportFromStablePath); + + Logger.Log(@$"Folder ""{fullPath}"" not available in the target osu!stable installation to import {Importer.HumanisedModelName}s.", LoggingTarget.Information, LogLevel.Error); + return Task.CompletedTask; + } + + return Task.Run(async () => await Importer.Import(GetStableImportPaths(storage).ToArray()).ConfigureAwait(false)); + } + + /// + /// Run any required traversal operations on the stable storage location before performing operations. + /// + /// The stable storage. + /// The usable storage. Return the unchanged if no traversal is required. + protected virtual Storage PrepareStableStorage(StableStorage stableStorage) => stableStorage; + } +} diff --git a/osu.Game/Database/StableScoreImporter.cs b/osu.Game/Database/StableScoreImporter.cs new file mode 100644 index 000000000000..fede10c7ea52 --- /dev/null +++ b/osu.Game/Database/StableScoreImporter.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using osu.Framework.Platform; +using osu.Game.Scoring; + +namespace osu.Game.Database +{ + public class StableScoreImporter : StableImporter + { + protected override string ImportFromStablePath => Path.Combine("Data", "r"); + + protected override IEnumerable GetStableImportPaths(Storage storage) + => storage.GetFiles(ImportFromStablePath).Where(p => Importer.HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.OrdinalIgnoreCase) ?? false)) + .Select(path => storage.GetFullPath(path)); + + public StableScoreImporter(IModelImporter importer) + : base(importer) + { + } + } +} diff --git a/osu.Game/Database/StableSkinImporter.cs b/osu.Game/Database/StableSkinImporter.cs new file mode 100644 index 000000000000..65601e85b7cf --- /dev/null +++ b/osu.Game/Database/StableSkinImporter.cs @@ -0,0 +1,14 @@ +using osu.Game.Skinning; + +namespace osu.Game.Database +{ + public class StableSkinImporter : StableImporter + { + protected override string ImportFromStablePath => "Skins"; + + public StableSkinImporter(IModelImporter importer) + : base(importer) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs index 29144e7bdc1f..d25671d77e42 100644 --- a/osu.Game/Scoring/ScoreManager.cs +++ b/osu.Game/Scoring/ScoreManager.cs @@ -15,7 +15,6 @@ using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.IO; using osu.Game.IO.Archives; using osu.Game.Online.API; using osu.Game.Overlays.Notifications; @@ -263,11 +262,6 @@ public Action PostNotification remove => scoreModelManager.ItemRemoved -= value; } - public Task ImportFromStableAsync(StableStorage stableStorage) - { - return scoreModelManager.ImportFromStableAsync(stableStorage); - } - public void Export(ScoreInfo item) { scoreModelManager.Export(item); diff --git a/osu.Game/Scoring/ScoreModelManager.cs b/osu.Game/Scoring/ScoreModelManager.cs index c194a7166df5..9da739237bbd 100644 --- a/osu.Game/Scoring/ScoreModelManager.cs +++ b/osu.Game/Scoring/ScoreModelManager.cs @@ -26,8 +26,6 @@ public class ScoreModelManager : ArchiveModelManager protected override string[] HashableFileTypes => new[] { ".osr" }; - protected override string ImportFromStablePath => Path.Combine("Data", "r"); - private readonly RulesetStore rulesets; private readonly Func beatmaps; @@ -81,9 +79,5 @@ public override void ExportModelTo(ScoreInfo model, Stream outputStream) using (var inputStream = Files.Storage.GetStream(file.FileInfo.GetStoragePath())) inputStream.CopyTo(outputStream); } - - protected override IEnumerable GetStableImportPaths(Storage storage) - => storage.GetFiles(ImportFromStablePath).Where(p => HandledExtensions.Any(ext => Path.GetExtension(p)?.Equals(ext, StringComparison.OrdinalIgnoreCase) ?? false)) - .Select(path => storage.GetFullPath(path)); } } diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index a840e17ed1d3..679b35799ebb 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -301,11 +301,6 @@ public Task> Import(SkinInfo item, ArchiveReader archive = null, remove => skinModelManager.ItemRemoved -= value; } - public Task ImportFromStableAsync(StableStorage stableStorage) - { - return skinModelManager.ImportFromStableAsync(stableStorage); - } - public void Export(SkinInfo item) { skinModelManager.Export(item); diff --git a/osu.Game/Skinning/SkinModelManager.cs b/osu.Game/Skinning/SkinModelManager.cs index f28b0c066bb4..572ae5cbfc62 100644 --- a/osu.Game/Skinning/SkinModelManager.cs +++ b/osu.Game/Skinning/SkinModelManager.cs @@ -34,8 +34,6 @@ public SkinModelManager(Storage storage, DatabaseContextFactory contextFactory, protected override string[] HashableFileTypes => new[] { ".ini", ".json" }; - protected override string ImportFromStablePath => "Skins"; - protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == @".osk"; protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name ?? @"No name" };