Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up ImportTask / ArchiveReader implementations #24807

Merged
merged 7 commits into from
Sep 14, 2023
2 changes: 1 addition & 1 deletion osu.Game/Beatmaps/BeatmapImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ private DateTimeOffset getDateAdded(ArchiveReader? reader)
{
DateTimeOffset dateAdded = DateTimeOffset.UtcNow;

if (reader is LegacyDirectoryArchiveReader legacyReader)
if (reader is DirectoryArchiveReader legacyReader)
{
var beatmaps = reader.Filenames.Where(f => f.EndsWith(".osu", StringComparison.OrdinalIgnoreCase));

Expand Down
60 changes: 21 additions & 39 deletions osu.Game/Database/ImportTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,55 +46,37 @@ public ImportTask(Stream stream, string filename)
/// </summary>
public ArchiveReader GetReader()
{
return Stream != null
? getReaderFrom(Stream)
: getReaderFrom(Path);
}
if (Stream == null)
{
if (ZipUtils.IsZipArchive(Path))
return new ZipArchiveReader(File.Open(Path, FileMode.Open, FileAccess.Read, FileShare.Read), System.IO.Path.GetFileName(Path));
if (Directory.Exists(Path))
return new DirectoryArchiveReader(Path);
if (File.Exists(Path))
return new SingleFileArchiveReader(Path);

/// <summary>
/// Deletes the file that is encapsulated by this <see cref="ImportTask"/>.
/// </summary>
public virtual void DeleteFile()
{
if (File.Exists(Path))
File.Delete(Path);
}
throw new InvalidFormatException($"{Path} is not a valid archive");
}

/// <summary>
/// Creates an <see cref="ArchiveReader"/> from a stream.
/// </summary>
/// <param name="stream">A seekable stream containing the archive content.</param>
/// <returns>A reader giving access to the archive's content.</returns>
private ArchiveReader getReaderFrom(Stream stream)
{
if (!(stream is MemoryStream memoryStream))
if (Stream is MemoryStream memoryStream)
{
// This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out).
memoryStream = new MemoryStream(stream.ReadAllBytesToArray());
stream.Dispose();
}
if (ZipUtils.IsZipArchive(memoryStream))
return new ZipArchiveReader(memoryStream, Path);

if (ZipUtils.IsZipArchive(memoryStream))
return new ZipArchiveReader(memoryStream, Path);
return new MemoryStreamArchiveReader(memoryStream, Path);
bdach marked this conversation as resolved.
Show resolved Hide resolved
}

return new LegacyByteArrayReader(memoryStream.ToArray(), Path);
// This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out).
return new ByteArrayArchiveReader(Stream.ReadAllBytesToArray(), Path);
}

/// <summary>
/// Creates an <see cref="ArchiveReader"/> from a valid storage path.
/// Deletes the file that is encapsulated by this <see cref="ImportTask"/>.
/// </summary>
/// <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)
public virtual void DeleteFile()
{
if (ZipUtils.IsZipArchive(path))
return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), System.IO.Path.GetFileName(path));
if (Directory.Exists(path))
return new LegacyDirectoryArchiveReader(path);
if (File.Exists(path))
return new LegacyFileArchiveReader(path);

throw new InvalidFormatException($"{path} is not a valid archive");
if (File.Exists(Path))
File.Delete(Path);
}

public override string ToString() => System.IO.Path.GetFileName(Path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ namespace osu.Game.IO.Archives
/// <summary>
/// Allows reading a single file from the provided byte array.
/// </summary>
public class LegacyByteArrayReader : ArchiveReader
public class ByteArrayArchiveReader : ArchiveReader
{
private readonly byte[] content;

public LegacyByteArrayReader(byte[] content, string filename)
public ByteArrayArchiveReader(byte[] content, string filename)
: base(filename)
{
this.content = content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
namespace osu.Game.IO.Archives
{
/// <summary>
/// Reads an archive from a directory on disk.
/// Reads an archive directly from a directory on disk.
/// </summary>
public class LegacyDirectoryArchiveReader : ArchiveReader
public class DirectoryArchiveReader : ArchiveReader
{
private readonly string path;

public LegacyDirectoryArchiveReader(string path)
public DirectoryArchiveReader(string path)
: base(Path.GetFileName(path))
{
// re-get full path to standardise with Directory.GetFiles return values below.
Expand Down
30 changes: 30 additions & 0 deletions osu.Game/IO/Archives/MemoryStreamArchiveReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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.Collections.Generic;
using System.IO;

namespace osu.Game.IO.Archives
{
/// <summary>
/// Allows reading a single file from the provided memory stream.
/// </summary>
public class MemoryStreamArchiveReader : ArchiveReader
{
private readonly MemoryStream stream;

public MemoryStreamArchiveReader(MemoryStream stream, string filename)
: base(filename)
{
this.stream = stream;
}

public override Stream GetStream(string name) => new MemoryStream(stream.GetBuffer(), 0, (int)stream.Length);

public override void Dispose()
{
}

public override IEnumerable<string> Filenames => new[] { Name };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
namespace osu.Game.IO.Archives
{
/// <summary>
/// Reads a file on disk as an archive.
/// Reads a single file on disk as an archive.
/// Note: In this case, the file is not an extractable archive, use <see cref="ZipArchiveReader"/> instead.
/// </summary>
public class LegacyFileArchiveReader : ArchiveReader
public class SingleFileArchiveReader : ArchiveReader
{
private readonly string path;

public LegacyFileArchiveReader(string path)
public SingleFileArchiveReader(string path)
: base(Path.GetFileName(path))
{
// re-get full path to standardise
Expand Down
4 changes: 2 additions & 2 deletions osu.Game/Screens/Play/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1144,14 +1144,14 @@ protected virtual Task ImportScore(Score score)
if (DrawableRuleset.ReplayScore != null)
return Task.CompletedTask;

LegacyByteArrayReader replayReader = null;
ByteArrayArchiveReader replayReader = null;

if (score.ScoreInfo.Ruleset.IsLegacyRuleset())
{
using (var stream = new MemoryStream())
{
new LegacyScoreEncoder(score, GameplayState.Beatmap).Encode(stream);
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr");
replayReader = new ByteArrayArchiveReader(stream.ToArray(), "replay.osr");
}
}

Expand Down