diff --git a/osu.Game/IO/MigratableStorage.cs b/osu.Game/IO/MigratableStorage.cs
index 14a3c5a43c..d03d259f71 100644
--- a/osu.Game/IO/MigratableStorage.cs
+++ b/osu.Game/IO/MigratableStorage.cs
@@ -6,8 +6,8 @@
using System;
using System.IO;
using System.Linq;
-using System.Threading;
using osu.Framework.Platform;
+using osu.Game.Utils;
namespace osu.Game.IO
{
@@ -81,7 +81,7 @@ namespace osu.Game.IO
if (IgnoreSuffixes.Any(suffix => fi.Name.EndsWith(suffix, StringComparison.Ordinal)))
continue;
- allFilesDeleted &= AttemptOperation(() => fi.Delete(), throwOnFailure: false);
+ allFilesDeleted &= FileUtils.AttemptOperation(() => fi.Delete(), throwOnFailure: false);
}
foreach (DirectoryInfo dir in target.GetDirectories())
@@ -92,11 +92,11 @@ namespace osu.Game.IO
if (IgnoreSuffixes.Any(suffix => dir.Name.EndsWith(suffix, StringComparison.Ordinal)))
continue;
- allFilesDeleted &= AttemptOperation(() => dir.Delete(true), throwOnFailure: false);
+ allFilesDeleted &= FileUtils.AttemptOperation(() => dir.Delete(true), throwOnFailure: false);
}
if (target.GetFiles().Length == 0 && target.GetDirectories().Length == 0)
- allFilesDeleted &= AttemptOperation(target.Delete, throwOnFailure: false);
+ allFilesDeleted &= FileUtils.AttemptOperation(target.Delete, throwOnFailure: false);
return allFilesDeleted;
}
@@ -115,7 +115,7 @@ namespace osu.Game.IO
if (IgnoreSuffixes.Any(suffix => fileInfo.Name.EndsWith(suffix, StringComparison.Ordinal)))
continue;
- AttemptOperation(() =>
+ FileUtils.AttemptOperation(() =>
{
fileInfo.Refresh();
@@ -139,35 +139,5 @@ namespace osu.Game.IO
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).
- /// Whether to throw an exception on failure. If false, will silently fail.
- protected static bool AttemptOperation(Action action, int attempts = 10, bool throwOnFailure = true)
- {
- while (true)
- {
- try
- {
- action();
- return true;
- }
- catch (Exception)
- {
- if (attempts-- == 0)
- {
- if (throwOnFailure)
- throw;
-
- return false;
- }
- }
-
- Thread.Sleep(250);
- }
- }
}
}
diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
index 3ff5556f4d..fe88413e6a 100644
--- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
@@ -15,6 +15,7 @@ using osu.Game.Localisation;
using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.Settings.Sections.Maintenance;
using osu.Game.Updater;
+using osu.Game.Utils;
using SharpCompress.Archives.Zip;
namespace osu.Game.Overlays.Settings.Sections.General
@@ -111,7 +112,8 @@ namespace osu.Game.Overlays.Settings.Sections.General
using (var outStream = storage.CreateFileSafely(archive_filename))
using (var zip = ZipArchive.Create())
{
- foreach (string? f in logStorage.GetFiles(string.Empty, "*.log")) zip.AddEntry(f, logStorage.GetStream(f), true);
+ foreach (string? f in logStorage.GetFiles(string.Empty, "*.log"))
+ FileUtils.AttemptOperation(z => z.AddEntry(f, logStorage.GetStream(f), true), zip);
zip.SaveTo(outStream);
}
diff --git a/osu.Game/Utils/FileUtils.cs b/osu.Game/Utils/FileUtils.cs
new file mode 100644
index 0000000000..063ab178f7
--- /dev/null
+++ b/osu.Game/Utils/FileUtils.cs
@@ -0,0 +1,72 @@
+// 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.Threading;
+
+namespace osu.Game.Utils
+{
+ public static class FileUtils
+ {
+ ///
+ /// Attempt an IO operation multiple times and only throw if none of the attempts succeed.
+ ///
+ /// The action to perform.
+ /// The provided state.
+ /// The number of attempts (250ms wait between each).
+ /// Whether to throw an exception on failure. If false, will silently fail.
+ public static bool AttemptOperation(Action action, T state, int attempts = 10, bool throwOnFailure = true)
+ {
+ while (true)
+ {
+ try
+ {
+ action(state);
+ return true;
+ }
+ catch (Exception)
+ {
+ if (attempts-- == 0)
+ {
+ if (throwOnFailure)
+ throw;
+
+ return false;
+ }
+ }
+
+ Thread.Sleep(250);
+ }
+ }
+
+ ///
+ /// 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).
+ /// Whether to throw an exception on failure. If false, will silently fail.
+ public static bool AttemptOperation(Action action, int attempts = 10, bool throwOnFailure = true)
+ {
+ while (true)
+ {
+ try
+ {
+ action();
+ return true;
+ }
+ catch (Exception)
+ {
+ if (attempts-- == 0)
+ {
+ if (throwOnFailure)
+ throw;
+
+ return false;
+ }
+ }
+
+ Thread.Sleep(250);
+ }
+ }
+ }
+}