osu/osu.Game/IO/OsuStorage.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

163 lines
5.4 KiB
C#
Raw Permalink Normal View History

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2020-07-06 13:03:09 +00:00
using System.Diagnostics;
2020-05-07 10:00:59 +00:00
using System.Linq;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Configuration;
namespace osu.Game.IO
{
public class OsuStorage : MigratableStorage
{
2020-07-06 13:03:09 +00:00
/// <summary>
/// Indicates the error (if any) that occurred when initialising the custom storage during initial startup.
/// </summary>
public readonly OsuStorageError Error;
/// <summary>
/// The custom storage path as selected by the user.
/// </summary>
public string? CustomStoragePath => storageConfig.Get<string>(StorageConfig.FullPath);
2020-07-06 13:03:09 +00:00
/// <summary>
/// The default storage path to be used if a custom storage path hasn't been selected or is not accessible.
/// </summary>
public string DefaultStoragePath => defaultStorage.GetFullPath(".");
private readonly GameHost host;
private readonly StorageConfigManager storageConfig;
2020-07-06 13:03:09 +00:00
private readonly Storage defaultStorage;
public override string[] IgnoreDirectories => new[]
{
"cache",
};
public override string[] IgnoreFiles => new[]
{
2020-06-23 22:37:29 +00:00
"framework.ini",
"storage.ini",
};
public override string[] IgnoreSuffixes => new[]
{
// Realm pipe files don't play well with copy operations
".note",
".lock",
".management",
2020-06-23 22:37:29 +00:00
};
public OsuStorage(GameHost host, Storage defaultStorage)
: base(defaultStorage, string.Empty)
{
this.host = host;
2020-07-06 13:03:09 +00:00
this.defaultStorage = defaultStorage;
storageConfig = new StorageConfigManager(defaultStorage);
2020-07-06 13:03:09 +00:00
if (!string.IsNullOrEmpty(CustomStoragePath))
TryChangeToCustomStorage(out Error);
}
/// <summary>
/// Resets the custom storage path, changing the target storage to the default location.
/// </summary>
public void ResetCustomStoragePath()
{
ChangeDataPath(string.Empty);
2020-07-06 13:03:09 +00:00
ChangeTargetStorage(defaultStorage);
}
/// <summary>
/// Updates the target data path without immediately switching.
/// This does NOT migrate any data.
/// The game should immediately be restarted after calling this.
/// </summary>
public void ChangeDataPath(string newPath)
{
storageConfig.SetValue(StorageConfig.FullPath, newPath);
storageConfig.Save();
}
2020-07-06 13:03:09 +00:00
/// <summary>
/// Attempts to change to the user's custom storage path.
/// </summary>
/// <param name="error">The error that occurred.</param>
/// <returns>Whether the custom storage path was used successfully. If not, <paramref name="error"/> will be populated with the reason.</returns>
public bool TryChangeToCustomStorage(out OsuStorageError error)
{
Debug.Assert(!string.IsNullOrEmpty(CustomStoragePath));
error = OsuStorageError.None;
Storage lastStorage = UnderlyingStorage;
Logger.Log($"Attempting to use custom storage location {CustomStoragePath}");
2020-07-06 13:03:09 +00:00
try
{
2020-07-06 13:03:09 +00:00
Storage userStorage = host.GetStorage(CustomStoragePath);
2020-07-06 13:41:58 +00:00
if (!userStorage.ExistsDirectory(".") || !userStorage.GetFiles(".").Any())
2020-07-06 13:03:09 +00:00
error = OsuStorageError.AccessibleButEmpty;
ChangeTargetStorage(userStorage);
Logger.Log($"Storage successfully changed to {CustomStoragePath}.");
2020-07-06 13:03:09 +00:00
}
catch
{
error = OsuStorageError.NotAccessible;
ChangeTargetStorage(lastStorage);
}
2020-07-06 13:03:09 +00:00
if (error != OsuStorageError.None)
Logger.Log($"Custom storage location could not be used ({error}).");
2020-07-06 13:03:09 +00:00
return error == OsuStorageError.None;
}
protected override void ChangeTargetStorage(Storage newStorage)
{
var lastStorage = UnderlyingStorage;
base.ChangeTargetStorage(newStorage);
if (lastStorage != null)
{
// for now we assume that if there was a previous storage, this is a migration operation.
// the logger shouldn't be set during initialisation as it can cause cross-talk in tests (due to being static).
Logger.Storage = UnderlyingStorage.GetStorageForDirectory("logs");
}
}
public override bool Migrate(Storage newStorage)
{
bool cleanupSucceeded = base.Migrate(newStorage);
ChangeDataPath(newStorage.GetFullPath("."));
return cleanupSucceeded;
2020-05-07 10:00:59 +00:00
}
}
2020-07-06 13:03:09 +00:00
public enum OsuStorageError
{
/// <summary>
/// No error.
/// </summary>
None,
/// <summary>
/// Occurs when the target storage directory is accessible but does not already contain game files.
/// Only happens when the user changes the storage directory and then moves the files manually or mounts a different device to the same path.
/// </summary>
AccessibleButEmpty,
/// <summary>
/// Occurs when the target storage directory cannot be accessed at all.
/// </summary>
NotAccessible,
}
}