mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 05:22:54 +08:00
Move migrations to own file and add user skin choice config migration
This commit is contained in:
parent
0efd565c8b
commit
6f66ecd77b
147
osu.Game/Database/EFToRealmMigrator.cs
Normal file
147
osu.Game/Database/EFToRealmMigrator.cs
Normal file
@ -0,0 +1,147 @@
|
||||
// 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.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
internal class EFToRealmMigrator
|
||||
{
|
||||
private readonly DatabaseContextFactory efContextFactory;
|
||||
private readonly RealmContextFactory realmContextFactory;
|
||||
private readonly OsuConfigManager config;
|
||||
|
||||
public EFToRealmMigrator(DatabaseContextFactory efContextFactory, RealmContextFactory realmContextFactory, OsuConfigManager config)
|
||||
{
|
||||
this.efContextFactory = efContextFactory;
|
||||
this.realmContextFactory = realmContextFactory;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
using (var db = efContextFactory.GetForWrite())
|
||||
{
|
||||
migrateSettings(db);
|
||||
migrateSkins(db);
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateSkins(DatabaseWriteUsage db)
|
||||
{
|
||||
var userSkinChoice = config.GetBindable<string>(OsuSetting.Skin);
|
||||
int.TryParse(userSkinChoice.Value, out int userSkinInt);
|
||||
|
||||
switch (userSkinInt)
|
||||
{
|
||||
case EFSkinInfo.DEFAULT_SKIN:
|
||||
userSkinChoice.Value = SkinInfo.DEFAULT_SKIN.ToString();
|
||||
break;
|
||||
|
||||
case EFSkinInfo.CLASSIC_SKIN:
|
||||
userSkinChoice.Value = SkinInfo.CLASSIC_SKIN.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
// migrate ruleset settings. can be removed 20220530.
|
||||
var existingSkins = db.Context.SkinInfo
|
||||
.Include(s => s.Files)
|
||||
.ThenInclude(f => f.FileInfo)
|
||||
.ToList();
|
||||
|
||||
// previous entries in EF are removed post migration.
|
||||
if (!existingSkins.Any())
|
||||
return;
|
||||
|
||||
using (var realm = realmContextFactory.CreateContext())
|
||||
using (var transaction = realm.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
if (!realm.All<SkinInfo>().Any(s => !s.Protected))
|
||||
{
|
||||
foreach (var skin in existingSkins)
|
||||
{
|
||||
var realmSkin = new SkinInfo
|
||||
{
|
||||
Name = skin.Name,
|
||||
Creator = skin.Creator,
|
||||
Hash = skin.Hash,
|
||||
Protected = false,
|
||||
InstantiationInfo = skin.InstantiationInfo,
|
||||
};
|
||||
|
||||
foreach (var file in skin.Files)
|
||||
{
|
||||
var realmFile = realm.Find<RealmFile>(file.FileInfo.Hash);
|
||||
|
||||
if (realmFile == null)
|
||||
realm.Add(realmFile = new RealmFile { Hash = file.FileInfo.Hash });
|
||||
|
||||
realmSkin.Files.Add(new RealmNamedFileUsage(realmFile, file.Filename));
|
||||
}
|
||||
|
||||
realm.Add(realmSkin);
|
||||
|
||||
if (skin.ID == userSkinInt)
|
||||
userSkinChoice.Value = realmSkin.ID.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
db.Context.RemoveRange(existingSkins);
|
||||
// Intentionally don't clean up the files, so they don't get purged by EF.
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
private void migrateSettings(DatabaseWriteUsage db)
|
||||
{
|
||||
// migrate ruleset settings. can be removed 20220315.
|
||||
var existingSettings = db.Context.DatabasedSetting;
|
||||
|
||||
// previous entries in EF are removed post migration.
|
||||
if (!existingSettings.Any())
|
||||
return;
|
||||
|
||||
using (var realm = realmContextFactory.CreateContext())
|
||||
using (var transaction = realm.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
if (!realm.All<RealmRulesetSetting>().Any())
|
||||
{
|
||||
foreach (var dkb in existingSettings)
|
||||
{
|
||||
if (dkb.RulesetID == null)
|
||||
continue;
|
||||
|
||||
string? shortName = getRulesetShortNameFromLegacyID(dkb.RulesetID.Value);
|
||||
|
||||
if (string.IsNullOrEmpty(shortName))
|
||||
continue;
|
||||
|
||||
realm.Add(new RealmRulesetSetting
|
||||
{
|
||||
Key = dkb.Key,
|
||||
Value = dkb.StringValue,
|
||||
RulesetName = shortName,
|
||||
Variant = dkb.Variant ?? 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
db.Context.RemoveRange(existingSettings);
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
private string? getRulesetShortNameFromLegacyID(long rulesetId) =>
|
||||
efContextFactory.Get().RulesetInfo.FirstOrDefault(r => r.ID == rulesetId)?.ShortName;
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Development;
|
||||
using osu.Framework.Input.Bindings;
|
||||
@ -103,10 +102,6 @@ namespace osu.Game.Database
|
||||
|
||||
// This method triggers the first `CreateContext` call, which will implicitly run realm migrations and bring the schema up-to-date.
|
||||
cleanupPendingDeletions();
|
||||
|
||||
// Data migration is handled separately from schema migrations.
|
||||
// This is required as the user may be initialising realm for the first time ever, which would result in no schema migrations running.
|
||||
migrateDataFromEF();
|
||||
}
|
||||
|
||||
private void cleanupPendingDeletions()
|
||||
@ -200,108 +195,6 @@ namespace osu.Game.Database
|
||||
};
|
||||
}
|
||||
|
||||
private void migrateDataFromEF()
|
||||
{
|
||||
if (efContextFactory == null)
|
||||
return;
|
||||
|
||||
using (var db = efContextFactory.GetForWrite())
|
||||
{
|
||||
migrateSettings(db);
|
||||
migrateSkins(db);
|
||||
}
|
||||
|
||||
void migrateSkins(DatabaseWriteUsage db)
|
||||
{
|
||||
// migrate ruleset settings. can be removed 20220530.
|
||||
var existingSkins = db.Context.SkinInfo
|
||||
.Include(s => s.Files)
|
||||
.ThenInclude(f => f.FileInfo);
|
||||
|
||||
// previous entries in EF are removed post migration.
|
||||
if (!existingSkins.Any())
|
||||
return;
|
||||
|
||||
using (var realm = CreateContext())
|
||||
using (var transaction = realm.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
if (!realm.All<SkinInfo>().Any(s => !s.Protected))
|
||||
{
|
||||
foreach (var skin in existingSkins)
|
||||
{
|
||||
var realmSkin = new SkinInfo
|
||||
{
|
||||
Name = skin.Name,
|
||||
Creator = skin.Creator,
|
||||
Hash = skin.Hash,
|
||||
Protected = false,
|
||||
InstantiationInfo = skin.InstantiationInfo,
|
||||
};
|
||||
|
||||
foreach (var file in skin.Files)
|
||||
{
|
||||
var realmFile = realm.Find<RealmFile>(file.FileInfo.Hash);
|
||||
|
||||
if (realmFile == null)
|
||||
realm.Add(realmFile = new RealmFile { Hash = file.FileInfo.Hash });
|
||||
|
||||
realmSkin.Files.Add(new RealmNamedFileUsage(realmFile, file.Filename));
|
||||
}
|
||||
|
||||
realm.Add(realmSkin);
|
||||
}
|
||||
}
|
||||
|
||||
db.Context.RemoveRange(existingSkins);
|
||||
// Intentionally don't clean up the files, so they don't get purged by EF.
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
void migrateSettings(DatabaseWriteUsage db)
|
||||
{
|
||||
// migrate ruleset settings. can be removed 20220315.
|
||||
var existingSettings = db.Context.DatabasedSetting;
|
||||
|
||||
// previous entries in EF are removed post migration.
|
||||
if (!existingSettings.Any())
|
||||
return;
|
||||
|
||||
using (var realm = CreateContext())
|
||||
using (var transaction = realm.BeginWrite())
|
||||
{
|
||||
// only migrate data if the realm database is empty.
|
||||
if (!realm.All<RealmRulesetSetting>().Any())
|
||||
{
|
||||
foreach (var dkb in existingSettings)
|
||||
{
|
||||
if (dkb.RulesetID == null)
|
||||
continue;
|
||||
|
||||
string? shortName = getRulesetShortNameFromLegacyID(dkb.RulesetID.Value);
|
||||
|
||||
if (string.IsNullOrEmpty(shortName))
|
||||
continue;
|
||||
|
||||
realm.Add(new RealmRulesetSetting
|
||||
{
|
||||
Key = dkb.Key,
|
||||
Value = dkb.StringValue,
|
||||
RulesetName = shortName,
|
||||
Variant = dkb.Variant ?? 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
db.Context.RemoveRange(existingSettings);
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onMigration(Migration migration, ulong lastSchemaVersion)
|
||||
{
|
||||
for (ulong i = lastSchemaVersion + 1; i <= schema_version; i++)
|
||||
|
@ -198,6 +198,8 @@ namespace osu.Game
|
||||
|
||||
dependencies.Cache(realmFactory = new RealmContextFactory(Storage, "client", contextFactory));
|
||||
|
||||
new EFToRealmMigrator(contextFactory, realmFactory, LocalConfig).Run();
|
||||
|
||||
dependencies.CacheAs(Storage);
|
||||
|
||||
var largeStore = new LargeTextureStore(Host.CreateTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures")));
|
||||
|
Loading…
Reference in New Issue
Block a user