From 43c839eb898b7fa67b658891e1f607eeb58e7aa1 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 9 Oct 2019 09:55:16 +0100 Subject: [PATCH] Create and using PauseEntryRebuilding for adding large numbers of entries --- .../Archives/AbstractWritableArchive.cs | 26 +++++++++++++++++++ .../Archives/IWritableArchive.cs | 6 +++++ .../Archives/IWritableArchiveExtensions.cs | 18 ++++++++----- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 5f38d459e..71a8d3c1a 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -12,11 +12,28 @@ public abstract class AbstractWritableArchive : AbstractArchive where TEntry : IArchiveEntry where TVolume : IVolume { + private class RebuildPauseDisposable: IDisposable + { + private readonly AbstractWritableArchive archive; + + public RebuildPauseDisposable(AbstractWritableArchive archive) + { + this.archive = archive; + archive.pauseRebuilding = true; + } + + public void Dispose() + { + archive.pauseRebuilding = false; + archive.RebuildModifiedCollection(); + } + } private readonly List newEntries = new List(); private readonly List removedEntries = new List(); private readonly List modifiedEntries = new List(); private bool hasModifications; + private bool pauseRebuilding; internal AbstractWritableArchive(ArchiveType type) : base(type) @@ -47,8 +64,17 @@ public override ICollection Entries } } + public IDisposable PauseEntryRebuilding() + { + return new RebuildPauseDisposable(this); + } + private void RebuildModifiedCollection() { + if (pauseRebuilding) + { + return; + } hasModifications = true; newEntries.RemoveAll(v => removedEntries.Contains(v)); modifiedEntries.Clear(); diff --git a/src/SharpCompress/Archives/IWritableArchive.cs b/src/SharpCompress/Archives/IWritableArchive.cs index 380d68148..3b1b03285 100644 --- a/src/SharpCompress/Archives/IWritableArchive.cs +++ b/src/SharpCompress/Archives/IWritableArchive.cs @@ -11,5 +11,11 @@ public interface IWritableArchive : IArchive IArchiveEntry AddEntry(string key, Stream source, bool closeStream, long size = 0, DateTime? modified = null); void SaveTo(Stream stream, WriterOptions options); + + /// + /// Use this to pause entry rebuilding when adding large collections of entries. Dispose when complete. A using statement is recommended. + /// + /// IDisposeable to resume entry rebuilding + IDisposable PauseEntryRebuilding(); } } \ No newline at end of file diff --git a/src/SharpCompress/Archives/IWritableArchiveExtensions.cs b/src/SharpCompress/Archives/IWritableArchiveExtensions.cs index bee42a499..00e43c0dc 100644 --- a/src/SharpCompress/Archives/IWritableArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IWritableArchiveExtensions.cs @@ -39,15 +39,21 @@ public static void SaveTo(this IWritableArchive writableArchive, FileInfo fileIn this IWritableArchive writableArchive, string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories) { + using (writableArchive.PauseEntryRebuilding()) + { #if NET35 - foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption)) + foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption)) #else - foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption)) + foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption)) #endif - { - var fileInfo = new FileInfo(path); - writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length, - fileInfo.LastWriteTime); + { + var fileInfo = new FileInfo(path); + writableArchive.AddEntry(path.Substring(filePath.Length), + fileInfo.OpenRead(), + true, + fileInfo.Length, + fileInfo.LastWriteTime); + } } } public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)