mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 02:13:21 +08:00
Move deletion to ArchiveModelImportManager
This commit is contained in:
parent
d8f84fcca3
commit
6ff63c2f0c
@ -97,10 +97,10 @@ namespace osu.Game.Beatmaps
|
||||
b.Metadata = null;
|
||||
}
|
||||
|
||||
protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo beatmapSet)
|
||||
protected override BeatmapSetInfo CheckForExisting(BeatmapSetInfo model)
|
||||
{
|
||||
// check if this beatmap has already been imported and exit early if so
|
||||
var existingHashMatch = beatmaps.BeatmapSets.FirstOrDefault(b => b.Hash == beatmapSet.Hash);
|
||||
var existingHashMatch = beatmaps.BeatmapSets.FirstOrDefault(b => b.Hash == model.Hash);
|
||||
if (existingHashMatch != null)
|
||||
{
|
||||
Undelete(existingHashMatch);
|
||||
@ -108,9 +108,9 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
|
||||
// check if a set already exists with the same online id
|
||||
if (beatmapSet.OnlineBeatmapSetID != null)
|
||||
if (model.OnlineBeatmapSetID != null)
|
||||
{
|
||||
var existingOnlineId = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID);
|
||||
var existingOnlineId = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == model.OnlineBeatmapSetID);
|
||||
if (existingOnlineId != null)
|
||||
{
|
||||
Delete(existingOnlineId);
|
||||
@ -217,32 +217,6 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="beatmapSet">The beatmap set to update.</param>
|
||||
public void Update(BeatmapSetInfo beatmap) => beatmaps.Update(beatmap);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a beatmap from the manager.
|
||||
/// Is a no-op for already deleted beatmaps.
|
||||
/// </summary>
|
||||
/// <param name="beatmapSet">The beatmap set to delete.</param>
|
||||
public void Delete(BeatmapSetInfo beatmapSet)
|
||||
{
|
||||
using (var usage = ContextFactory.GetForWrite())
|
||||
{
|
||||
var context = usage.Context;
|
||||
|
||||
context.ChangeTracker.AutoDetectChangesEnabled = false;
|
||||
|
||||
// re-fetch the beatmap set on the import context.
|
||||
beatmapSet = context.BeatmapSetInfo.Include(s => s.Files).ThenInclude(f => f.FileInfo).First(s => s.ID == beatmapSet.ID);
|
||||
|
||||
if (beatmaps.Delete(beatmapSet))
|
||||
{
|
||||
if (!beatmapSet.Protected)
|
||||
Files.Dereference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
||||
}
|
||||
|
||||
context.ChangeTracker.AutoDetectChangesEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore all beatmaps that were previously deleted.
|
||||
/// This will post notifications tracking progress.
|
||||
@ -351,7 +325,7 @@ namespace osu.Game.Beatmaps
|
||||
/// Returns a list of all usable <see cref="BeatmapSetInfo"/>s.
|
||||
/// </summary>
|
||||
/// <returns>A list of available <see cref="BeatmapSetInfo"/>.</returns>
|
||||
public List<BeatmapSetInfo> GetAllUsableBeatmapSets() => beatmaps.BeatmapSets.Where(s => !s.DeletePending).ToList();
|
||||
public List<BeatmapSetInfo> GetAllUsableBeatmapSets() => beatmaps.BeatmapSets.Where(s => !s.DeletePending && !s.Protected).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Perform a lookup query on available <see cref="BeatmapSetInfo"/>s.
|
||||
|
@ -9,7 +9,7 @@ using osu.Game.IO;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>
|
||||
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int ID { get; set; }
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Beatmaps
|
||||
/// <summary>
|
||||
/// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing
|
||||
/// </summary>
|
||||
public class BeatmapStore : DatabaseBackedStore, IAddableStore<BeatmapSetInfo>
|
||||
public class BeatmapStore : DatabaseBackedStore, IMutableStore<BeatmapSetInfo>
|
||||
{
|
||||
public event Action<BeatmapSetInfo> BeatmapSetAdded;
|
||||
public event Action<BeatmapSetInfo> BeatmapSetRemoved;
|
||||
@ -79,7 +79,7 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
Refresh(ref beatmapSet, BeatmapSets);
|
||||
|
||||
if (beatmapSet.DeletePending) return false;
|
||||
if (beatmapSet.Protected || beatmapSet.DeletePending) return false;
|
||||
|
||||
beatmapSet.DeletePending = true;
|
||||
}
|
||||
@ -178,17 +178,17 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
|
||||
public IQueryable<BeatmapSetInfo> BeatmapSets => ContextFactory.Get().BeatmapSetInfo
|
||||
.Include(s => s.Metadata)
|
||||
.Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset)
|
||||
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
|
||||
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
|
||||
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
|
||||
.Include(s => s.Metadata)
|
||||
.Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset)
|
||||
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
|
||||
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
|
||||
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
|
||||
|
||||
public IQueryable<BeatmapInfo> Beatmaps => ContextFactory.Get().BeatmapInfo
|
||||
.Include(b => b.BeatmapSet).ThenInclude(s => s.Metadata)
|
||||
.Include(b => b.BeatmapSet).ThenInclude(s => s.Files).ThenInclude(f => f.FileInfo)
|
||||
.Include(b => b.Metadata)
|
||||
.Include(b => b.Ruleset)
|
||||
.Include(b => b.BaseDifficulty);
|
||||
.Include(b => b.BeatmapSet).ThenInclude(s => s.Metadata)
|
||||
.Include(b => b.BeatmapSet).ThenInclude(s => s.Files).ThenInclude(f => f.FileInfo)
|
||||
.Include(b => b.Metadata)
|
||||
.Include(b => b.Ruleset)
|
||||
.Include(b => b.BaseDifficulty);
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Ionic.Zip;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.IO;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using FileInfo = osu.Game.IO.FileInfo;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public abstract class ArchiveModelImportManager<TModel, TFileModel> : ICanImportArchives
|
||||
where TModel : class, IHasFiles<TFileModel>
|
||||
where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete
|
||||
where TFileModel : INamedFileInfo, new()
|
||||
{
|
||||
/// <summary>
|
||||
@ -28,12 +30,12 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
protected readonly IDatabaseContextFactory ContextFactory;
|
||||
|
||||
protected readonly IAddableStore<TModel> ModelStore;
|
||||
protected readonly IMutableStore<TModel> ModelStore;
|
||||
|
||||
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||
private ArchiveImportIPCChannel ipc;
|
||||
|
||||
protected ArchiveModelImportManager(Storage storage, IDatabaseContextFactory contextFactory, IAddableStore<TModel> modelStore, IIpcHost importHost = null)
|
||||
protected ArchiveModelImportManager(Storage storage, IDatabaseContextFactory contextFactory, IMutableStore<TModel> modelStore, IIpcHost importHost = null)
|
||||
{
|
||||
ContextFactory = contextFactory;
|
||||
ModelStore = modelStore;
|
||||
@ -127,6 +129,31 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete a model from the manager.
|
||||
/// Is a no-op for already deleted models.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to delete.</param>
|
||||
public void Delete(TModel model)
|
||||
{
|
||||
using (var usage = ContextFactory.GetForWrite())
|
||||
{
|
||||
var context = usage.Context;
|
||||
|
||||
context.ChangeTracker.AutoDetectChangesEnabled = false;
|
||||
|
||||
// re-fetch the model on the import context.
|
||||
var foundModel = ContextFactory.Get().Set<TModel>().Include(s => s.Files).ThenInclude(f => f.FileInfo).First(s => s.ID == model.ID);
|
||||
|
||||
if (foundModel.DeletePending || !CheckCanDelete(foundModel)) return;
|
||||
|
||||
if (ModelStore.Delete(foundModel))
|
||||
Files.Dereference(foundModel.Files.Select(f => f.FileInfo).ToArray());
|
||||
|
||||
context.ChangeTracker.AutoDetectChangesEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create all required <see cref="FileInfo"/>s for the provided archive, adding them to the global file store.
|
||||
/// </summary>
|
||||
@ -164,13 +191,15 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual TModel CheckForExisting(TModel beatmapSet) => null;
|
||||
protected virtual TModel CheckForExisting(TModel model) => null;
|
||||
|
||||
protected virtual bool CheckCanDelete(TModel model) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ArchiveReader"/> from a valid storage path.
|
||||
/// </summary>
|
||||
/// <param name="path">A file or folder path resolving the beatmap content.</param>
|
||||
/// <returns>A reader giving access to the beatmap's content.</returns>
|
||||
/// <param name="path">A file or folder path resolving the archive content.</param>
|
||||
/// <returns>A reader giving access to the archive's content.</returns>
|
||||
private ArchiveReader getReaderFrom(string path)
|
||||
{
|
||||
if (ZipFile.IsZipFile(path))
|
@ -1,4 +1,4 @@
|
||||
namespace osu.Game.Beatmaps
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public interface ICanImportArchives
|
||||
{
|
10
osu.Game/Database/ISoftDelete.cs
Normal file
10
osu.Game/Database/ISoftDelete.cs
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public interface ISoftDelete
|
||||
{
|
||||
bool DeletePending { get; set; }
|
||||
}
|
||||
}
|
@ -3,12 +3,14 @@
|
||||
|
||||
namespace osu.Game.IO
|
||||
{
|
||||
public interface IAddableStore<in T>
|
||||
public interface IMutableStore<in T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Add an object to the store.
|
||||
/// </summary>
|
||||
/// <param name="object">The object to add.</param>
|
||||
void Add(T item);
|
||||
|
||||
bool Delete(T item);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.IPC
|
||||
{
|
||||
|
@ -63,7 +63,9 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
// we need to import the default menu background beatmap
|
||||
setInfo = beatmaps.Import(new OszArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"), "circles.osz"));
|
||||
|
||||
setInfo.Protected = true;
|
||||
beatmaps.Update(setInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,9 +75,6 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
welcome = audio.Sample.Get(@"welcome");
|
||||
seeya = audio.Sample.Get(@"seeya");
|
||||
|
||||
if (setInfo.Protected)
|
||||
beatmaps.Delete(setInfo);
|
||||
}
|
||||
|
||||
protected override void OnEntering(Screen last)
|
||||
|
@ -243,7 +243,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Audio\SampleInfo.cs" />
|
||||
<Compile Include="Beatmaps\ArchiveModelImportManager.cs" />
|
||||
<Compile Include="Beatmaps\Beatmap.cs" />
|
||||
<Compile Include="Beatmaps\BeatmapConverter.cs" />
|
||||
<Compile Include="Beatmaps\BeatmapDifficulty.cs" />
|
||||
@ -271,20 +270,22 @@
|
||||
<Compile Include="Beatmaps\Formats\JsonBeatmapDecoder.cs" />
|
||||
<Compile Include="Beatmaps\Formats\LegacyDecoder.cs" />
|
||||
<Compile Include="Beatmaps\Formats\LegacyStoryboardDecoder.cs" />
|
||||
<Compile Include="Beatmaps\ICanImportArchives.cs" />
|
||||
<Compile Include="Configuration\DatabasedSetting.cs" />
|
||||
<Compile Include="Configuration\SettingsStore.cs" />
|
||||
<Compile Include="Configuration\DatabasedConfigManager.cs" />
|
||||
<Compile Include="Configuration\SpeedChangeVisualisationMethod.cs" />
|
||||
<Compile Include="Database\ArchiveModelImportManager.cs" />
|
||||
<Compile Include="Database\DatabaseContextFactory.cs" />
|
||||
<Compile Include="Database\DatabaseWriteUsage.cs" />
|
||||
<Compile Include="Database\ICanImportArchives.cs" />
|
||||
<Compile Include="Database\IDatabaseContextFactory.cs" />
|
||||
<Compile Include="Database\IHasPrimaryKey.cs" />
|
||||
<Compile Include="Database\INamedFileInfo.cs" />
|
||||
<Compile Include="Database\ISoftDelete.cs" />
|
||||
<Compile Include="Database\SingletonContextFactory.cs" />
|
||||
<Compile Include="Graphics\Containers\LinkFlowContainer.cs" />
|
||||
<Compile Include="Graphics\Textures\LargeTextureStore.cs" />
|
||||
<Compile Include="IO\IAddableStore.cs" />
|
||||
<Compile Include="IO\IMutableStore.cs" />
|
||||
<Compile Include="IO\IHasFiles.cs" />
|
||||
<Compile Include="Online\API\APIDownloadRequest.cs" />
|
||||
<Compile Include="Online\API\Requests\GetUserRequest.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user