From dd9697032c0071931eecf6b563c1774647ae33dd Mon Sep 17 00:00:00 2001 From: Shivam Date: Tue, 16 Jun 2020 17:39:20 +0200 Subject: [PATCH] Introduce new class MigratableStorage --- osu.Game.Tournament/IO/TournamentStorage.cs | 70 +++------------ osu.Game/IO/MigratableStorage.cs | 95 +++++++++++++++++++++ 2 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 osu.Game/IO/MigratableStorage.cs diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs index 611592e0e3..1731b96095 100644 --- a/osu.Game.Tournament/IO/TournamentStorage.cs +++ b/osu.Game.Tournament/IO/TournamentStorage.cs @@ -11,7 +11,7 @@ using osu.Game.Tournament.Configuration; namespace osu.Game.Tournament.IO { - public class TournamentStorage : WrappedStorage + public class TournamentStorage : MigratableStorage { private readonly Storage storage; internal readonly TournamentVideoResourceStore VideoStore; @@ -52,8 +52,15 @@ namespace osu.Game.Tournament.IO var destination = new DirectoryInfo(GetFullPath(default_tournament)); var cfgDestination = new DirectoryInfo(GetFullPath(default_tournament + Path.DirectorySeparatorChar + config_directory)); - if (!destination.Exists) - destination.Create(); + // if (!destination.Exists) + // destination.Create(); + + if (source.Exists) + { + Logger.Log("Migrating tournament assets to default tournament storage."); + copyRecursive(source, destination); + deleteRecursive(source); + } if (!cfgDestination.Exists) destination.CreateSubdirectory(config_directory); @@ -62,13 +69,6 @@ namespace osu.Game.Tournament.IO moveFileIfExists("drawings.txt", destination); moveFileIfExists("drawings_results.txt", destination); moveFileIfExists("drawings.ini", cfgDestination); - - if (source.Exists) - { - Logger.Log("Migrating tournament assets to default tournament storage."); - copyRecursive(source, destination); - deleteRecursive(source); - } } private void moveFileIfExists(string file, DirectoryInfo destination) @@ -81,55 +81,5 @@ namespace osu.Game.Tournament.IO fileInfo.Delete(); } } - - private void copyRecursive(DirectoryInfo source, DirectoryInfo destination) - { - // based off example code https://docs.microsoft.com/en-us/dotnet/api/system.io.directoryinfo - - foreach (System.IO.FileInfo fi in source.GetFiles()) - { - attemptOperation(() => fi.CopyTo(Path.Combine(destination.FullName, fi.Name), true)); - } - - foreach (DirectoryInfo dir in source.GetDirectories()) - { - copyRecursive(dir, destination.CreateSubdirectory(dir.Name)); - } - } - - private void deleteRecursive(DirectoryInfo target) - { - foreach (System.IO.FileInfo fi in target.GetFiles()) - { - attemptOperation(() => fi.Delete()); - } - - foreach (DirectoryInfo dir in target.GetDirectories()) - { - attemptOperation(() => dir.Delete(true)); - } - - if (target.GetFiles().Length == 0 && target.GetDirectories().Length == 0) - attemptOperation(target.Delete); - } - - private void attemptOperation(Action action, int attempts = 10) - { - while (true) - { - try - { - action(); - return; - } - catch (Exception) - { - if (attempts-- == 0) - throw; - } - - Thread.Sleep(250); - } - } } } diff --git a/osu.Game/IO/MigratableStorage.cs b/osu.Game/IO/MigratableStorage.cs new file mode 100644 index 0000000000..0ab0ea9934 --- /dev/null +++ b/osu.Game/IO/MigratableStorage.cs @@ -0,0 +1,95 @@ +// 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; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Configuration; + +namespace osu.Game.IO +{ + public abstract class MigratableStorage : WrappedStorage + { + + virtual protected string[] IGNORE_DIRECTORIES { get; set; } = Array.Empty(); + + virtual protected string[] IGNORE_FILES { get; set; } = Array.Empty(); + + public MigratableStorage(Storage storage, string subPath = null) + : base(storage, subPath) + { + } + + protected void deleteRecursive(DirectoryInfo target, bool topLevelExcludes = true) + { + foreach (System.IO.FileInfo fi in target.GetFiles()) + { + if (topLevelExcludes && IGNORE_FILES.Contains(fi.Name)) + continue; + + attemptOperation(() => fi.Delete()); + } + + foreach (DirectoryInfo dir in target.GetDirectories()) + { + if (topLevelExcludes && IGNORE_DIRECTORIES.Contains(dir.Name)) + continue; + + attemptOperation(() => dir.Delete(true)); + } + + if (target.GetFiles().Length == 0 && target.GetDirectories().Length == 0) + attemptOperation(target.Delete); + } + + protected void copyRecursive(DirectoryInfo source, DirectoryInfo destination, bool topLevelExcludes = true) + { + // based off example code https://docs.microsoft.com/en-us/dotnet/api/system.io.directoryinfo + if (!destination.Exists) + Directory.CreateDirectory(destination.FullName); + + foreach (System.IO.FileInfo fi in source.GetFiles()) + { + if (topLevelExcludes && IGNORE_FILES.Contains(fi.Name)) + continue; + + attemptOperation(() => fi.CopyTo(Path.Combine(destination.FullName, fi.Name), true)); + } + + foreach (DirectoryInfo dir in source.GetDirectories()) + { + if (topLevelExcludes && IGNORE_DIRECTORIES.Contains(dir.Name)) + continue; + + copyRecursive(dir, destination.CreateSubdirectory(dir.Name), false); + } + } + + /// + /// Attempt an IO operation multiple times and only throw if none of the attempts succeed. + /// + /// The action to perform. + /// The number of attempts (250ms wait between each). + protected static void attemptOperation(Action action, int attempts = 10) + { + while (true) + { + try + { + action(); + return; + } + catch (Exception) + { + if (attempts-- == 0) + throw; + } + + Thread.Sleep(250); + } + } + } +}