From 07b2d37a0c28c027fb7d151f1a5ea34c5a8a54fb Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 28 Jan 2026 22:35:11 +0000
Subject: [PATCH 1/6] Initial plan
From b9470611ebcc927070b44bde8ec892c06404435a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 28 Jan 2026 22:37:49 +0000
Subject: [PATCH 2/6] Initial commit - planning changes to TarExtractor error
handling
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
---
nuget.config | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/nuget.config b/nuget.config
index 227ad0ce..765346e5 100644
--- a/nuget.config
+++ b/nuget.config
@@ -1,7 +1,7 @@
-
+
-
+
-
\ No newline at end of file
+
From 2b2a9c2ab33cb29bb2dcb54d59b5e9d5586d679b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 28 Jan 2026 22:39:45 +0000
Subject: [PATCH 3/6] Fix TarExtractor to dispose backing stream and skip
failed entries
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
---
RecursiveExtractor/Extractors/TarExtractor.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/RecursiveExtractor/Extractors/TarExtractor.cs b/RecursiveExtractor/Extractors/TarExtractor.cs
index 8553da07..de5228d5 100644
--- a/RecursiveExtractor/Extractors/TarExtractor.cs
+++ b/RecursiveExtractor/Extractors/TarExtractor.cs
@@ -62,6 +62,8 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra
catch (Exception e)
{
Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.TAR, fileEntry.FullPath, tarEntry.Key, e.GetType());
+ fs?.Dispose();
+ continue;
}
var name = tarEntry.Key?.Replace('/', Path.DirectorySeparatorChar);
if (string.IsNullOrEmpty(name))
@@ -132,6 +134,8 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti
catch (Exception e)
{
Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.TAR, fileEntry.FullPath, tarEntry.Key, e.GetType());
+ fs?.Dispose();
+ continue;
}
var name = tarEntry.Key?.Replace('/', Path.DirectorySeparatorChar);
if (string.IsNullOrEmpty(name))
From ea4d2a1d2e85416d3de747fc49509ea1e3c8208b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 28 Jan 2026 22:40:58 +0000
Subject: [PATCH 4/6] Fix ZipExtractor to dispose backing stream and skip
failed entries
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
---
RecursiveExtractor/Extractors/ZipExtractor.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs
index 0c786230..c6d1b0fa 100644
--- a/RecursiveExtractor/Extractors/ZipExtractor.cs
+++ b/RecursiveExtractor/Extractors/ZipExtractor.cs
@@ -136,9 +136,10 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra
catch (Exception e)
{
Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.ZIP, fileEntry.FullPath, zipEntry.Key, e.GetType());
+ target?.Dispose();
+ continue;
}
- target ??= new MemoryStream();
var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? "";
var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff);
@@ -222,7 +223,7 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti
{
governor.CheckResourceGovernor(zipEntry.Size);
- using var fs = StreamFactory.GenerateAppropriateBackingStream(options, zipEntry.Size);
+ var fs = StreamFactory.GenerateAppropriateBackingStream(options, zipEntry.Size);
try
{
@@ -232,6 +233,8 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti
catch (Exception e)
{
Logger.Debug(Extractor.FAILED_PARSING_ERROR_MESSAGE_STRING, ArchiveFileType.ZIP, fileEntry.FullPath, zipEntry.Key, e.GetType());
+ fs?.Dispose();
+ continue;
}
var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? "";
From 90261d1fef7a4252c14c4ddcb0031567886f0504 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 12 Feb 2026 06:13:01 +0000
Subject: [PATCH 5/6] Use passthroughStream in ZipExtractor to reduce
allocations
Co-authored-by: gfs <98900+gfs@users.noreply.github.com>
---
RecursiveExtractor/Extractors/ZipExtractor.cs | 2 +-
nuget.config | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs
index c6d1b0fa..d5b061ee 100644
--- a/RecursiveExtractor/Extractors/ZipExtractor.cs
+++ b/RecursiveExtractor/Extractors/ZipExtractor.cs
@@ -238,7 +238,7 @@ public IEnumerable Extract(FileEntry fileEntry, ExtractorOptions opti
}
var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? "";
- var newFileEntry = new FileEntry(name, fs, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff);
+ var newFileEntry = new FileEntry(name, fs, fileEntry, passthroughStream: true, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff);
if (options.Recurse || topLevel)
{
diff --git a/nuget.config b/nuget.config
index 765346e5..227ad0ce 100644
--- a/nuget.config
+++ b/nuget.config
@@ -1,7 +1,7 @@
-
+
-
+
-
+
\ No newline at end of file
From 80f2f28079fb0c9488a75d779c458f3c4a526878 Mon Sep 17 00:00:00 2001
From: Giulia Stocco <98900+gfs@users.noreply.github.com>
Date: Fri, 13 Feb 2026 21:22:35 -0800
Subject: [PATCH 6/6] Update RecursiveExtractor/Extractors/ZipExtractor.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
RecursiveExtractor/Extractors/ZipExtractor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/RecursiveExtractor/Extractors/ZipExtractor.cs b/RecursiveExtractor/Extractors/ZipExtractor.cs
index 002be391..4c619da7 100644
--- a/RecursiveExtractor/Extractors/ZipExtractor.cs
+++ b/RecursiveExtractor/Extractors/ZipExtractor.cs
@@ -141,7 +141,7 @@ public async IAsyncEnumerable ExtractAsync(FileEntry fileEntry, Extra
}
var name = zipEntry.Key?.Replace('/', Path.DirectorySeparatorChar) ?? "";
- var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff);
+ var newFileEntry = new FileEntry(name, target, fileEntry, modifyTime: zipEntry.LastModifiedTime, memoryStreamCutoff: options.MemoryStreamCutoff, passthroughStream: true);
if (options.Recurse || topLevel)
{