From 14ad6a86853c8de8a5cd531193febaefb4891cb0 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 29 Apr 2026 11:50:51 +0100 Subject: [PATCH] tar can write async --- src/SharpCompress/Factories/TarFactory.cs | 82 ++++++++++++++++++- src/SharpCompress/Writers/Tar/TarWriter.cs | 33 -------- .../Mocks/AsyncOnlyStream.cs | 4 +- .../Tar/TarWriterAsyncTests.cs | 2 +- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 51e5f547..0bfde315 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -404,19 +404,95 @@ public class TarFactory nameof(writerOptions) ), }; + + if (!stream.CanWrite) + { + throw new ArgumentException("Tars require writable streams."); + } + if (writerOptions.LeaveStreamOpen) + { + stream = SharpCompressStream.CreateNonDisposing(stream); + } + + var providers = writerOptions.Providers; + + stream = writerOptions.CompressionType switch + { + CompressionType.None => stream, + CompressionType.BZip2 => providers.CreateCompressStream( + CompressionType.BZip2, + stream, + writerOptions.CompressionLevel + ), + CompressionType.GZip => providers.CreateCompressStream( + CompressionType.GZip, + stream, + writerOptions.CompressionLevel + ), + CompressionType.LZip => providers.CreateCompressStream( + CompressionType.LZip, + stream, + writerOptions.CompressionLevel + ), + _ => throw new InvalidFormatException( + "Tar does not support compression: " + writerOptions.CompressionType + ), + }; return new TarWriter(stream, tarOptions); } /// - public ValueTask OpenAsyncWriter( + public async ValueTask OpenAsyncWriter( Stream stream, IWriterOptions writerOptions, CancellationToken cancellationToken = default ) { cancellationToken.ThrowIfCancellationRequested(); - var writer = OpenWriter(stream, writerOptions); - return new((IAsyncWriter)writer); + TarWriterOptions tarOptions = writerOptions switch + { + TarWriterOptions two => two, + WriterOptions wo => new TarWriterOptions(wo), + _ => throw new ArgumentException( + $"Expected WriterOptions or TarWriterOptions, got {writerOptions.GetType().Name}", + nameof(writerOptions) + ), + }; + + if (!stream.CanWrite) + { + throw new ArgumentException("Tars require writable streams."); + } + if (writerOptions.LeaveStreamOpen) + { + stream = SharpCompressStream.CreateNonDisposing(stream); + } + + var providers = writerOptions.Providers; + + stream = writerOptions.CompressionType switch + { + CompressionType.None => stream, + CompressionType.BZip2 => await providers.CreateCompressStreamAsync( + CompressionType.BZip2, + stream, + writerOptions.CompressionLevel, + cancellationToken).ConfigureAwait(false), + CompressionType.GZip => await providers.CreateCompressStreamAsync( + CompressionType.GZip, + stream, + writerOptions.CompressionLevel, + cancellationToken).ConfigureAwait(false), + CompressionType.LZip => await providers.CreateCompressStreamAsync( + CompressionType.LZip, + stream, + writerOptions.CompressionLevel, + cancellationToken).ConfigureAwait(false), + _ => throw new InvalidFormatException( + "Tar does not support compression: " + writerOptions.CompressionType + ), + }; + return new TarWriter(stream, tarOptions); } #endregion diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index faa2b72a..73378fb0 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -21,39 +21,6 @@ public partial class TarWriter : AbstractWriter finalizeArchiveOnClose = options.FinalizeArchiveOnClose; headerFormat = options.HeaderFormat; - if (!destination.CanWrite) - { - throw new ArgumentException("Tars require writable streams."); - } - if (WriterOptions.LeaveStreamOpen) - { - destination = SharpCompressStream.CreateNonDisposing(destination); - } - - var providers = options.Providers; - - destination = options.CompressionType switch - { - CompressionType.None => destination, - CompressionType.BZip2 => providers.CreateCompressStream( - CompressionType.BZip2, - destination, - options.CompressionLevel - ), - CompressionType.GZip => providers.CreateCompressStream( - CompressionType.GZip, - destination, - options.CompressionLevel - ), - CompressionType.LZip => providers.CreateCompressStream( - CompressionType.LZip, - destination, - options.CompressionLevel - ), - _ => throw new InvalidFormatException( - "Tar does not support compression: " + options.CompressionType - ), - }; InitializeStream(destination); } diff --git a/tests/SharpCompress.Test/Mocks/AsyncOnlyStream.cs b/tests/SharpCompress.Test/Mocks/AsyncOnlyStream.cs index 823327f0..232f60ee 100644 --- a/tests/SharpCompress.Test/Mocks/AsyncOnlyStream.cs +++ b/tests/SharpCompress.Test/Mocks/AsyncOnlyStream.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; namespace SharpCompress.Test.Mocks; -public class AsyncOnlyStream(Stream stream) : Stream +public class AsyncOnlyStream(Stream stream, bool disposeStream = true) : Stream { private readonly Stream _stream = stream ?? throw new ArgumentNullException(nameof(stream)); @@ -71,7 +71,7 @@ public class AsyncOnlyStream(Stream stream) : Stream protected override void Dispose(bool disposing) { - if (disposing) + if (disposing && disposeStream) { _stream.Dispose(); } diff --git a/tests/SharpCompress.Test/Tar/TarWriterAsyncTests.cs b/tests/SharpCompress.Test/Tar/TarWriterAsyncTests.cs index 8f6c5079..b21e4439 100644 --- a/tests/SharpCompress.Test/Tar/TarWriterAsyncTests.cs +++ b/tests/SharpCompress.Test/Tar/TarWriterAsyncTests.cs @@ -67,7 +67,7 @@ public class TarWriterAsyncTests : WriterTests using Stream content = File.OpenRead(Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg")); await using ( var writer = new TarWriter( - new AsyncOnlyStream(stream), + new AsyncOnlyStream(stream, false), new TarWriterOptions(CompressionType.None, finalizeArchive) ) )