From 9e6e41d7c06c09e671c3274ef7f56a75cfd09f1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 20 Oct 2021 17:33:36 +0900 Subject: [PATCH] Add migration to reset and repopulate existing skin hashes --- osu.Game/Database/ArchiveModelManager.cs | 11 +++++---- .../20211020081609_ResetSkinHashes.cs | 23 +++++++++++++++++++ osu.Game/Skinning/SkinManager.cs | 22 ++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 osu.Game/Migrations/20211020081609_ResetSkinHashes.cs diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 5b07bfe9a5..63a5da79a7 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -32,7 +32,7 @@ namespace osu.Game.Database /// The associated file join type. public abstract class ArchiveModelManager : IModelManager, IModelFileManager where TModel : class, IHasFiles, IHasPrimaryKey, ISoftDelete - where TFileModel : class, INamedFileInfo, new() + where TFileModel : class, INamedFileInfo, IHasPrimaryKey, new() { private const int import_queue_request_concurrency = 1; @@ -520,9 +520,12 @@ namespace osu.Game.Database { Files.Dereference(file.FileInfo); - // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked - // Definitely can be removed once we rework the database backend. - usage.Context.Set().Remove(file); + if (file.ID > 0) + { + // This shouldn't be required, but here for safety in case the provided TModel is not being change tracked + // Definitely can be removed once we rework the database backend. + usage.Context.Set().Remove(file); + } } model.Files.Remove(file); diff --git a/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs b/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs new file mode 100644 index 0000000000..6d53c019ec --- /dev/null +++ b/osu.Game/Migrations/20211020081609_ResetSkinHashes.cs @@ -0,0 +1,23 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20211020081609_ResetSkinHashes")] + public partial class ResetSkinHashes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"UPDATE SkinInfo SET Hash = null"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 213c92c103..0b611bfe8f 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -18,6 +18,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; @@ -84,6 +85,27 @@ namespace osu.Game.Skinning SourceChanged?.Invoke(); }; + + // can be removed 20220420. + populateMissingHashes(); + } + + private void populateMissingHashes() + { + var skinsWithoutHashes = ModelStore.ConsumableItems.Where(i => i.Hash == null).ToArray(); + + foreach (SkinInfo skin in skinsWithoutHashes) + { + try + { + Update(skin); + } + catch (Exception e) + { + Delete(skin); + Logger.Error(e, $"Existing skin {skin} has been deleted during hash recomputation due to being invalid"); + } + } } protected override bool ShouldDeleteArchive(string path) => Path.GetExtension(path)?.ToLowerInvariant() == ".osk";