mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
use extension where appropriate with more fixes
This commit is contained in:
@@ -42,4 +42,9 @@ public class GZipEntry : Entry
|
||||
{
|
||||
yield return new GZipEntry(GZipFilePart.Create(stream, options.ArchiveEncoding));
|
||||
}
|
||||
|
||||
internal static async IAsyncEnumerable<GZipEntry> GetEntriesAsync(Stream stream, OptionsBase options)
|
||||
{
|
||||
yield return new GZipEntry(await GZipFilePart.CreateAsync(stream, options.ArchiveEncoding));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,12 @@ internal sealed class GZipFilePart : FilePart
|
||||
internal override string? FilePartName => _name;
|
||||
|
||||
internal override Stream GetCompressedStream() =>
|
||||
new DeflateStream(_stream, CompressionMode.Decompress, CompressionLevel.Default);
|
||||
new DeflateStream(
|
||||
_stream,
|
||||
CompressionMode.Decompress,
|
||||
CompressionLevel.Default,
|
||||
leaveOpen: true
|
||||
);
|
||||
|
||||
internal override Stream GetRawStream() => _stream;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace SharpCompress.Common;
|
||||
|
||||
public interface IVolume : IDisposable
|
||||
public interface IVolume : IDisposable, IAsyncDisposable
|
||||
{
|
||||
int Index { get; }
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Common;
|
||||
|
||||
public abstract class Volume : IVolume
|
||||
public abstract class Volume : IVolume, IAsyncDisposable
|
||||
{
|
||||
private readonly Stream _baseStream;
|
||||
private readonly Stream _actualStream;
|
||||
@@ -58,4 +59,14 @@ public abstract class Volume : IVolume
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public virtual async ValueTask DisposeAsync()
|
||||
{
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
await Task.Run(() => _actualStream.Dispose()).ConfigureAwait(false);
|
||||
#else
|
||||
await _actualStream.DisposeAsync().ConfigureAwait(false);
|
||||
#endif
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,19 +57,31 @@ public class DeflateStream : Stream, IStreamStack
|
||||
|
||||
private readonly ZlibBaseStream _baseStream;
|
||||
private bool _disposed;
|
||||
private readonly bool _leaveOpen;
|
||||
|
||||
public DeflateStream(
|
||||
Stream stream,
|
||||
CompressionMode mode,
|
||||
CompressionLevel level = CompressionLevel.Default,
|
||||
Encoding? forceEncoding = null
|
||||
)
|
||||
: this(stream, mode, level, leaveOpen: false, forceEncoding) { }
|
||||
|
||||
public DeflateStream(
|
||||
Stream stream,
|
||||
CompressionMode mode,
|
||||
CompressionLevel level,
|
||||
bool leaveOpen,
|
||||
Encoding? forceEncoding = null
|
||||
)
|
||||
{
|
||||
_leaveOpen = leaveOpen;
|
||||
_baseStream = new ZlibBaseStream(
|
||||
stream,
|
||||
mode,
|
||||
level,
|
||||
ZlibStreamFlavor.DEFLATE,
|
||||
leaveOpen,
|
||||
forceEncoding
|
||||
);
|
||||
|
||||
@@ -265,7 +277,7 @@ public class DeflateStream : Stream, IStreamStack
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(DeflateStream));
|
||||
#endif
|
||||
if (disposing)
|
||||
if (disposing && !_leaveOpen)
|
||||
{
|
||||
_baseStream?.Dispose();
|
||||
}
|
||||
@@ -286,7 +298,10 @@ public class DeflateStream : Stream, IStreamStack
|
||||
#if DEBUG_STREAMS
|
||||
this.DebugDispose(typeof(DeflateStream));
|
||||
#endif
|
||||
await _baseStream.DisposeAsync().ConfigureAwait(false);
|
||||
if (!_leaveOpen)
|
||||
{
|
||||
await _baseStream.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
await base.DisposeAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -89,6 +89,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
protected internal int _gzipHeaderByteCount;
|
||||
|
||||
private readonly Encoding _encoding;
|
||||
private readonly bool _leaveOpen;
|
||||
|
||||
internal int Crc32 => crc?.Crc32Result ?? 0;
|
||||
|
||||
@@ -98,9 +99,20 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
CompressionLevel level,
|
||||
ZlibStreamFlavor flavor,
|
||||
Encoding encoding
|
||||
)
|
||||
: this(stream, compressionMode, level, flavor, leaveOpen: false, encoding) { }
|
||||
|
||||
public ZlibBaseStream(
|
||||
Stream stream,
|
||||
CompressionMode compressionMode,
|
||||
CompressionLevel level,
|
||||
ZlibStreamFlavor flavor,
|
||||
bool leaveOpen,
|
||||
Encoding encoding
|
||||
)
|
||||
{
|
||||
_flushMode = FlushType.None;
|
||||
_leaveOpen = leaveOpen;
|
||||
|
||||
//this._workingBuffer = new byte[WORKING_BUFFER_SIZE_DEFAULT];
|
||||
_stream = stream;
|
||||
@@ -546,7 +558,10 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
finally
|
||||
{
|
||||
end();
|
||||
_stream?.Dispose();
|
||||
if (!_leaveOpen)
|
||||
{
|
||||
_stream?.Dispose();
|
||||
}
|
||||
_stream = null;
|
||||
}
|
||||
}
|
||||
@@ -577,7 +592,10 @@ internal class ZlibBaseStream : Stream, IStreamStack
|
||||
end();
|
||||
if (_stream != null)
|
||||
{
|
||||
await _stream.DisposeAsync().ConfigureAwait(false);
|
||||
if (!_leaveOpen)
|
||||
{
|
||||
await _stream.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
_stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ public abstract class Factory : IFactory
|
||||
{
|
||||
RegisterFactory(new ZipFactory());
|
||||
RegisterFactory(new RarFactory());
|
||||
RegisterFactory(new SevenZipFactory());
|
||||
RegisterFactory(new TarFactory());//put tar before most
|
||||
RegisterFactory(new GZipFactory());
|
||||
RegisterFactory(new TarFactory());
|
||||
RegisterFactory(new ArcFactory());
|
||||
RegisterFactory(new ArjFactory());
|
||||
RegisterFactory(new AceFactory());
|
||||
RegisterFactory(new SevenZipFactory());
|
||||
}
|
||||
|
||||
private static readonly HashSet<Factory> _factories = new();
|
||||
|
||||
@@ -67,7 +67,16 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IAsyncReader
|
||||
{
|
||||
await _entriesForCurrentReadStreamAsync.DisposeAsync();
|
||||
}
|
||||
Volume?.Dispose();
|
||||
|
||||
// If Volume implements IAsyncDisposable, use async disposal
|
||||
if (Volume is IAsyncDisposable asyncDisposable)
|
||||
{
|
||||
await asyncDisposable.DisposeAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
Volume?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -21,6 +21,11 @@ public partial class GZipReader : AbstractReader<GZipEntry, GZipVolume>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
return new GZipReader(stream, options ?? new ReaderOptions());
|
||||
}
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? options = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
return new GZipReader(stream, options ?? new ReaderOptions());
|
||||
@@ -30,4 +35,7 @@ public partial class GZipReader : AbstractReader<GZipEntry, GZipVolume>
|
||||
|
||||
protected override IEnumerable<GZipEntry> GetEntries(Stream stream) =>
|
||||
GZipEntry.GetEntries(stream, Options);
|
||||
protected override IAsyncEnumerable<GZipEntry> GetEntriesAsync(Stream stream) {
|
||||
return GZipEntry.GetEntriesAsync(stream, Options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AwesomeAssertions;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
@@ -90,6 +91,7 @@ public class ArchiveTests : ReaderTests
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveStreamRead(
|
||||
ArchiveFactory.FindFactory<IArchiveFactory>(testArchive),
|
||||
Path.GetExtension(testArchive).Substring(1),
|
||||
readerOptions,
|
||||
testArchive
|
||||
);
|
||||
@@ -102,36 +104,43 @@ public class ArchiveTests : ReaderTests
|
||||
)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveStreamRead(archiveFactory, readerOptions, testArchive);
|
||||
ArchiveStreamRead(archiveFactory, Path.GetExtension(testArchive), readerOptions, testArchive);
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
string extension,
|
||||
ReaderOptions? readerOptions = null,
|
||||
params string[] testArchives
|
||||
) =>
|
||||
ArchiveStreamRead(
|
||||
ArchiveFactory.FindFactory<IArchiveFactory>(testArchives[0]),
|
||||
extension,
|
||||
readerOptions,
|
||||
testArchives
|
||||
);
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
string extension,
|
||||
ReaderOptions? readerOptions = null,
|
||||
params string[] testArchives
|
||||
) =>
|
||||
ArchiveStreamRead(
|
||||
archiveFactory,
|
||||
readerOptions,
|
||||
testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x))
|
||||
testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x)),
|
||||
extension
|
||||
);
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
ReaderOptions? readerOptions,
|
||||
IEnumerable<string> testArchives
|
||||
IEnumerable<string> testArchives,
|
||||
string extension
|
||||
)
|
||||
{
|
||||
extension.Should().BeOneOf(archiveFactory.GetSupportedExtensions());
|
||||
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
using (
|
||||
@@ -290,6 +299,11 @@ public class ArchiveTests : ReaderTests
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
archiveFactory ??= ArchiveFactory.FindFactory<IArchiveFactory>(testArchive);
|
||||
string extension = Path.GetExtension(testArchive).Substring(1);
|
||||
if (!int.TryParse(extension, out _) && "exe" != extension) //exclude parts
|
||||
{
|
||||
extension.Should().BeOneOf(archiveFactory.GetSupportedExtensions());
|
||||
}
|
||||
using (var archive = archiveFactory.OpenArchive(new FileInfo(testArchive), readerOptions))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
@@ -74,7 +75,7 @@ public class AsyncTests : TestBase
|
||||
public async ValueTask Archive_Entry_Async_Open_Stream()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz");
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
await using var archive = GZipArchive.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(File.OpenRead(testArchive))
|
||||
);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class GZipArchiveAsyncTests : ArchiveTests
|
||||
await using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
|
||||
#endif
|
||||
await using (
|
||||
var archive = await ArchiveFactory.OpenAsyncArchive(new AsyncOnlyStream(stream))
|
||||
var archive = GZipArchive.OpenAsyncArchive(new AsyncOnlyStream(stream))
|
||||
)
|
||||
{
|
||||
var entry = await archive.EntriesAsync.FirstAsync();
|
||||
|
||||
@@ -17,7 +17,7 @@ public class GZipArchiveTests : ArchiveTests
|
||||
public void GZip_Archive_Generic()
|
||||
{
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
|
||||
using (var archive = ArchiveFactory.OpenArchive(stream))
|
||||
using (var archive = GZipArchive.OpenArchive(stream))
|
||||
{
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
||||
|
||||
@@ -10,6 +10,7 @@ using SharpCompress.Common;
|
||||
using SharpCompress.Factories;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.GZip;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
@@ -149,6 +150,7 @@ public abstract class ReaderTests : TestBase
|
||||
|
||||
options.LeaveStreamOpen = false;
|
||||
await ReadImplAsync(testArchive, expectedCompression, options, cancellationToken);
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ public class SevenZipArchiveTests : ArchiveTests
|
||||
public void SevenZipArchive_BZip2_Split() =>
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
ArchiveStreamRead(
|
||||
".7z",
|
||||
null,
|
||||
"Original.7z.001",
|
||||
"Original.7z.002",
|
||||
@@ -151,6 +152,7 @@ public class SevenZipArchiveTests : ArchiveTests
|
||||
public void SevenZipArchive_ZSTD_Split() =>
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
ArchiveStreamRead(
|
||||
".7z",
|
||||
null,
|
||||
"7Zip.ZSTD.Split.7z.001",
|
||||
"7Zip.ZSTD.Split.7z.002",
|
||||
|
||||
@@ -63,6 +63,20 @@ public class TestBase : IAsyncDisposable
|
||||
Directory.Delete(SCRATCH2_FILES_PATH, true);
|
||||
}
|
||||
|
||||
public void CleanScratch()
|
||||
{
|
||||
if (Directory.Exists(SCRATCH_FILES_PATH))
|
||||
{
|
||||
Directory.Delete(SCRATCH_FILES_PATH, true);
|
||||
}
|
||||
Directory.CreateDirectory(SCRATCH_FILES_PATH);
|
||||
if (Directory.Exists(SCRATCH2_FILES_PATH))
|
||||
{
|
||||
Directory.Delete(SCRATCH2_FILES_PATH, true);
|
||||
}
|
||||
Directory.CreateDirectory(SCRATCH2_FILES_PATH);
|
||||
}
|
||||
|
||||
public void VerifyFiles()
|
||||
{
|
||||
if (UseExtensionInsteadOfNameToVerify)
|
||||
|
||||
Reference in New Issue
Block a user