Merge pull request #20641 from pfgithub/patch-fix-save-collections

Preserve collections when saving a beatmap
This commit is contained in:
Dean Herbert 2022-10-12 18:36:45 +09:00 committed by GitHub
commit 3da54814f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 12 deletions

View File

@ -9,8 +9,10 @@
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Tests.Resources;
using osu.Game.Tests.Visual;
@ -96,5 +98,41 @@ public void TestForcedRefetchRetrievalWithFiles() => AddStep("run test", () =>
var second = beatmaps.GetWorkingBeatmap(beatmap, true);
Assert.That(first, Is.Not.SameAs(second));
});
[Test]
public void TestSavePreservesCollections() => AddStep("run test", () =>
{
var beatmap = Realm.Run(r => r.Find<BeatmapInfo>(importedSet.Beatmaps.First().ID).Detach());
var working = beatmaps.GetWorkingBeatmap(beatmap);
Assert.That(working.BeatmapInfo.BeatmapSet?.Files, Has.Count.GreaterThan(0));
string initialHash = working.BeatmapInfo.MD5Hash;
var preserveCollection = new BeatmapCollection("test contained");
preserveCollection.BeatmapMD5Hashes.Add(initialHash);
var noNewCollection = new BeatmapCollection("test not contained");
Realm.Write(r =>
{
r.Add(preserveCollection);
r.Add(noNewCollection);
});
Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(initialHash));
Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash));
beatmaps.Save(working.BeatmapInfo, working.GetPlayableBeatmap(new OsuRuleset().RulesetInfo));
string finalHash = working.BeatmapInfo.MD5Hash;
Assert.That(finalHash, Is.Not.SameAs(initialHash));
Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Not.Contain(initialHash));
Assert.That(preserveCollection.BeatmapMD5Hashes, Does.Contain(finalHash));
Assert.That(noNewCollection.BeatmapMD5Hashes, Does.Not.Contain(finalHash));
});
}
}

View File

@ -141,18 +141,9 @@ private static void transferCollectionReferences(Realm realm, BeatmapSetInfo ori
// Handle collections using permissive difficulty name to track difficulties.
foreach (var originalBeatmap in original.Beatmaps)
{
var updatedBeatmap = updated.Beatmaps.FirstOrDefault(b => b.DifficultyName == originalBeatmap.DifficultyName);
if (updatedBeatmap == null)
continue;
var collections = realm.All<BeatmapCollection>().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(originalBeatmap.MD5Hash));
foreach (var c in collections)
{
c.BeatmapMD5Hashes.Remove(originalBeatmap.MD5Hash);
c.BeatmapMD5Hashes.Add(updatedBeatmap.MD5Hash);
}
updated.Beatmaps
.FirstOrDefault(b => b.DifficultyName == originalBeatmap.DifficultyName)?
.TransferCollectionReferences(realm, originalBeatmap.MD5Hash);
}
}

View File

@ -8,6 +8,7 @@
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Models;
using osu.Game.Online.API.Requests.Responses;
@ -213,6 +214,23 @@ private static bool compareFiles(BeatmapInfo x, BeatmapInfo y, Func<IBeatmapMeta
return fileHashX == fileHashY;
}
/// <summary>
/// When updating a beatmap, its hashes will change. Collections currently track beatmaps by hash, so they need to be updated.
/// This method will handle updating
/// </summary>
/// <param name="realm">A realm instance in an active write transaction.</param>
/// <param name="previousMD5Hash">The previous MD5 hash of the beatmap before update.</param>
public void TransferCollectionReferences(Realm realm, string previousMD5Hash)
{
var collections = realm.All<BeatmapCollection>().AsEnumerable().Where(c => c.BeatmapMD5Hashes.Contains(previousMD5Hash));
foreach (var c in collections)
{
c.BeatmapMD5Hashes.Remove(previousMD5Hash);
c.BeatmapMD5Hashes.Add(MD5Hash);
}
}
IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata;
IBeatmapSetInfo? IBeatmapInfo.BeatmapSet => BeatmapSet;
IRulesetInfo IBeatmapInfo.Ruleset => Ruleset;

View File

@ -311,6 +311,8 @@ public virtual void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin
if (existingFileInfo != null)
DeleteFile(setInfo, existingFileInfo);
string oldMd5Hash = beatmapInfo.MD5Hash;
beatmapInfo.MD5Hash = stream.ComputeMD5Hash();
beatmapInfo.Hash = stream.ComputeSHA2Hash();
@ -327,6 +329,8 @@ public virtual void Save(BeatmapInfo beatmapInfo, IBeatmap beatmapContent, ISkin
setInfo.CopyChangesToRealm(liveBeatmapSet);
beatmapInfo.TransferCollectionReferences(r, oldMd5Hash);
ProcessBeatmap?.Invoke((liveBeatmapSet, false));
});
}