Compare commits

..

5 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
c825ae91a1 Complete fix for Microsoft.Bcl.AsyncInterfaces version conflict
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-11 22:15:38 +00:00
copilot-swe-agent[bot]
6478723a8d Format code with CSharpier
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-11 22:10:48 +00:00
copilot-swe-agent[bot]
2c7e9b9c21 Fix Microsoft.Bcl.AsyncInterfaces version conflict by downgrading to 8.0.0
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-11 22:10:01 +00:00
copilot-swe-agent[bot]
7f3da598d1 Initial plan 2026-02-11 22:04:45 +00:00
Adam Hathcock
33e9c78626 Merge pull request #1203 from adamhathcock/adam/issue-1201 2026-02-11 17:41:08 +00:00
6 changed files with 49 additions and 275 deletions

View File

@@ -5,7 +5,7 @@
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
<PackageVersion Include="Glob" Version="1.1.9" />
<PackageVersion Include="JetBrains.Profiler.SelfApi" Version="2.5.16" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageVersion Include="SimpleExec" Version="13.0.0" />

View File

@@ -4,11 +4,11 @@
".NETFramework,Version=v4.8": {
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Direct",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "vFuwSLj9QJBbNR0NeNO4YVASUbokxs+i/xbuu8B+Fs4FAZg5QaFa6eGrMaRqTzzNI5tAb97T7BhSxtLckFyiRA==",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.6.3"
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
@@ -91,10 +91,10 @@
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.6.3",
"contentHash": "7sCiwilJLYbTZELaKnc7RecBBXWXA+xMLQWZKWawBxYjp6DBlSE3v9/UcvKBvr1vv2tTOhipiogM8rRmxlhrVA==",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.1.2"
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.ValueTuple": {
@@ -106,11 +106,11 @@
".NETStandard,Version=v2.0": {
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Direct",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "vFuwSLj9QJBbNR0NeNO4YVASUbokxs+i/xbuu8B+Fs4FAZg5QaFa6eGrMaRqTzzNI5tAb97T7BhSxtLckFyiRA==",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.6.3"
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
@@ -206,19 +206,19 @@
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.6.3",
"contentHash": "7sCiwilJLYbTZELaKnc7RecBBXWXA+xMLQWZKWawBxYjp6DBlSE3v9/UcvKBvr1vv2tTOhipiogM8rRmxlhrVA==",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.1.2"
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
}
},
"net10.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "sXdDtMf2qcnbygw9OdE535c2lxSxrZP8gO4UhDJ0xiJbl1wIqXS1OTcTDFTIJPOFd6Mhcm8gPEthqWGUxBsTqw=="
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
@@ -264,9 +264,9 @@
"net8.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.23, )",
"resolved": "8.0.23",
"contentHash": "GqHiB1HbbODWPbY/lc5xLQH8siEEhNA0ptpJCC6X6adtAYNEzu5ZlqV3YHA3Gh7fuEwgA8XqVwMtH2KNtuQM1Q=="
"requested": "[8.0.22, )",
"resolved": "8.0.22",
"contentHash": "MhcMithKEiyyNkD2ZfbDZPmcOdi0GheGfg8saEIIEfD/fol3iHmcV8TsZkD4ZYz5gdUuoX4YtlVySUU7Sxl9SQ=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",

View File

@@ -1,243 +0,0 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Test.Mocks;
using Xunit;
namespace SharpCompress.Test.Rar;
/// <summary>
/// Tests specifically designed to exercise the Unpack5Async code path for RAR5 archives.
/// These tests use AsyncOnlyStream to ensure that async methods are actually being called.
/// </summary>
public class Rar5AsyncExtractionTests : ArchiveTests
{
[Fact]
public async Task Rar5_Basic_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_None_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.none.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_ExtractAllEntries_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
Assert.True(await archive.IsSolidAsync());
await using var reader = await archive.ExtractAllEntriesAsync();
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Reader_OpenEntryStream_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
var entryStream = await reader.OpenEntryStreamAsync();
try
{
var file = Path.GetFileName(reader.Entry.Key).NotNull();
var folder = Path.GetDirectoryName(reader.Entry.Key) ?? "";
var destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
if (!Directory.Exists(destdir))
{
Directory.CreateDirectory(destdir);
}
var destinationFileName = Path.Combine(destdir, file);
using var fs = File.OpenWrite(destinationFileName);
await entryStream.CopyToAsync(fs);
}
finally
{
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
await entryStream.DisposeAsync();
#else
entryStream.Dispose();
#endif
}
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Encrypted_FilesOnly_Reader_Async()
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar5.encrypted_filesOnly.rar")
);
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { Password = "test" }
);
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Encrypted_FilesAndHeader_Reader_Async()
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar5.encrypted_filesAndHeader.rar")
);
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { Password = "test" }
);
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_CRC_Blake2_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.crc_blake2.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Comment_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.comment.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_Skip_Some_Entries_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
// Only extract jpg files to test skipping in solid archive
if (!reader.Entry.IsDirectory && reader.Entry.Key.NotNull().Contains("jpg"))
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
}
[Fact]
public async Task Rar5_WriteToDirectory_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_WriteToDirectory_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
Assert.True(await archive.IsSolidAsync());
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
VerifyFiles();
}
}

View File

@@ -344,4 +344,21 @@ public class SevenZipArchiveTests : 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
}
[Fact]
public void SevenZipArchive_Cheat_CanBeOpenedWithArchiveFactory()
{
// Regression test for issue #1204: 7zip file couldn't be opened with ArchiveFactory.OpenArchive()
// due to Microsoft.Bcl.AsyncInterfaces version conflict (version 10.0.0 was too new)
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "cheat.7z");
// Test that ArchiveFactory can open the file
using var archive = ArchiveFactory.OpenArchive(testArchive);
Assert.NotNull(archive);
Assert.True(archive.Entries.Any());
// Verify we can read entries
var entry = archive.Entries.First();
Assert.NotNull(entry);
}
}

View File

@@ -190,10 +190,10 @@
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.6.3",
"contentHash": "7sCiwilJLYbTZELaKnc7RecBBXWXA+xMLQWZKWawBxYjp6DBlSE3v9/UcvKBvr1vv2tTOhipiogM8rRmxlhrVA==",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.1.2"
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"System.ValueTuple": {
@@ -275,7 +275,7 @@
"sharpcompress": {
"type": "Project",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "[10.0.0, )",
"Microsoft.Bcl.AsyncInterfaces": "[8.0.0, )",
"System.Buffers": "[4.6.1, )",
"System.Memory": "[4.6.3, )",
"System.Text.Encoding.CodePages": "[10.0.0, )"
@@ -283,11 +283,11 @@
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "vFuwSLj9QJBbNR0NeNO4YVASUbokxs+i/xbuu8B+Fs4FAZg5QaFa6eGrMaRqTzzNI5tAb97T7BhSxtLckFyiRA==",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.6.3"
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Buffers": {
@@ -527,9 +527,9 @@
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "vFuwSLj9QJBbNR0NeNO4YVASUbokxs+i/xbuu8B+Fs4FAZg5QaFa6eGrMaRqTzzNI5tAb97T7BhSxtLckFyiRA=="
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
}
}
}

Binary file not shown.