Skip to content

Comments

Some clean up post-async merging#1184

Merged
adamhathcock merged 14 commits intomasterfrom
adam/cleanup
Feb 4, 2026
Merged

Some clean up post-async merging#1184
adamhathcock merged 14 commits intomasterfrom
adam/cleanup

Conversation

@adamhathcock
Copy link
Owner

This pull request refactors several files to adopt file-scoped namespaces for improved readability and consistency, and updates stream handling logic for archive entries to use a unified stream wrapper. Additionally, it enhances asynchronous extraction APIs and simplifies code in some archive format implementations.

Namespace Refactoring:

  • Converted multiple files in the SharpCompress.Common.Ace and SharpCompress.Common.Arc namespaces to use file-scoped namespace declarations, reducing indentation and boilerplate. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]

Stream Handling Improvements:

  • Replaced NonDisposingStream with SharpCompressStream.CreateNonDisposing in archive entry stream methods for GZip, Tar, and Zip writable archive entries, ensuring consistent stream management. [1] [2] [3]

Async API and Extraction Enhancements:

  • Updated TarArchiveEntry.OpenEntryStreamAsync to use an actual asynchronous stream retrieval, improving correctness for async extraction.
  • Improved WriteToAsync to use conditional compilation for legacy and modern .NET async stream disposal, ensuring compatibility across frameworks.

SevenZip Archive Code Simplification:

  • Simplified SevenZipArchive.GetEntryStream: removed the unused useSyncOverAsyncDispose parameter and cleaned up related calls. [1] [2]

Arc Archive Async Stream Handling:

  • Cleaned up async stream creation logic in ArcFilePart.Async.cs by reducing nesting and simplifying the construction of compression streams. [1] [2]

These changes collectively modernize the codebase, improve maintainability, and enhance compatibility with newer .NET features.

Copilot AI review requested due to automatic review settings February 4, 2026 15:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request modernizes the codebase by adopting file-scoped namespaces, consolidating stream wrapper functionality, and improving async stream handling. The changes refactor stream management to use a unified SharpCompressStream wrapper instead of the previous NonDisposingStream and RewindableStream classes, while also removing the useSyncOverAsyncDispose parameter in favor of a centralized utility method.

Changes:

  • Converted multiple files to use file-scoped namespace declarations for reduced indentation
  • Replaced NonDisposingStream with SharpCompressStream.CreateNonDisposing() throughout the codebase
  • Renamed RewindableStream to SharpCompressStream and SeekableRewindableStream to SeekableSharpCompressStream
  • Removed useSyncOverAsyncDispose parameter from multiple methods, replacing with Utility.UseSyncOverAsyncDispose()
  • Enhanced async APIs with proper conditional compilation for legacy vs. modern .NET
  • Removed DEBUG_STREAMS conditional compilation directives

Reviewed changes

Copilot reviewed 159 out of 159 changed files in this pull request and generated 31 comments.

Show a summary per file
File Description
Multiple test files Updated to use SharpCompressStream.CreateNonDisposing() and renamed class references
Writer classes (Zip, Tar, GZip) Replaced NonDisposingStream with SharpCompressStream.CreateNonDisposing()
Reader classes (Rar, Arj, Arc, Ace) Removed useSyncOverAsyncDispose parameter and updated to file-scoped namespaces
Common classes Renamed stream classes and updated references throughout
Archive entry classes Updated stream handling for writable entries
Factory classes Updated to use SharpCompressStream instead of RewindableStream
Compressor classes Removed DEBUG_STREAMS directives
Namespace files (Arj, Arc, Ace) Converted to file-scoped namespaces
Comments suppressed due to low confidence (1)

src/SharpCompress/IO/SharpCompressStream.cs:220

  • The expression 'A ? B : true' can be simplified to '!A || B'.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

while (true)
{
var reader = new BinaryReader(rewindableStream);
var reader = new BinaryReader(sharpCompressStream);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Disposable 'BinaryReader' is created but not disposed.

Copilot uses AI. Check for mistakes.
throw new NotSupportedException();
private Stream BuildDecodedStream()
{
var binaryReader = new BinaryReader(_stream, Encoding.Default, leaveOpen: true);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Disposable 'BinaryReader' is created but not disposed.

Copilot uses AI. Check for mistakes.
rewindableStream.Rewind();
var testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
sharpCompressStream.Rewind();
var testStream = new GZipStream(sharpCompressStream, CompressionMode.Decompress);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Disposable 'GZipStream' is created but not disposed.

Copilot uses AI. Check for mistakes.
#region Instance Fields

private Stream baseInputStream;
private Stream baseInputStream;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Field 'baseInputStream' can be 'readonly'.

Copilot uses AI. Check for mistakes.
internal class BitStream
private const int EOF = 1234;
private byte[] _src;
private int _srcLen;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Field '_srcLen' can be 'readonly'.

Copilot uses AI. Check for mistakes.
private byte[] _src;
private int _srcLen;
private int _byteIdx;
private int _bitIdx;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Field '_bitIdx' can be 'readonly'.

Copilot uses AI. Check for mistakes.
{
internal class BitStream
private const int EOF = 1234;
private byte[] _src;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Field '_src' can be 'readonly'.

Copilot uses AI. Check for mistakes.
private int _bitIdx;
private int _bitsLeft;
private ulong _bitBuffer;
private static uint[] _maskBits = new uint[17]
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

Field '_maskBits' can be 'readonly'.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 4, 2026 16:17
_isDisposed = true;
if (!LeaveStreamOpen)
{
_underlyingStream.Dispose();
Copy link
Contributor

Choose a reason for hiding this comment

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

WARNING: Inconsistent async dispose pattern - synchronous dispose on async path

The DisposeAsync() method calls _underlyingStream.Dispose() (synchronous) instead of await _underlyingStream.DisposeAsync(). This could block the async flow and cause deadlocks in certain scenarios.

Suggested change
_underlyingStream.Dispose();
await _underlyingStream.DisposeAsync();

await stream.DisposeAsync();
if (!LeaveStreamOpen)
{
await stream.DisposeAsync();
Copy link
Contributor

Choose a reason for hiding this comment

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

WARNING: Missing .ConfigureAwait(false) on async dispose

The DisposeAsync() method calls await stream.DisposeAsync() without .ConfigureAwait(false). This could cause deadlocks in UI or ASP.NET Classic contexts.

Suggested change
await stream.DisposeAsync();
await stream.DisposeAsync().ConfigureAwait(false);

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 177 out of 177 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

offset += 2 + commentLength;
}
ushort commentLength = BitConverter.ToUInt16(headerData, offset);
offset += 2 + commentLength;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to offset is useless, since its value is never read.

Suggested change
offset += 2 + commentLength;

Copilot uses AI. Check for mistakes.
((long)reader.ReadUInt32() << 32) | headerBytes;
headerBytes = reader.ReadUInt32();

var version = reader.ReadUInt16();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to version is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
headerBytes = reader.ReadUInt32();

var version = reader.ReadUInt16();
var flags = (HeaderFlags)reader.ReadUInt16();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to flags is useless, since its value is never read.

Copilot uses AI. Check for mistakes.

var version = reader.ReadUInt16();
var flags = (HeaderFlags)reader.ReadUInt16();
var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to compressionMethod is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
var version = reader.ReadUInt16();
var flags = (HeaderFlags)reader.ReadUInt16();
var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
var lastModifiedDate = reader.ReadUInt16();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to lastModifiedDate is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
var flags = (HeaderFlags)reader.ReadUInt16();
var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
var lastModifiedDate = reader.ReadUInt16();
var lastModifiedTime = reader.ReadUInt16();
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This assignment to lastModifiedTime is useless, since its value is never read.

Copilot uses AI. Check for mistakes.
&& local_header.CompressedSize == 0
&& local_header.UncompressedSize == 0
&& local_header.Crc == 0
&& local_header.IsDirectory == false
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The expression 'A == false' can be simplified to '!A'.

Copilot uses AI. Check for mistakes.

public override bool CanRead => true;

public override bool CanSeek => _isPassthrough ? stream.CanSeek : true;
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The expression 'A ? B : true' can be simplified to '!A || B'.

Copilot uses AI. Check for mistakes.
var rewindableStream = RewindableStream.EnsureSeekable(stream);
while (true)
var sharpCompressStream = SharpCompressStream.EnsureSeekable(stream);
var reader = new BinaryReader(
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

This variable is manually disposed in a finally block - consider a C# using statement as a preferable resource management technique.

Copilot uses AI. Check for mistakes.
@kiloconnect
Copy link
Contributor

kiloconnect bot commented Feb 4, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/SharpCompress/IO/SeekableSharpCompressStream.Async.cs 43 Inconsistent async dispose - synchronous dispose on async path
src/SharpCompress/IO/SharpCompressStream.Async.cs 266 Missing .ConfigureAwait(false) on async dispose
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
src/SharpCompress/Factories/GZipFactory.cs 120 Disposable 'GZipStream' is created but not disposed (existing comment)
src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs 26 Disposable 'BinaryReader' is created but not disposed (existing comment)
src/SharpCompress/Compressors/Squeezed/SqueezedStream.cs 66 Disposable 'BinaryReader' is created but not disposed (existing comment)
Files Reviewed (X files)
  • src/SharpCompress/IO/SharpCompressStream.cs - renamed from RewindableStream
  • src/SharpCompress/IO/SharpCompressStream.Async.cs - renamed from RewindableStream.Async
  • src/SharpCompress/IO/SeekableSharpCompressStream.cs - renamed from SeekableRewindableStream
  • src/SharpCompress/IO/SeekableSharpCompressStream.Async.cs - renamed from SeekableRewindableStream.Async
  • src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs
  • src/SharpCompress/Archives/IArchiveEntryExtensions.cs
  • src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs
  • src/SharpCompress/Archives/Tar/TarArchive.Factory.cs
  • src/SharpCompress/Archives/Tar/TarArchiveEntry.cs
  • src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs
  • src/SharpCompress/Archives/Zip/ZipWritableArchiveEntry.cs
  • src/SharpCompress/Factories/GZipFactory.cs
  • src/SharpCompress/Common/Ace/AceCrc.cs
  • src/SharpCompress/Common/Ace/AceEntry.cs
  • src/SharpCompress/Common/Ace/AceFilePart.cs
  • src/SharpCompress/Common/Ace/AceVolume.cs
  • src/SharpCompress/Common/Ace/Headers/AceFileHeader.cs
  • src/SharpCompress/Common/Ace/Headers/AceFileHeader.Async.cs
  • src/SharpCompress/Common/Ace/Headers/AceHeader.cs
  • src/SharpCompress/Common/Ace/Headers/AceHeader.Async.cs
  • src/SharpCompress/Common/Ace/Headers/AceMainHeader.cs
  • src/SharpCompress/Common/Ace/Headers/AceMainHeader.Async.cs
  • src/SharpCompress/Common/Ace/Headers/AceSignature.cs
  • src/SharpCompress/Common/Arc/ArcEntry.cs
  • src/SharpCompress/Common/Arc/ArcFilePart.cs
  • src/SharpCompress/Common/Arj/ArjEntry.cs
  • src/SharpCompress/Common/Arj/ArjFilePart.cs
  • src/SharpCompress/Common/Arj/Headers/ArjHeader.cs
  • src/SharpCompress/Common/Arj/Headers/ArjLocalHeader.cs
  • src/SharpCompress/Common/Arj/Headers/ArjMainHeader.cs
  • src/SharpCompress/Common/Tar/TarFilePart.cs
  • src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs
  • src/SharpCompress/Common/Zip/ZipFilePart.cs
  • src/SharpCompress/Compressors/Arj/LhaStream.cs
  • src/SharpCompress/Compressors/Squeezed/SqueezedStream.cs
  • src/SharpCompress/Readers/Ace/AceReader.cs
  • src/SharpCompress/Readers/Arc/ArcReader.cs
  • src/SharpCompress/Readers/Arj/ArjReader.cs
  • src/SharpCompress/Readers/ReaderFactory.cs
  • Multiple test files (renamed and updated)

Fix these issues in Kilo Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant