diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 84635af39a..90d1aa542f 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.IO; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -40,8 +41,16 @@ namespace osu.Game.Tests.Beatmaps.IO using (HeadlessGameHost host = new HeadlessGameHost()) { var osu = loadOsu(host); - osu.Dependencies.Get().Import(osz_path); + + var temp = prepareTempCopy(osz_path); + + Assert.IsTrue(File.Exists(temp)); + + osu.Dependencies.Get().Import(temp); + ensureLoaded(osu); + + Assert.IsFalse(File.Exists(temp)); } } @@ -56,14 +65,51 @@ namespace osu.Game.Tests.Beatmaps.IO var osu = loadOsu(host); + var temp = prepareTempCopy(osz_path); + + Assert.IsTrue(File.Exists(temp)); + var importer = new BeatmapImporter(client); - if (!importer.ImportAsync(osz_path).Wait(1000)) + if (!importer.ImportAsync(temp).Wait(1000)) Assert.Fail(@"IPC took too long to send"); ensureLoaded(osu); + + Assert.IsFalse(File.Exists(temp)); } } + [Test] + public void TestImportWhenFileOpen() + { + //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. + using (HeadlessGameHost host = new HeadlessGameHost()) + { + var osu = loadOsu(host); + + var temp = prepareTempCopy(osz_path); + + Assert.IsTrue(File.Exists(temp)); + + using (FileStream stream = File.OpenRead(temp)) + osu.Dependencies.Get().Import(temp); + + ensureLoaded(osu); + + Assert.IsTrue(File.Exists(temp)); + + File.Delete(temp); + + Assert.IsFalse(File.Exists(temp)); + } + } + + private string prepareTempCopy(string path) + { + var temp = Path.GetTempFileName(); + return new FileInfo(osz_path).CopyTo(temp, true).FullName; + } + private OsuGameBase loadOsu(GameHost host) { var osu = new OsuGameBase(); diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index fc2c7558b0..03f904b7e8 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -116,13 +116,61 @@ namespace osu.Game.Database connection.DeleteAll(); } + /// + /// Import multiple from . + /// + /// Multiple locations on disk public void Import(IEnumerable paths) { + Stack sets = new Stack(); + foreach (string p in paths) - Import(p); + try + { + BeatmapSetInfo set = getBeatmapSet(p); + + //If we have an ID then we already exist in the database. + if (set.ID == 0) + sets.Push(set); + + // We may or may not want to delete the file depending on where it is stored. + // e.g. reconstructing/repairing database with beatmaps from default storage. + // Also, not always a single file, i.e. for LegacyFilesystemReader + // TODO: Add a check to prevent files from storage to be deleted. + try + { + File.Delete(p); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete file at {p}"); + } + } + catch (Exception e) + { + e = e.InnerException ?? e; + Logger.Error(e, $@"Could not import beatmap set"); + } + + // Batch commit with multiple sets to database + Import(sets); } + /// + /// Import from . + /// + /// Location on disk public void Import(string path) + { + Import(new [] { path }); + } + + /// + /// Duplicates content from to storage and returns a representing . + /// + /// Content location + /// + private BeatmapSetInfo getBeatmapSet(string path) { string hash = null; @@ -156,7 +204,7 @@ namespace osu.Game.Database BeatmapSetAdded?.Invoke(existing); } - return; + return existing; } var beatmapSet = new BeatmapSetInfo @@ -172,7 +220,6 @@ namespace osu.Game.Database { string[] mapNames = reader.BeatmapFilenames; foreach (var name in mapNames) - { using (var stream = new StreamReader(reader.GetStream(name))) { var decoder = BeatmapDecoder.GetDecoder(stream); @@ -184,11 +231,10 @@ namespace osu.Game.Database beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } - beatmapSet.StoryboardFile = reader.StoryboardFilename; - } + beatmapSet.StoryboardFile = reader.StoryboardFilename; } - Import(new[] { beatmapSet }); + return beatmapSet; } public void Import(IEnumerable beatmapSets)