Refactor to support beatmap updates

This commit is contained in:
smoogipoo 2020-01-02 13:20:38 +09:00
parent f745d74666
commit 681a43a318
3 changed files with 101 additions and 5 deletions

View File

@ -11,9 +11,14 @@ using NUnit.Framework;
using osu.Framework.Platform;
using osu.Game.IPC;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.Database;
using osu.Game.IO;
using osu.Game.IO.Archives;
using osu.Game.Tests.Resources;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
@ -552,6 +557,46 @@ namespace osu.Game.Tests.Beatmaps.IO
}
}
[Test]
public async Task TestUpdateFile()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost(nameof(TestUpdateFile)))
{
try
{
var osu = loadOsu(host);
var manager = osu.Dependencies.Get<BeatmapManager>();
var temp = TestResources.GetTestBeatmapForImport();
await osu.Dependencies.Get<BeatmapManager>().Import(temp);
BeatmapSetInfo setToUpdate = manager.GetAllUsableBeatmapSets()[0];
Beatmap beatmapToUpdate = (Beatmap)manager.GetWorkingBeatmap(setToUpdate.Beatmaps.First(b => b.RulesetID == 0)).Beatmap;
BeatmapSetFileInfo fileToUpdate = setToUpdate.Files.First(f => beatmapToUpdate.BeatmapInfo.Path.Contains(f.Filename));
using (var stream = new MemoryStream())
{
using (var writer = new StreamWriter(stream, leaveOpen: true))
{
beatmapToUpdate.BeatmapInfo.Version = "updated";
new LegacyBeatmapEncoder(beatmapToUpdate).Encode(writer);
}
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new UpdateArchiveReader<BeatmapSetInfo, BeatmapSetFileInfo>(manager.Files.Store, setToUpdate, fileToUpdate, stream))
await manager.Import(setToUpdate, reader);
}
var allBeatmaps = manager.GetAllUsableBeatmapSets();
}
finally
{
host.Exit();
}
}
}
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
{
var temp = path ?? TestResources.GetTestBeatmapForImport(virtualTrack);
@ -655,5 +700,56 @@ namespace osu.Game.Tests.Beatmaps.IO
Assert.IsTrue(task.Wait(timeout), failureMessage);
}
private class UpdateArchiveReader<TModel, TFileModel> : ArchiveReader
where TModel : class, IHasFiles<TFileModel>
where TFileModel : INamedFileInfo, new()
{
private readonly IResourceStore<byte[]> store;
private readonly TModel modelToUpdate;
private readonly TFileModel fileToUpdate;
private readonly Stream newContents;
public UpdateArchiveReader(IResourceStore<byte[]> store, TModel modelToUpdate, TFileModel fileToUpdate, Stream newContents)
: base(string.Empty)
{
this.store = store;
this.modelToUpdate = modelToUpdate;
this.fileToUpdate = fileToUpdate;
this.newContents = newContents;
}
public override Stream GetStream(string name)
{
name = name.ToStandardisedPath();
if (name.Contains(fileToUpdate.Filename, StringComparison.Ordinal))
{
var stream = new MemoryStream();
newContents.Seek(0, SeekOrigin.Begin);
newContents.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
TFileModel existing = modelToUpdate.Files.FirstOrDefault(m => name.Contains(m.Filename, StringComparison.Ordinal));
if (!string.IsNullOrEmpty(existing?.FileInfo?.StoragePath))
return store.GetStream(existing.FileInfo.StoragePath);
return null;
}
public override void Dispose()
{
}
public override IEnumerable<string> Filenames => Enumerable.Empty<string>(); // modelToUpdate.Files.Select(f => f.Filename);
public override Stream GetUnderlyingStream() => null;
}
}
}

View File

@ -63,7 +63,7 @@ namespace osu.Game.Beatmaps.Formats
writer.WriteLine(FormattableString.Invariant($"PreviewTime: {beatmap.Metadata.PreviewTime}"));
// Todo: Not all countdown types are supported by lazer yet
writer.WriteLine(FormattableString.Invariant($"Countdown: {(beatmap.BeatmapInfo.Countdown ? '1' : '0')}"));
writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePoints[0].SampleBank)}"));
writer.WriteLine(FormattableString.Invariant($"SampleSet: {toLegacySampleBank(beatmap.ControlPointInfo.SamplePointAt(double.MinValue).SampleBank)}"));
writer.WriteLine(FormattableString.Invariant($"StackLeniency: {beatmap.BeatmapInfo.StackLeniency}"));
writer.WriteLine(FormattableString.Invariant($"Mode: {beatmap.BeatmapInfo.RulesetID}"));
writer.WriteLine(FormattableString.Invariant($"LetterboxInBreaks: {(beatmap.BeatmapInfo.LetterboxInBreaks ? '1' : '0')}"));

View File

@ -68,7 +68,7 @@ namespace osu.Game.Database
public virtual bool SupportsImportFromStable => RuntimeInfo.IsDesktop;
protected readonly FileStore Files;
public readonly FileStore Files;
protected readonly IDatabaseContextFactory ContextFactory;
@ -222,9 +222,8 @@ namespace osu.Game.Database
{
model = CreateModel(archive);
if (model == null) return Task.FromResult<TModel>(null);
model.Hash = computeHash(archive);
if (model == null)
return Task.FromResult<TModel>(null);
}
catch (TaskCanceledException)
{
@ -303,6 +302,7 @@ namespace osu.Game.Database
LogForModel(item, "Beginning import...");
item.Files = archive != null ? createFileInfos(archive, Files) : new List<TFileModel>();
item.Hash = archive != null ? computeHash(archive) : item.Hash;
await Populate(item, archive, cancellationToken);