mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:20:04 +08:00
Merge pull request #14903 from peppy/importer-returns-live
Add `ILive<T>` and use as return type of `Import` methods
This commit is contained in:
commit
4bd1083388
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||
|
||||
BeatmapSetInfo importedSet;
|
||||
ILive<BeatmapSetInfo> importedSet;
|
||||
|
||||
using (var stream = File.OpenRead(tempPath))
|
||||
{
|
||||
@ -97,7 +97,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
Assert.IsTrue(File.Exists(tempPath), "Stream source file somehow went missing");
|
||||
File.Delete(tempPath);
|
||||
|
||||
var imported = manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
||||
var imported = manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||
|
||||
deleteBeatmapSet(imported, osu);
|
||||
}
|
||||
@ -172,8 +172,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
ensureLoaded(osu);
|
||||
|
||||
// but contents doesn't, so existing should still be used.
|
||||
Assert.IsTrue(imported.ID == importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
|
||||
Assert.IsTrue(imported.ID == importedSecondTime.Value.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Value.Beatmaps.First().ID);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -226,8 +226,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
ensureLoaded(osu);
|
||||
|
||||
// check the newly "imported" beatmap is not the original.
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -278,8 +278,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
ensureLoaded(osu);
|
||||
|
||||
// check the newly "imported" beatmap is not the original.
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -329,8 +329,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
ensureLoaded(osu);
|
||||
|
||||
// check the newly "imported" beatmap is not the original.
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
||||
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -570,8 +570,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
var imported = await manager.Import(toImport);
|
||||
|
||||
Assert.NotNull(imported);
|
||||
Assert.AreEqual(null, imported.Beatmaps[0].OnlineBeatmapID);
|
||||
Assert.AreEqual(null, imported.Beatmaps[1].OnlineBeatmapID);
|
||||
Assert.AreEqual(null, imported.Value.Beatmaps[0].OnlineBeatmapID);
|
||||
Assert.AreEqual(null, imported.Value.Beatmaps[1].OnlineBeatmapID);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -706,7 +706,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
ensureLoaded(osu);
|
||||
|
||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder");
|
||||
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -759,8 +759,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
ensureLoaded(osu);
|
||||
|
||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("__MACOSX")), "Files contain resource fork folder, which should be ignored");
|
||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("actual_data")), "Files contain common subfolder");
|
||||
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("__MACOSX")), "Files contain resource fork folder, which should be ignored");
|
||||
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("actual_data")), "Files contain common subfolder");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -915,7 +915,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||
|
||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||
}
|
||||
|
||||
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
|
||||
@ -930,7 +930,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||
|
||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||
}
|
||||
|
||||
private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu)
|
||||
|
@ -156,7 +156,7 @@ namespace osu.Game.Tests.Online
|
||||
{
|
||||
public TaskCompletionSource<bool> AllowImport = new TaskCompletionSource<bool>();
|
||||
|
||||
public Task<BeatmapSetInfo> CurrentImportTask { get; private set; }
|
||||
public Task<ILive<BeatmapSetInfo>> CurrentImportTask { get; private set; }
|
||||
|
||||
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
||||
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
||||
@ -194,7 +194,7 @@ namespace osu.Game.Tests.Online
|
||||
this.testBeatmapManager = testBeatmapManager;
|
||||
}
|
||||
|
||||
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public override async Task<ILive<BeatmapSetInfo>> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await testBeatmapManager.AllowImport.Task.ConfigureAwait(false);
|
||||
return await (testBeatmapManager.CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
|
||||
|
@ -196,7 +196,7 @@ namespace osu.Game.Tests.Skins.IO
|
||||
private async Task<SkinInfo> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null)
|
||||
{
|
||||
var skinManager = osu.Dependencies.Get<SkinManager>();
|
||||
return await skinManager.Import(archive);
|
||||
return (await skinManager.Import(archive)).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Skins
|
||||
private void load()
|
||||
{
|
||||
var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).Result;
|
||||
beatmap = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]);
|
||||
beatmap = beatmaps.GetWorkingBeatmap(imported.Value.Beatmaps[0]);
|
||||
beatmap.LoadTrack();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Skins
|
||||
private void load()
|
||||
{
|
||||
var imported = skins.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-skin.osk"))).Result;
|
||||
skin = skins.GetSkin(imported);
|
||||
skin = skins.GetSkin(imported.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Menus
|
||||
AddStep("import beatmap with track", () =>
|
||||
{
|
||||
var setWithTrack = Game.BeatmapManager.Import(new ImportTask(TestResources.GetTestBeatmapForImport())).Result;
|
||||
Beatmap.Value = Game.BeatmapManager.GetWorkingBeatmap(setWithTrack.Beatmaps.First());
|
||||
Beatmap.Value = Game.BeatmapManager.GetWorkingBeatmap(setWithTrack.Value.Beatmaps.First());
|
||||
});
|
||||
|
||||
AddStep("bind to track change", () =>
|
||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
|
||||
},
|
||||
}
|
||||
}).Result;
|
||||
}).Result.Value;
|
||||
});
|
||||
|
||||
AddAssert($"import {i} succeeded", () => imported != null);
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
}
|
||||
}).Result;
|
||||
}).Result.Value;
|
||||
});
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
OnlineScoreID = i,
|
||||
BeatmapInfo = beatmap.Beatmaps.First(),
|
||||
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
|
||||
}).Result;
|
||||
}).Result.Value;
|
||||
});
|
||||
|
||||
AddAssert($"import {i} succeeded", () => imported != null);
|
||||
|
@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
||||
{
|
||||
beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 1;
|
||||
|
||||
importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result;
|
||||
importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result.Value;
|
||||
});
|
||||
|
||||
AddStep("load room", () =>
|
||||
|
@ -192,7 +192,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return Game.BeatmapManager.Import(beatmapSet).Result;
|
||||
return Game.BeatmapManager.Import(beatmapSet).Result.Value;
|
||||
}
|
||||
|
||||
private bool ensureAllBeatmapSetsImported(IEnumerable<BeatmapSetInfo> beatmapSets) => beatmapSets.All(set => set != null);
|
||||
|
@ -751,7 +751,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddStep("import huge difficulty count map", () =>
|
||||
{
|
||||
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
|
||||
imported = manager.Import(createTestBeatmapSet(usableRulesets, 50)).Result;
|
||||
imported = manager.Import(createTestBeatmapSet(usableRulesets, 50)).Result.Value;
|
||||
});
|
||||
|
||||
AddStep("select the first beatmap of import", () => Beatmap.Value = manager.GetWorkingBeatmap(imported.Beatmaps.First()));
|
||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, ContextFactory, rulesetStore, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
|
||||
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, null, ContextFactory, Scheduler));
|
||||
|
||||
beatmapInfo = beatmapManager.Import(new ImportTask(TestResources.GetQuickTestBeatmapForImport())).Result.Beatmaps[0];
|
||||
beatmapInfo = beatmapManager.Import(new ImportTask(TestResources.GetQuickTestBeatmapForImport())).Result.Value.Beatmaps[0];
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
User = new User { Username = "TestUser" },
|
||||
};
|
||||
|
||||
importedScores.Add(scoreManager.Import(score).Result);
|
||||
importedScores.Add(scoreManager.Import(score).Result.Value);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
|
@ -90,8 +90,9 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
};
|
||||
|
||||
var working = beatmapModelManager.Import(set).Result;
|
||||
return GetWorkingBeatmap(working.Beatmaps.First());
|
||||
var imported = beatmapModelManager.Import(set).Result.Value;
|
||||
|
||||
return GetWorkingBeatmap(imported.Beatmaps.First());
|
||||
}
|
||||
|
||||
#region Delegation to BeatmapModelManager (methods which previously existed locally).
|
||||
@ -177,7 +178,7 @@ namespace osu.Game.Beatmaps
|
||||
/// <summary>
|
||||
/// Fired when the user requests to view the resulting import.
|
||||
/// </summary>
|
||||
public Action<IEnumerable<BeatmapSetInfo>> PresentImport { set => beatmapModelManager.PresentImport = value; }
|
||||
public Action<IEnumerable<ILive<BeatmapSetInfo>>> PresentImport { set => beatmapModelManager.PostImport = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Delete a beatmap difficulty.
|
||||
@ -276,22 +277,22 @@ namespace osu.Game.Beatmaps
|
||||
return beatmapModelManager.Import(tasks);
|
||||
}
|
||||
|
||||
public Task<IEnumerable<BeatmapSetInfo>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
public Task<IEnumerable<ILive<BeatmapSetInfo>>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
{
|
||||
return beatmapModelManager.Import(notification, tasks);
|
||||
}
|
||||
|
||||
public Task<BeatmapSetInfo> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<BeatmapSetInfo>> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return beatmapModelManager.Import(task, lowPriority, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<BeatmapSetInfo> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<BeatmapSetInfo>> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return beatmapModelManager.Import(archive, lowPriority, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<BeatmapSetInfo>> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return beatmapModelManager.Import(item, archive, lowPriority, cancellationToken);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Database
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The model type.</typeparam>
|
||||
/// <typeparam name="TFileModel">The associated file join type.</typeparam>
|
||||
public abstract class ArchiveModelManager<TModel, TFileModel> : ICanAcceptFiles, IModelManager<TModel>, IModelFileManager<TModel, TFileModel>, IPresentImports<TModel>
|
||||
public abstract class ArchiveModelManager<TModel, TFileModel> : ICanAcceptFiles, IModelManager<TModel>, IModelFileManager<TModel, TFileModel>, IPostImports<TModel>
|
||||
where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete
|
||||
where TFileModel : class, INamedFileInfo, new()
|
||||
{
|
||||
@ -132,13 +132,13 @@ namespace osu.Game.Database
|
||||
return Import(notification, tasks);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TModel>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
public async Task<IEnumerable<ILive<TModel>>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
{
|
||||
if (tasks.Length == 0)
|
||||
{
|
||||
notification.CompletionText = $"No {HumanisedModelName}s were found to import!";
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
return Enumerable.Empty<TModel>();
|
||||
return Enumerable.Empty<ILive<TModel>>();
|
||||
}
|
||||
|
||||
notification.Progress = 0;
|
||||
@ -146,7 +146,7 @@ namespace osu.Game.Database
|
||||
|
||||
int current = 0;
|
||||
|
||||
var imported = new List<TModel>();
|
||||
var imported = new List<ILive<TModel>>();
|
||||
|
||||
bool isLowPriorityImport = tasks.Length > low_priority_import_batch_size;
|
||||
|
||||
@ -200,12 +200,12 @@ namespace osu.Game.Database
|
||||
? $"Imported {imported.First()}!"
|
||||
: $"Imported {imported.Count} {HumanisedModelName}s!";
|
||||
|
||||
if (imported.Count > 0 && PresentImport != null)
|
||||
if (imported.Count > 0 && PostImport != null)
|
||||
{
|
||||
notification.CompletionText += " Click to view.";
|
||||
notification.CompletionClickAction = () =>
|
||||
{
|
||||
PresentImport?.Invoke(imported);
|
||||
PostImport?.Invoke(imported);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@ -224,11 +224,11 @@ namespace osu.Game.Database
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
/// <returns>The imported model, if successful.</returns>
|
||||
public async Task<TModel> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public async Task<ILive<TModel>> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
TModel import;
|
||||
ILive<TModel> import;
|
||||
using (ArchiveReader reader = task.GetReader())
|
||||
import = await Import(reader, lowPriority, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@ -243,13 +243,13 @@ namespace osu.Game.Database
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogForModel(import, $@"Could not delete original file after import ({task})", e);
|
||||
LogForModel(import?.Value, $@"Could not delete original file after import ({task})", e);
|
||||
}
|
||||
|
||||
return import;
|
||||
}
|
||||
|
||||
public Action<IEnumerable<TModel>> PresentImport { protected get; set; }
|
||||
public Action<IEnumerable<ILive<TModel>>> PostImport { protected get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Silently import an item from an <see cref="ArchiveReader"/>.
|
||||
@ -257,7 +257,7 @@ namespace osu.Game.Database
|
||||
/// <param name="archive">The archive to be imported.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
public Task<TModel> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<TModel>> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@ -268,7 +268,7 @@ namespace osu.Game.Database
|
||||
model = CreateModel(archive);
|
||||
|
||||
if (model == null)
|
||||
return Task.FromResult<TModel>(null);
|
||||
return Task.FromResult<ILive<TModel>>(new EntityFrameworkLive<TModel>(null));
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
@ -343,7 +343,7 @@ namespace osu.Game.Database
|
||||
/// <param name="archive">An optional archive to use for model population.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
public virtual async Task<TModel> Import(TModel item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () =>
|
||||
public virtual async Task<ILive<TModel>> Import(TModel item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default) => await Task.Factory.StartNew(async () =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@ -369,7 +369,7 @@ namespace osu.Game.Database
|
||||
{
|
||||
LogForModel(item, @$"Found existing (optimised) {HumanisedModelName} for {item} (ID {existing.ID}) – skipping import.");
|
||||
Undelete(existing);
|
||||
return existing;
|
||||
return existing.ToEntityFrameworkLive();
|
||||
}
|
||||
|
||||
LogForModel(item, @"Found existing (optimised) but failed pre-check.");
|
||||
@ -415,7 +415,7 @@ namespace osu.Game.Database
|
||||
// existing item will be used; rollback new import and exit early.
|
||||
rollback();
|
||||
flushEvents(true);
|
||||
return existing;
|
||||
return existing.ToEntityFrameworkLive();
|
||||
}
|
||||
|
||||
LogForModel(item, @"Found existing but failed re-use check.");
|
||||
@ -448,7 +448,7 @@ namespace osu.Game.Database
|
||||
}
|
||||
|
||||
flushEvents(true);
|
||||
return item;
|
||||
return item.ToEntityFrameworkLive();
|
||||
}, cancellationToken, TaskCreationOptions.HideScheduler, lowPriority ? import_scheduler_low_priority : import_scheduler).Unwrap().ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
|
34
osu.Game/Database/EntityFrameworkLive.cs
Normal file
34
osu.Game/Database/EntityFrameworkLive.cs
Normal file
@ -0,0 +1,34 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class EntityFrameworkLive<T> : ILive<T> where T : class
|
||||
{
|
||||
public EntityFrameworkLive(T item)
|
||||
{
|
||||
Value = item;
|
||||
}
|
||||
|
||||
public Guid ID => throw new InvalidOperationException();
|
||||
|
||||
public void PerformRead(Action<T> perform)
|
||||
{
|
||||
perform(Value);
|
||||
}
|
||||
|
||||
public TReturn PerformRead<TReturn>(Func<T, TReturn> perform)
|
||||
{
|
||||
return perform(Value);
|
||||
}
|
||||
|
||||
public void PerformWrite(Action<T> perform)
|
||||
{
|
||||
perform(Value);
|
||||
}
|
||||
|
||||
public T Value { get; }
|
||||
}
|
||||
}
|
14
osu.Game/Database/EntityFrameworkLiveExtensions.cs
Normal file
14
osu.Game/Database/EntityFrameworkLiveExtensions.cs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public static class EntityFrameworkLiveExtensions
|
||||
{
|
||||
public static ILive<T> ToEntityFrameworkLive<T>(this T item)
|
||||
where T : class
|
||||
{
|
||||
return new EntityFrameworkLive<T>(item);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,6 @@ namespace osu.Game.Database
|
||||
{
|
||||
[JsonIgnore]
|
||||
[PrimaryKey]
|
||||
Guid ID { get; set; }
|
||||
Guid ID { get; }
|
||||
}
|
||||
}
|
||||
|
42
osu.Game/Database/ILive.cs
Normal file
42
osu.Game/Database/ILive.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// A wrapper to provide access to database backed classes in a thread-safe manner.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The databased type.</typeparam>
|
||||
public interface ILive<out T> where T : class // TODO: Add IHasGuidPrimaryKey once we don't need EF support any more.
|
||||
{
|
||||
Guid ID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Perform a read operation on this live object.
|
||||
/// </summary>
|
||||
/// <param name="perform">The action to perform.</param>
|
||||
void PerformRead(Action<T> perform);
|
||||
|
||||
/// <summary>
|
||||
/// Perform a read operation on this live object.
|
||||
/// </summary>
|
||||
/// <param name="perform">The action to perform.</param>
|
||||
TReturn PerformRead<TReturn>(Func<T, TReturn> perform);
|
||||
|
||||
/// <summary>
|
||||
/// Perform a write operation on this live object.
|
||||
/// </summary>
|
||||
/// <param name="perform">The action to perform.</param>
|
||||
void PerformWrite(Action<T> perform);
|
||||
|
||||
/// <summary>
|
||||
/// Resolve the value of this instance on the current thread's context.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// After resolving the data should not be passed between threads.
|
||||
/// </remarks>
|
||||
T Value { get; }
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ namespace osu.Game.Database
|
||||
|
||||
Task Import(params ImportTask[] tasks);
|
||||
|
||||
Task<IEnumerable<TModel>> Import(ProgressNotification notification, params ImportTask[] tasks);
|
||||
Task<IEnumerable<ILive<TModel>>> Import(ProgressNotification notification, params ImportTask[] tasks);
|
||||
|
||||
/// <summary>
|
||||
/// Import one <typeparamref name="TModel"/> from the filesystem and delete the file on success.
|
||||
@ -38,7 +38,7 @@ namespace osu.Game.Database
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
/// <returns>The imported model, if successful.</returns>
|
||||
Task<TModel> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
Task<ILive<TModel>> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Silently import an item from an <see cref="ArchiveReader"/>.
|
||||
@ -46,7 +46,7 @@ namespace osu.Game.Database
|
||||
/// <param name="archive">The archive to be imported.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
Task<TModel> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
Task<ILive<TModel>> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Silently import an item from a <typeparamref name="TModel"/>.
|
||||
@ -55,7 +55,7 @@ namespace osu.Game.Database
|
||||
/// <param name="archive">An optional archive to use for model population.</param>
|
||||
/// <param name="lowPriority">Whether this is a low priority import.</param>
|
||||
/// <param name="cancellationToken">An optional cancellation token.</param>
|
||||
Task<TModel> Import(TModel item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
Task<ILive<TModel>> Import(TModel item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// A user displayable name for the model type associated with this manager.
|
||||
|
@ -6,12 +6,12 @@ using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public interface IPresentImports<TModel>
|
||||
public interface IPostImports<out TModel>
|
||||
where TModel : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Fired when the user requests to view the resulting import.
|
||||
/// </summary>
|
||||
public Action<IEnumerable<TModel>> PresentImport { set; }
|
||||
public Action<IEnumerable<ILive<TModel>>> PostImport { set; }
|
||||
}
|
||||
}
|
@ -624,10 +624,10 @@ namespace osu.Game
|
||||
SkinManager.PostNotification = n => Notifications.Post(n);
|
||||
|
||||
BeatmapManager.PostNotification = n => Notifications.Post(n);
|
||||
BeatmapManager.PresentImport = items => PresentBeatmap(items.First());
|
||||
BeatmapManager.PresentImport = items => PresentBeatmap(items.First().Value);
|
||||
|
||||
ScoreManager.PostNotification = n => Notifications.Post(n);
|
||||
ScoreManager.PresentImport = items => PresentScore(items.First());
|
||||
ScoreManager.PostImport = items => PresentScore(items.First().Value);
|
||||
|
||||
// make config aware of how to lookup skins for on-screen display purposes.
|
||||
// if this becomes a more common thing, tracked settings should be reconsidered to allow local DI.
|
||||
|
@ -25,7 +25,7 @@ using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Scoring
|
||||
{
|
||||
public class ScoreManager : IModelManager<ScoreInfo>, IModelFileManager<ScoreInfo, ScoreFileInfo>, IModelDownloader<ScoreInfo>, ICanAcceptFiles, IPresentImports<ScoreInfo>
|
||||
public class ScoreManager : IModelManager<ScoreInfo>, IModelFileManager<ScoreInfo, ScoreFileInfo>, IModelDownloader<ScoreInfo>, ICanAcceptFiles, IPostImports<ScoreInfo>
|
||||
{
|
||||
private readonly Scheduler scheduler;
|
||||
private readonly Func<BeatmapDifficultyCache> difficulties;
|
||||
@ -299,22 +299,22 @@ namespace osu.Game.Scoring
|
||||
|
||||
public IEnumerable<string> HandledExtensions => scoreModelManager.HandledExtensions;
|
||||
|
||||
public Task<IEnumerable<ScoreInfo>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
public Task<IEnumerable<ILive<ScoreInfo>>> Import(ProgressNotification notification, params ImportTask[] tasks)
|
||||
{
|
||||
return scoreModelManager.Import(notification, tasks);
|
||||
}
|
||||
|
||||
public Task<ScoreInfo> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<ScoreInfo>> Import(ImportTask task, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return scoreModelManager.Import(task, lowPriority, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<ScoreInfo> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<ScoreInfo>> Import(ArchiveReader archive, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return scoreModelManager.Import(archive, lowPriority, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<ScoreInfo> Import(ScoreInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
public Task<ILive<ScoreInfo>> Import(ScoreInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return scoreModelManager.Import(item, archive, lowPriority, cancellationToken);
|
||||
}
|
||||
@ -365,9 +365,9 @@ namespace osu.Game.Scoring
|
||||
|
||||
#region Implementation of IPresentImports<ScoreInfo>
|
||||
|
||||
public Action<IEnumerable<ScoreInfo>> PresentImport
|
||||
public Action<IEnumerable<ILive<ScoreInfo>>> PostImport
|
||||
{
|
||||
set => scoreModelManager.PresentImport = value;
|
||||
set => scoreModelManager.PostImport = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -101,8 +101,12 @@ namespace osu.Game.Screens.Menu
|
||||
// if we detect that the theme track or beatmap is unavailable this is either first startup or things are in a bad state.
|
||||
// this could happen if a user has nuked their files store. for now, reimport to repair this.
|
||||
var import = beatmaps.Import(new ZipArchiveReader(game.Resources.GetStream($"Tracks/{BeatmapFile}"), BeatmapFile)).Result;
|
||||
import.Protected = true;
|
||||
beatmaps.Update(import);
|
||||
|
||||
import.PerformWrite(b =>
|
||||
{
|
||||
b.Protected = true;
|
||||
beatmaps.Update(b);
|
||||
});
|
||||
|
||||
loadThemedIntro();
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ namespace osu.Game.Skinning
|
||||
Name = skin.SkinInfo.Name + " (modified)",
|
||||
Creator = skin.SkinInfo.Creator,
|
||||
InstantiationInfo = skin.SkinInfo.InstantiationInfo,
|
||||
}).Result;
|
||||
}).Result.Value;
|
||||
}
|
||||
|
||||
public void Save(Skin skin)
|
||||
|
Loading…
Reference in New Issue
Block a user