Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/SharpCompress/Archives/ArchiveFactory.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ public static async ValueTask<IAsyncArchive> OpenAsyncArchive(

var factory = await FindFactoryAsync<IMultiArchiveFactory>(fileInfo, cancellationToken)
.ConfigureAwait(false);
return factory.OpenAsyncArchive(filesArray, options);
return await factory
.OpenAsyncArchive(filesArray, options, cancellationToken)
.ConfigureAwait(false);
}

public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
Expand Down Expand Up @@ -106,7 +108,9 @@ public static async ValueTask<IAsyncArchive> OpenAsyncArchive(

var factory = await FindFactoryAsync<IMultiArchiveFactory>(firstStream, cancellationToken)
.ConfigureAwait(false);
return factory.OpenAsyncArchive(streamsArray, options);
return await factory
.OpenAsyncArchive(streamsArray, options, cancellationToken)
.ConfigureAwait(false);
}

public static ValueTask<T> FindFactoryAsync<T>(
Expand Down
15 changes: 11 additions & 4 deletions src/SharpCompress/Archives/IMultiArchiveFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Factories;
using SharpCompress.Readers;

Expand Down Expand Up @@ -33,9 +34,12 @@ public interface IMultiArchiveFactory : IFactory
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
IAsyncArchive OpenAsyncArchive(
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A <see cref="ValueTask{TResult}"/> containing the opened async archive.</returns>
ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);

/// <summary>
Expand All @@ -50,8 +54,11 @@ IAsyncArchive OpenAsyncArchive(
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
IAsyncArchive OpenAsyncArchive(
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A <see cref="ValueTask{TResult}"/> containing the opened async archive.</returns>
ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
}
31 changes: 23 additions & 8 deletions src/SharpCompress/Factories/GZipFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,17 @@ public IArchive OpenArchive(
) => GZipArchive.OpenArchive(streams, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await GZipArchive
.OpenAsyncArchive(streams, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc/>
public IArchive OpenArchive(
Expand All @@ -107,10 +114,17 @@ public IArchive OpenArchive(
) => GZipArchive.OpenArchive(fileInfos, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await GZipArchive
.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

#endregion

Expand Down Expand Up @@ -191,14 +205,15 @@ public IWriter OpenWriter(Stream stream, IWriterOptions writerOptions)
}

/// <inheritdoc/>
public IAsyncWriter OpenAsyncWriter(
public ValueTask<IAsyncWriter> OpenAsyncWriter(
Stream stream,
IWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)OpenWriter(stream, writerOptions);
var writer = OpenWriter(stream, writerOptions);
return new((IAsyncWriter)writer);
}

#endregion
Expand Down
23 changes: 17 additions & 6 deletions src/SharpCompress/Factories/RarFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,17 @@ public IArchive OpenArchive(
) => RarArchive.OpenArchive(streams, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await RarArchive
.OpenAsyncArchive(streams, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc/>
public IArchive OpenArchive(
Expand All @@ -102,12 +109,16 @@ public IArchive OpenArchive(
) => RarArchive.OpenArchive(fileInfos, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
cancellationToken.ThrowIfCancellationRequested();
return await RarArchive
.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

#endregion
Expand Down
26 changes: 20 additions & 6 deletions src/SharpCompress/Factories/SevenZipFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,17 @@ public IArchive OpenArchive(
) => SevenZipArchive.OpenArchive(streams, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await SevenZipArchive
.OpenAsyncArchive(streams, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc/>
public IArchive OpenArchive(
Expand All @@ -97,10 +104,17 @@ public IArchive OpenArchive(
) => SevenZipArchive.OpenArchive(fileInfos, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await SevenZipArchive
.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

#endregion

Expand Down
31 changes: 23 additions & 8 deletions src/SharpCompress/Factories/TarFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,17 @@ public IArchive OpenArchive(
) => TarArchive.OpenArchive(streams, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await TarArchive
.OpenAsyncArchive(streams, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc/>
public IArchive OpenArchive(
Expand All @@ -291,10 +298,17 @@ public IArchive OpenArchive(
) => TarArchive.OpenArchive(fileInfos, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await TarArchive
.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

#endregion

Expand Down Expand Up @@ -394,14 +408,15 @@ public IWriter OpenWriter(Stream stream, IWriterOptions writerOptions)
}

/// <inheritdoc/>
public IAsyncWriter OpenAsyncWriter(
public ValueTask<IAsyncWriter> OpenAsyncWriter(
Stream stream,
IWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)OpenWriter(stream, writerOptions);
var writer = OpenWriter(stream, writerOptions);
return new((IAsyncWriter)writer);
}

#endregion
Expand Down
31 changes: 23 additions & 8 deletions src/SharpCompress/Factories/ZipFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,17 @@ public IArchive OpenArchive(
) => ZipArchive.OpenArchive(streams, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await ZipArchive
.OpenAsyncArchive(streams, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc/>
public IArchive OpenArchive(
Expand All @@ -175,10 +182,17 @@ public IArchive OpenArchive(
) => ZipArchive.OpenArchive(fileInfos, readerOptions);

/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
public async ValueTask<IAsyncArchive> OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return await ZipArchive
.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken)
.ConfigureAwait(false);
}

#endregion

Expand Down Expand Up @@ -219,14 +233,15 @@ public IWriter OpenWriter(Stream stream, IWriterOptions writerOptions)
}

/// <inheritdoc/>
public IAsyncWriter OpenAsyncWriter(
public ValueTask<IAsyncWriter> OpenAsyncWriter(
Stream stream,
IWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)OpenWriter(stream, writerOptions);
var writer = OpenWriter(stream, writerOptions);
return new((IAsyncWriter)writer);
}

#endregion
Expand Down
5 changes: 3 additions & 2 deletions src/SharpCompress/Readers/ReaderFactory.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ public static ValueTask<IAsyncReader> OpenAsyncReader(
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static ValueTask<IAsyncReader> OpenAsyncReader(
public static async ValueTask<IAsyncReader> OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
)
{
options ??= ReaderOptions.ForOwnedFile;
return OpenAsyncReader(fileInfo.OpenRead(), options, cancellationToken);
var stream = fileInfo.OpenAsyncReadStream(cancellationToken);
return await OpenAsyncReader(stream, options, cancellationToken).ConfigureAwait(false);
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stream opened from fileInfo.OpenAsyncReadStream(...) is not disposed if OpenAsyncReader(stream, ...) throws (e.g., invalid format). Wrap the call so the stream is disposed on failure to avoid file handle leaks.

Suggested change
return await OpenAsyncReader(stream, options, cancellationToken).ConfigureAwait(false);
try
{
return await OpenAsyncReader(stream, options, cancellationToken).ConfigureAwait(false);
}
catch
{
stream.Dispose();
throw;
}

Copilot uses AI. Check for mistakes.
}

public static async ValueTask<IAsyncReader> OpenAsyncReader(
Expand Down
6 changes: 4 additions & 2 deletions src/SharpCompress/Readers/Tar/TarReader.Factory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,16 @@ await TarArchive.IsTarFileAsync(testStream, cancellationToken).ConfigureAwait(fa
return new TarReader(sharpCompressStream, readerOptions, CompressionType.None);
}

public static ValueTask<IAsyncReader> OpenAsyncReader(
public static async ValueTask<IAsyncReader> OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
readerOptions ??= new ReaderOptions() { LeaveStreamOpen = false };
return OpenAsyncReader(fileInfo.OpenRead(), readerOptions, cancellationToken);
var stream = fileInfo.OpenAsyncReadStream(cancellationToken);
return await OpenAsyncReader(stream, readerOptions, cancellationToken)
.ConfigureAwait(false);
Comment on lines +144 to +145
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file stream opened here isn’t disposed if OpenAsyncReader(stream, ...) throws before returning a reader. Consider disposing stream on failure (try/finally) to prevent leaking file handles.

Suggested change
return await OpenAsyncReader(stream, readerOptions, cancellationToken)
.ConfigureAwait(false);
try
{
return await OpenAsyncReader(stream, readerOptions, cancellationToken)
.ConfigureAwait(false);
}
catch
{
stream.Dispose();
throw;
}

Copilot uses AI. Check for mistakes.
}

public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
Expand Down
2 changes: 1 addition & 1 deletion src/SharpCompress/SharpCompress.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<PropertyGroup Condition=" '$(TargetFramework)' == 'net48' Or '$(TargetFramework)' == 'netstandard2.0' Or '$(TargetFramework)' == 'netstandard2.1' ">
<DefineConstants>$(DefineConstants);LEGACY_DOTNET</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net9.0' Or '$(TargetFramework)' == 'net10.0' ">
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net10.0' ">
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net9.0 is still listed in TargetFrameworks, but it was removed from the IsTrimmable/IsAotCompatible condition. If net9.0 is intended to remain supported, consider adding it back to this property group (or document why it’s intentionally excluded).

Suggested change
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net10.0' ">
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net9.0' Or '$(TargetFramework)' == 'net10.0' ">

Copilot uses AI. Check for mistakes.
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
Expand Down
Loading