mirror of
https://github.com/ppy/osu.git
synced 2024-11-13 22:47:26 +08:00
Merge pull request #1075 from peppy/import-from-stable-part-two
Tidy up osu-stable import process
This commit is contained in:
commit
d72a479d9d
@ -1 +1 @@
|
|||||||
Subproject commit 2204764944ff693e857649253547054cc91764a0
|
Subproject commit 96daf2053a8a19fe221fef2557674ca5bee808fb
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@ -11,6 +12,7 @@ using System.Reflection;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Win32;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
|
|
||||||
@ -30,6 +32,58 @@ namespace osu.Desktop
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Storage GetStorageForStableInstall()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new StableStorage();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A method of accessing an osu-stable install in a controlled fashion.
|
||||||
|
/// </summary>
|
||||||
|
private class StableStorage : DesktopStorage
|
||||||
|
{
|
||||||
|
protected override string LocateBasePath()
|
||||||
|
{
|
||||||
|
Func<string, bool> checkExists = p => Directory.Exists(Path.Combine(p, "Songs"));
|
||||||
|
|
||||||
|
string stableInstallPath;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu"))
|
||||||
|
stableInstallPath = key?.OpenSubKey(@"shell\open\command")?.GetValue(String.Empty).ToString().Split('"')[1].Replace("osu!.exe", "");
|
||||||
|
|
||||||
|
if (checkExists(stableInstallPath))
|
||||||
|
return stableInstallPath;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
|
||||||
|
if (checkExists(stableInstallPath))
|
||||||
|
return stableInstallPath;
|
||||||
|
|
||||||
|
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu");
|
||||||
|
if (checkExists(stableInstallPath))
|
||||||
|
return stableInstallPath;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StableStorage()
|
||||||
|
: base(string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -47,6 +47,8 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
private readonly FileStore files;
|
private readonly FileStore files;
|
||||||
|
|
||||||
|
private readonly SQLiteConnection connection;
|
||||||
|
|
||||||
private readonly RulesetStore rulesets;
|
private readonly RulesetStore rulesets;
|
||||||
|
|
||||||
private readonly BeatmapStore beatmaps;
|
private readonly BeatmapStore beatmaps;
|
||||||
@ -59,6 +61,11 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<Notification> PostNotification { private get; set; }
|
public Action<Notification> PostNotification { private get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set a storage with access to an osu-stable install for import purposes.
|
||||||
|
/// </summary>
|
||||||
|
public Func<Storage> GetStableStorage { private get; set; }
|
||||||
|
|
||||||
public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null)
|
public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null)
|
||||||
{
|
{
|
||||||
beatmaps = new BeatmapStore(connection);
|
beatmaps = new BeatmapStore(connection);
|
||||||
@ -67,6 +74,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
|
this.connection = connection;
|
||||||
this.rulesets = rulesets;
|
this.rulesets = rulesets;
|
||||||
|
|
||||||
if (importHost != null)
|
if (importHost != null)
|
||||||
@ -136,13 +144,13 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <param name="archiveReader">The beatmap to be imported.</param>
|
/// <param name="archiveReader">The beatmap to be imported.</param>
|
||||||
public BeatmapSetInfo Import(ArchiveReader archiveReader)
|
public BeatmapSetInfo Import(ArchiveReader archiveReader)
|
||||||
{
|
{
|
||||||
|
BeatmapSetInfo set = null;
|
||||||
|
|
||||||
// let's only allow one concurrent import at a time for now.
|
// let's only allow one concurrent import at a time for now.
|
||||||
lock (importLock)
|
lock (importLock)
|
||||||
{
|
connection.RunInTransaction(() => Import(set = importToStorage(archiveReader)));
|
||||||
BeatmapSetInfo set = importToStorage(archiveReader);
|
|
||||||
Import(set);
|
return set;
|
||||||
return set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -169,7 +177,7 @@ namespace osu.Game.Beatmaps
|
|||||||
if (!beatmaps.Delete(beatmapSet)) return;
|
if (!beatmaps.Delete(beatmapSet)) return;
|
||||||
|
|
||||||
if (!beatmapSet.Protected)
|
if (!beatmapSet.Protected)
|
||||||
files.Dereference(beatmapSet.Files.Select(f => f.FileInfo));
|
files.Dereference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -183,7 +191,7 @@ namespace osu.Game.Beatmaps
|
|||||||
if (!beatmaps.Undelete(beatmapSet)) return;
|
if (!beatmaps.Undelete(beatmapSet)) return;
|
||||||
|
|
||||||
if (!beatmapSet.Protected)
|
if (!beatmapSet.Protected)
|
||||||
files.Reference(beatmapSet.Files.Select(f => f.FileInfo));
|
files.Reference(beatmapSet.Files.Select(f => f.FileInfo).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -451,19 +459,20 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future.
|
||||||
|
/// </summary>
|
||||||
public void ImportFromStable()
|
public void ImportFromStable()
|
||||||
{
|
{
|
||||||
string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!", "Songs");
|
var stable = GetStableStorage?.Invoke();
|
||||||
if (!Directory.Exists(stableInstallPath))
|
|
||||||
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu", "Songs");
|
|
||||||
|
|
||||||
if (!Directory.Exists(stableInstallPath))
|
if (stable == null)
|
||||||
{
|
{
|
||||||
Logger.Log("Couldn't find an osu!stable installation!", LoggingTarget.Information, LogLevel.Error);
|
Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Import(Directory.GetDirectories(stableInstallPath));
|
Import(stable.GetDirectories("Songs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteAll()
|
public void DeleteAll()
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Logging;
|
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using SQLite.Net;
|
using SQLite.Net;
|
||||||
using SQLiteNetExtensions.Extensions;
|
using SQLiteNetExtensions.Extensions;
|
||||||
@ -130,23 +129,11 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
private void cleanupPendingDeletions()
|
private void cleanupPendingDeletions()
|
||||||
{
|
{
|
||||||
foreach (var b in QueryAndPopulate<BeatmapSetInfo>(b => b.DeletePending && !b.Protected))
|
Connection.RunInTransaction(() =>
|
||||||
{
|
{
|
||||||
try
|
foreach (var b in QueryAndPopulate<BeatmapSetInfo>(b => b.DeletePending && !b.Protected))
|
||||||
{
|
|
||||||
// many-to-many join table entries are not automatically tidied.
|
|
||||||
Connection.Table<BeatmapSetFileInfo>().Delete(f => f.BeatmapSetInfoID == b.ID);
|
|
||||||
Connection.Delete(b, true);
|
Connection.Delete(b, true);
|
||||||
}
|
});
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Error(e, $@"Could not delete beatmap {b}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//this is required because sqlite migrations don't work, initially inserting nulls into this field.
|
|
||||||
//see https://github.com/praeclarum/sqlite-net/issues/326
|
|
||||||
Connection.Query<BeatmapSetInfo>("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
var storeName = GetType().Name;
|
var storeName = GetType().Name;
|
||||||
|
|
||||||
var reportedVersion = Connection.Table<StoreVersion>().FirstOrDefault(s => s.StoreName == storeName) ?? new StoreVersion
|
var reportedVersion = Connection.Table<StoreVersion>().Where(s => s.StoreName == storeName).FirstOrDefault() ?? new StoreVersion
|
||||||
{
|
{
|
||||||
StoreName = storeName,
|
StoreName = storeName,
|
||||||
Version = 0
|
Version = 0
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
@ -83,10 +82,9 @@ namespace osu.Game.IO
|
|||||||
{
|
{
|
||||||
string hash = data.ComputeSHA2Hash();
|
string hash = data.ComputeSHA2Hash();
|
||||||
|
|
||||||
var info = new FileInfo { Hash = hash };
|
var existing = Connection.Table<FileInfo>().Where(f => f.Hash == hash).FirstOrDefault();
|
||||||
|
|
||||||
var existing = Connection.Table<FileInfo>().FirstOrDefault(f => f.Hash == info.Hash);
|
|
||||||
|
|
||||||
|
var info = existing ?? new FileInfo { Hash = hash };
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
info = existing;
|
info = existing;
|
||||||
@ -106,11 +104,11 @@ namespace osu.Game.IO
|
|||||||
Connection.Insert(info);
|
Connection.Insert(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference(new[] { info });
|
Reference(info);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reference(IEnumerable<FileInfo> files)
|
public void Reference(params FileInfo[] files)
|
||||||
{
|
{
|
||||||
Connection.RunInTransaction(() =>
|
Connection.RunInTransaction(() =>
|
||||||
{
|
{
|
||||||
@ -125,7 +123,7 @@ namespace osu.Game.IO
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dereference(IEnumerable<FileInfo> files)
|
public void Dereference(params FileInfo[] files)
|
||||||
{
|
{
|
||||||
Connection.RunInTransaction(() =>
|
Connection.RunInTransaction(() =>
|
||||||
{
|
{
|
||||||
@ -142,18 +140,21 @@ namespace osu.Game.IO
|
|||||||
|
|
||||||
private void deletePending()
|
private void deletePending()
|
||||||
{
|
{
|
||||||
foreach (var f in QueryAndPopulate<FileInfo>(f => f.ReferenceCount < 1))
|
Connection.RunInTransaction(() =>
|
||||||
{
|
{
|
||||||
try
|
foreach (var f in Query<FileInfo>(f => f.ReferenceCount < 1))
|
||||||
{
|
{
|
||||||
Connection.Delete(f);
|
try
|
||||||
Storage.Delete(Path.Combine(prefix, f.StoragePath));
|
{
|
||||||
|
Storage.Delete(Path.Combine(prefix, f.StoragePath));
|
||||||
|
Connection.Delete(f);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Error(e, $@"Could not delete beatmap {f}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
});
|
||||||
{
|
|
||||||
Logger.Error(e, $@"Could not delete beatmap {f}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ using osu.Game.Screens.Menu;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -47,6 +48,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
private UserProfileOverlay userProfile;
|
private UserProfileOverlay userProfile;
|
||||||
|
|
||||||
|
public virtual Storage GetStorageForStableInstall() => null;
|
||||||
|
|
||||||
private Intro intro
|
private Intro intro
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -151,6 +154,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
// hook up notifications to components.
|
// hook up notifications to components.
|
||||||
BeatmapManager.PostNotification = n => notificationOverlay?.Post(n);
|
BeatmapManager.PostNotification = n => notificationOverlay?.Post(n);
|
||||||
|
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||||
|
|
||||||
AddRange(new Drawable[] {
|
AddRange(new Drawable[] {
|
||||||
new VolumeControlReceptor
|
new VolumeControlReceptor
|
||||||
|
@ -62,7 +62,7 @@ namespace osu.Game.Rulesets
|
|||||||
{
|
{
|
||||||
var us = createRulesetInfo(r);
|
var us = createRulesetInfo(r);
|
||||||
|
|
||||||
var existing = Query<RulesetInfo>().FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo);
|
var existing = Query<RulesetInfo>().Where(ri => ri.InstantiationInfo == us.InstantiationInfo).FirstOrDefault();
|
||||||
|
|
||||||
if (existing == null)
|
if (existing == null)
|
||||||
Connection.Insert(us);
|
Connection.Insert(us);
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToAny/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToAny/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToCount/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToCount/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirst/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirst/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToFirstOrDefault/@EntryIndexedValue">HINT</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLast/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLast/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLastOrDefault/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToLastOrDefault/@EntryIndexedValue">WARNING</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingle/@EntryIndexedValue">WARNING</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ReplaceWithSingleCallToSingle/@EntryIndexedValue">WARNING</s:String>
|
||||||
|
Loading…
Reference in New Issue
Block a user