Merge pull request #1340 from adamhathcock/copilot/fix-7zip-progress-reporting

Restore `WriteToDirectoryAsync` progress callbacks for solid 7z archives
This commit is contained in:
Adam Hathcock
2026-05-29 09:48:32 +01:00
committed by GitHub
3 changed files with 64 additions and 25 deletions

View File

@@ -29,12 +29,33 @@ public static class IAsyncArchiveExtensions
|| archive.Type == ArchiveType.SevenZip
)
{
var totalBytes = await archive.TotalUncompressedSizeAsync().ConfigureAwait(false);
var bytesRead = 0L;
await using var reader = await archive
.ExtractAllEntriesAsync()
.ConfigureAwait(false);
await reader
.WriteAllToDirectoryAsync(destinationDirectory, options, cancellationToken)
.ConfigureAwait(false);
while (await reader.MoveToNextEntryAsync(cancellationToken).ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
await reader
.WriteEntryToDirectoryAsync(
destinationDirectory,
options,
cancellationToken
)
.ConfigureAwait(false);
if (reader.Entry.IsDirectory)
{
continue;
}
bytesRead += reader.Entry.Size;
progress?.Report(
new ProgressReport(reader.Entry.Key ?? string.Empty, bytesRead, totalBytes)
);
}
}
else
{

View File

@@ -4,15 +4,15 @@
"net10.0": {
"Microsoft.DotNet.ILCompiler": {
"type": "Direct",
"requested": "[10.0.6, )",
"resolved": "10.0.6",
"contentHash": "nBOzxOys8OeyJ+Nsi/uYlI/5TSsvwjaM/p5m4dTL6khCLx9UuP3b2ec3HeuBw/+F7hHCAZG1yFx8VBeoRAX+EQ=="
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "f9u8fMRROe2lS5MOOLutK6iSNTK9pC3kqd90FIn8Sk29fbZ0QDjZrBbwUkhouk/8dppC71SIEQaag0lGRTxvfA=="
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.6, )",
"resolved": "10.0.6",
"contentHash": "QKuvS0LWX4fjFqeDkyM7Kqt8P3wYTiPD4nwU+9y59n0sCiG714fxDgbbN82vDnzq89AF/PiHl92TP2C4aFDUQA=="
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
@@ -63,22 +63,6 @@
"sharpcompress": {
"type": "Project"
}
},
"net10.0/osx-arm64": {
"Microsoft.DotNet.ILCompiler": {
"type": "Direct",
"requested": "[10.0.6, )",
"resolved": "10.0.6",
"contentHash": "nBOzxOys8OeyJ+Nsi/uYlI/5TSsvwjaM/p5m4dTL6khCLx9UuP3b2ec3HeuBw/+F7hHCAZG1yFx8VBeoRAX+EQ==",
"dependencies": {
"runtime.osx-arm64.Microsoft.DotNet.ILCompiler": "10.0.6"
}
},
"runtime.osx-arm64.Microsoft.DotNet.ILCompiler": {
"type": "Transitive",
"resolved": "10.0.6",
"contentHash": "+yovwOAlIpfIcH+ZWmLYXWTSWYJ93wcQxF/RVk+X4MXgLASeosCJYVLqP20g0cufKjoRqvCmnklR6y9Su3ORtA=="
}
}
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Test.Mocks;
using Xunit;
@@ -141,6 +143,29 @@ public class SevenZipArchiveAsyncTests : ArchiveTests
VerifyFiles();
}
[Fact]
public async Task SevenZipArchive_Solid_WriteToDirectoryAsync_WithProgress()
{
var progressReports = new System.Collections.Generic.List<ProgressReport>();
var progress = new SynchronousProgress<ProgressReport>(report =>
progressReports.Add(report)
);
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.solid.7z");
#if NETFRAMEWORK
using var stream = File.OpenRead(testArchive);
#else
await using var stream = File.OpenRead(testArchive);
#endif
await using var archive = await ArchiveFactory.OpenAsyncArchive(
new AsyncOnlyStream(stream)
);
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH, progress: progress);
VerifyFiles();
Assert.True(progressReports.Count > 0, "Progress reports should be generated");
}
[Fact]
public async Task SevenZipArchive_BZip2_AsyncStreamExtraction()
{
@@ -336,4 +361,13 @@ public class SevenZipArchiveAsyncTests : ArchiveTests
// The critical check: within a single folder, the stream should NEVER be recreated
Assert.Equal(0, streamRecreationsWithinFolder); // Folder stream should remain the same for all entries in the same folder
}
private sealed class SynchronousProgress<T> : IProgress<T>
{
private readonly Action<T> _handler;
public SynchronousProgress(Action<T> handler) => _handler = handler;
public void Report(T value) => _handler(value);
}
}