mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 12:57:36 +08:00
Split out legacy model export logic into LegacyModelExporter
classes
This commit is contained in:
parent
7488ccd5fe
commit
cc1b91e4bd
@ -225,16 +225,6 @@ namespace osu.Game.Beatmaps
|
||||
remove => beatmapModelManager.ItemRemoved -= value;
|
||||
}
|
||||
|
||||
public void Export(BeatmapSetInfo item)
|
||||
{
|
||||
beatmapModelManager.Export(item);
|
||||
}
|
||||
|
||||
public void ExportModelTo(BeatmapSetInfo model, Stream outputStream)
|
||||
{
|
||||
beatmapModelManager.ExportModelTo(model, outputStream);
|
||||
}
|
||||
|
||||
public void Update(BeatmapSetInfo item)
|
||||
{
|
||||
beatmapModelManager.Update(item);
|
||||
|
@ -20,7 +20,6 @@ using osu.Game.IO;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.IPC;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -82,8 +81,6 @@ namespace osu.Game.Database
|
||||
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||
private ArchiveImportIPCChannel ipc;
|
||||
|
||||
private readonly Storage exportStorage;
|
||||
|
||||
protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes<TModel, TFileModel> modelStore, IIpcHost importHost = null)
|
||||
{
|
||||
ContextFactory = contextFactory;
|
||||
@ -92,8 +89,6 @@ namespace osu.Game.Database
|
||||
ModelStore.ItemUpdated += item => handleEvent(() => ItemUpdated?.Invoke(item));
|
||||
ModelStore.ItemRemoved += item => handleEvent(() => ItemRemoved?.Invoke(item));
|
||||
|
||||
exportStorage = storage.GetStorageForDirectory(@"exports");
|
||||
|
||||
Files = new FileStore(contextFactory, storage);
|
||||
|
||||
if (importHost != null)
|
||||
@ -452,41 +447,6 @@ namespace osu.Game.Database
|
||||
return item.ToEntityFrameworkLive();
|
||||
}, cancellationToken, TaskCreationOptions.HideScheduler, lowPriority ? import_scheduler_low_priority : import_scheduler).Unwrap().ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to a legacy (.zip based) package.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to export.</param>
|
||||
public void Export(TModel item)
|
||||
{
|
||||
var retrievedItem = ModelStore.ConsumableItems.FirstOrDefault(s => s.ID == item.ID);
|
||||
|
||||
if (retrievedItem == null)
|
||||
throw new ArgumentException(@"Specified model could not be found", nameof(item));
|
||||
|
||||
string filename = $"{GetValidFilename(item.ToString())}{HandledExtensions.First()}";
|
||||
|
||||
using (var stream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create))
|
||||
ExportModelTo(retrievedItem, stream);
|
||||
|
||||
exportStorage.PresentFileExternally(filename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to the given output stream.
|
||||
/// </summary>
|
||||
/// <param name="model">The item to export.</param>
|
||||
/// <param name="outputStream">The output stream to export to.</param>
|
||||
public virtual void ExportModelTo(TModel model, Stream outputStream)
|
||||
{
|
||||
using (var archive = ZipArchive.Create())
|
||||
{
|
||||
foreach (var file in model.Files)
|
||||
archive.AddEntry(file.Filename, Files.Storage.GetStream(file.FileInfo.GetStoragePath()));
|
||||
|
||||
archive.SaveTo(outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replace an existing file with a new version.
|
||||
/// </summary>
|
||||
@ -875,18 +835,5 @@ namespace osu.Game.Database
|
||||
// this doesn't follow the SHA2 hashing schema intentionally, so such entries on the data store can be identified.
|
||||
return Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
private readonly char[] invalidFilenameCharacters = Path.GetInvalidFileNameChars()
|
||||
// Backslash is added to avoid issues when exporting to zip.
|
||||
// See SharpCompress filename normalisation https://github.com/adamhathcock/sharpcompress/blob/a1e7c0068db814c9aa78d86a94ccd1c761af74bd/src/SharpCompress/Writers/Zip/ZipWriter.cs#L143.
|
||||
.Append('\\')
|
||||
.ToArray();
|
||||
|
||||
protected string GetValidFilename(string filename)
|
||||
{
|
||||
foreach (char c in invalidFilenameCharacters)
|
||||
filename = filename.Replace(c, '_');
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -24,19 +23,6 @@ namespace osu.Game.Database
|
||||
/// </summary>
|
||||
event Action<TModel> ItemRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to a legacy (.zip based) package.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to export.</param>
|
||||
void Export(TModel item);
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to the given output stream.
|
||||
/// </summary>
|
||||
/// <param name="model">The item to export.</param>
|
||||
/// <param name="outputStream">The output stream to export to.</param>
|
||||
void ExportModelTo(TModel model, Stream outputStream);
|
||||
|
||||
/// <summary>
|
||||
/// Perform an update of the specified item.
|
||||
/// TODO: Support file additions/removals.
|
||||
|
18
osu.Game/Database/LegacyBeatmapExporter.cs
Normal file
18
osu.Game/Database/LegacyBeatmapExporter.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class LegacyBeatmapExporter : LegacyExporter<BeatmapSetInfo>
|
||||
{
|
||||
protected override string FileExtension => ".osz";
|
||||
|
||||
public LegacyBeatmapExporter(Storage storage, IModelManager<BeatmapSetInfo> manager)
|
||||
: base(storage, manager)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
66
osu.Game/Database/LegacyExporter.cs
Normal file
66
osu.Game/Database/LegacyExporter.cs
Normal file
@ -0,0 +1,66 @@
|
||||
// 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.IO;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Extensions;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// A class which handles exporting legacy user data of a single type from osu-stable.
|
||||
/// </summary>
|
||||
public abstract class LegacyExporter<TModel>
|
||||
where TModel : class, IHasNamedFiles
|
||||
{
|
||||
/// <summary>
|
||||
/// The file extension for exports (including the leading '.').
|
||||
/// </summary>
|
||||
protected abstract string FileExtension { get; }
|
||||
|
||||
protected readonly IModelManager<TModel> Manager;
|
||||
|
||||
protected readonly Storage UserFileStorage;
|
||||
|
||||
private readonly Storage exportStorage;
|
||||
|
||||
protected LegacyExporter(Storage storage, IModelManager<TModel> manager)
|
||||
{
|
||||
Manager = manager;
|
||||
|
||||
exportStorage = storage.GetStorageForDirectory(@"exports");
|
||||
UserFileStorage = storage.GetStorageForDirectory(@"files");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to a legacy (.zip based) package.
|
||||
/// </summary>
|
||||
/// <param name="item">The item to export.</param>
|
||||
public void Export(TModel item)
|
||||
{
|
||||
string filename = $"{item.ToString().GetValidArchiveContentFilename()}{FileExtension}";
|
||||
|
||||
using (var stream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create))
|
||||
ExportModelTo(item, stream);
|
||||
|
||||
exportStorage.PresentFileExternally(filename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports an item to the given output stream.
|
||||
/// </summary>
|
||||
/// <param name="model">The item to export.</param>
|
||||
/// <param name="outputStream">The output stream to export to.</param>
|
||||
public virtual void ExportModelTo(TModel model, Stream outputStream)
|
||||
{
|
||||
using (var archive = ZipArchive.Create())
|
||||
{
|
||||
foreach (var file in model.Files)
|
||||
archive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath()));
|
||||
|
||||
archive.SaveTo(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
osu.Game/Database/LegacyScoreExporter.cs
Normal file
31
osu.Game/Database/LegacyScoreExporter.cs
Normal file
@ -0,0 +1,31 @@
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class LegacyScoreExporter : LegacyExporter<ScoreInfo>
|
||||
{
|
||||
protected override string FileExtension => ".osr";
|
||||
|
||||
public LegacyScoreExporter(Storage storage, IModelManager<ScoreInfo> manager)
|
||||
: base(storage, manager)
|
||||
{
|
||||
}
|
||||
|
||||
public override void ExportModelTo(ScoreInfo model, Stream outputStream)
|
||||
{
|
||||
var file = model.Files.SingleOrDefault();
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
using (var inputStream = UserFileStorage.GetStream(file.FileInfo.GetStoragePath()))
|
||||
inputStream.CopyTo(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
18
osu.Game/Database/LegacySkinExporter.cs
Normal file
18
osu.Game/Database/LegacySkinExporter.cs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 osu.Framework.Platform;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public class LegacySkinExporter : LegacyExporter<SkinInfo>
|
||||
{
|
||||
protected override string FileExtension => ".osk";
|
||||
|
||||
public LegacySkinExporter(Storage storage, IModelManager<SkinInfo> manager)
|
||||
: base(storage, manager)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@ -66,6 +68,9 @@ namespace osu.Game.Online.Leaderboards
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Storage storage { get; set; }
|
||||
|
||||
public LeaderboardScore(ScoreInfo score, int? rank, bool allowHighlight = true)
|
||||
{
|
||||
Score = score;
|
||||
@ -395,7 +400,7 @@ namespace osu.Game.Online.Leaderboards
|
||||
items.Add(new OsuMenuItem("Use these mods", MenuItemType.Highlighted, () => songSelect.Mods.Value = Score.Mods));
|
||||
|
||||
if (Score.Files.Count > 0)
|
||||
items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => scoreManager.Export(Score)));
|
||||
items.Add(new OsuMenuItem("Export", MenuItemType.Standard, () => new LegacyScoreExporter(storage, scoreManager).Export(Score)));
|
||||
|
||||
if (Score.ID != 0)
|
||||
items.Add(new OsuMenuItem("Delete", MenuItemType.Destructive, () => dialogOverlay?.Push(new LocalScoreDeleteDialog(Score))));
|
||||
|
@ -11,7 +11,9 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Skinning;
|
||||
@ -167,6 +169,9 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
[Resolved]
|
||||
private SkinManager skins { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Storage storage { get; set; }
|
||||
|
||||
private Bindable<Skin> currentSkin;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -183,7 +188,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
try
|
||||
{
|
||||
skins.Export(currentSkin.Value.SkinInfo);
|
||||
new LegacySkinExporter(storage, skins).Export(currentSkin.Value.SkinInfo);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -262,16 +262,6 @@ namespace osu.Game.Scoring
|
||||
remove => scoreModelManager.ItemRemoved -= value;
|
||||
}
|
||||
|
||||
public void Export(ScoreInfo item)
|
||||
{
|
||||
scoreModelManager.Export(item);
|
||||
}
|
||||
|
||||
public void ExportModelTo(ScoreInfo model, Stream outputStream)
|
||||
{
|
||||
scoreModelManager.ExportModelTo(model, outputStream);
|
||||
}
|
||||
|
||||
public void Update(ScoreInfo item)
|
||||
{
|
||||
scoreModelManager.Update(item);
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
@ -13,7 +12,6 @@ using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.IO.Archives;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
@ -69,15 +67,5 @@ namespace osu.Game.Scoring
|
||||
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
|
||||
=> base.CheckLocalAvailability(model, items)
|
||||
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
|
||||
|
||||
public override void ExportModelTo(ScoreInfo model, Stream outputStream)
|
||||
{
|
||||
var file = model.Files.SingleOrDefault();
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
using (var inputStream = Files.Storage.GetStream(file.FileInfo.GetStoragePath()))
|
||||
inputStream.CopyTo(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,11 @@ using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -63,6 +65,9 @@ namespace osu.Game.Screens.Edit
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private Storage storage { get; set; }
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private DialogOverlay dialogOverlay { get; set; }
|
||||
|
||||
@ -753,7 +758,7 @@ namespace osu.Game.Screens.Edit
|
||||
private void exportBeatmap()
|
||||
{
|
||||
Save();
|
||||
beatmapManager.Export(Beatmap.Value.BeatmapSetInfo);
|
||||
new LegacyBeatmapExporter(storage, beatmapManager).Export(Beatmap.Value.BeatmapSetInfo);
|
||||
}
|
||||
|
||||
private void updateLastSavedHash()
|
||||
|
@ -301,16 +301,6 @@ namespace osu.Game.Skinning
|
||||
remove => skinModelManager.ItemRemoved -= value;
|
||||
}
|
||||
|
||||
public void Export(SkinInfo item)
|
||||
{
|
||||
skinModelManager.Export(item);
|
||||
}
|
||||
|
||||
public void ExportModelTo(SkinInfo model, Stream outputStream)
|
||||
{
|
||||
skinModelManager.ExportModelTo(model, outputStream);
|
||||
}
|
||||
|
||||
public void Update(SkinInfo item)
|
||||
{
|
||||
skinModelManager.Update(item);
|
||||
|
Loading…
Reference in New Issue
Block a user