Compare commits

...

6 Commits

Author SHA1 Message Date
Adam Hathcock
c4a28e7cfb Update tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-09 09:11:19 +00:00
Adam Hathcock
29197f2142 Update tests/SharpCompress.Test/Rar/RarArchiveTests.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-09 09:10:59 +00:00
copilot-swe-agent[bot]
2a4081362e Complete fix for RAR extraction subdirectory issue
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-08 12:56:44 +00:00
copilot-swe-agent[bot]
d5cab8172b Address code review feedback: clarify file size comment
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-08 12:54:11 +00:00
copilot-swe-agent[bot]
4084b347d4 Fix RAR extraction to preserve subdirectory structure
- Set default ExtractFullPath=true in WriteToDirectoryInternal methods
- Add test case with sample RAR archive containing subdirectories
- Tests verify files are extracted to correct subdirectories, not root

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-08 12:52:25 +00:00
copilot-swe-agent[bot]
5437d9ff8c Initial plan 2026-02-08 12:38:49 +00:00
6 changed files with 94 additions and 6 deletions

View File

@@ -43,6 +43,9 @@ public static class IArchiveExtensions
var bytesRead = 0L;
var seenDirectories = new HashSet<string>();
// When extracting an entire archive, default to extracting with full paths
options ??= new ExtractionOptions { ExtractFullPath = true, Overwrite = true };
foreach (var entry in archive.Entries)
{
if (entry.IsDirectory)

View File

@@ -58,6 +58,9 @@ public static class IAsyncArchiveExtensions
var bytesRead = 0L;
var seenDirectories = new HashSet<string>();
// When extracting an entire archive, default to extracting with full paths
options ??= new ExtractionOptions { ExtractFullPath = true, Overwrite = true };
await foreach (var entry in archive.EntriesAsync.WithCancellation(cancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();

View File

@@ -216,9 +216,9 @@
"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

@@ -718,6 +718,47 @@ public class RarArchiveAsyncTests : ArchiveTests
VerifyFiles();
}
/// <summary>
/// Tests for Issue #1050 - RAR extraction with WriteToDirectoryAsync creates folders
/// but places all files at the top level instead of in their subdirectories.
/// </summary>
[Fact]
public async ValueTask Rar_Issue1050_WriteToDirectoryAsync_ExtractsToSubdirectories()
{
var testFile = "Rar.issue1050.rar";
using var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testFile));
await using var archive = RarArchive.OpenAsyncArchive(fileStream);
// Extract using archive.WriteToDirectoryAsync without explicit options
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
// Verify files are in their subdirectories, not at the root
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "PhysicsBraid", "263825.tr11dtp")),
"File should be in PhysicsBraid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Animations", "15441.tr11anim")),
"File should be in Animations subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Braid", "766728.tr11dtp")),
"File should be in Braid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Braid", "766832.tr11dtp")),
"File should be in Braid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "HeadBraid", "321353.tr11modeldata")),
"File should be in HeadBraid subdirectory"
);
// NOTE: The file size check is omitted because there's a separate pre-existing bug
// in the async RAR stream implementation that causes incorrect file sizes.
// This test only verifies the directory structure fix.
}
private async ValueTask ArchiveOpenStreamReadAsync(
ReaderOptions? readerOptions,
params string[] testArchives

View File

@@ -722,6 +722,47 @@ public class RarArchiveTests : ArchiveTests
Assert.Contains("unpacked file size does not match header", exception.Message);
}
/// <summary>
/// Tests for Issue #1050 - RAR extraction with WriteToDirectory creates folders
/// but places all files at the top level instead of in their subdirectories.
/// </summary>
[Fact]
public void Rar_Issue1050_WriteToDirectory_ExtractsToSubdirectories()
{
var testFile = "Rar.issue1050.rar";
using var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testFile));
using var archive = RarArchive.OpenArchive(fileStream);
// Extract using archive.WriteToDirectory without explicit options
archive.WriteToDirectory(SCRATCH_FILES_PATH);
// Verify files are in their subdirectories, not at the root
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "PhysicsBraid", "263825.tr11dtp")),
"File should be in PhysicsBraid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Animations", "15441.tr11anim")),
"File should be in Animations subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Braid", "766728.tr11dtp")),
"File should be in Braid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "Braid", "766832.tr11dtp")),
"File should be in Braid subdirectory"
);
Assert.True(
File.Exists(Path.Combine(SCRATCH_FILES_PATH, "HeadBraid", "321353.tr11modeldata")),
"File should be in HeadBraid subdirectory"
);
// Verify the exact file size of 766832.tr11dtp matches the archive entry size
var fileInfo = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Braid", "766832.tr11dtp"));
Assert.Equal(4867620, fileInfo.Length); // Expected: 4,867,620 bytes
}
/// <summary>
/// Test case for malformed RAR archives that previously caused infinite loops.
/// This test verifies that attempting to read entries from a potentially malformed

Binary file not shown.