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 | 22 ++++++++++------ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 5f38d459..71a8d3c1 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -12,11 +12,28 @@ namespace SharpCompress.Archives 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 @@ namespace SharpCompress.Archives } } + 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 380d6814..3b1b0328 100644 --- a/src/SharpCompress/Archives/IWritableArchive.cs +++ b/src/SharpCompress/Archives/IWritableArchive.cs @@ -11,5 +11,11 @@ namespace SharpCompress.Archives 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 bee42a49..00e43c0d 100644 --- a/src/SharpCompress/Archives/IWritableArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IWritableArchiveExtensions.cs @@ -39,15 +39,21 @@ namespace SharpCompress.Archives this IWritableArchive writableArchive, string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories) { -#if NET35 - foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption)) -#else - foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption)) -#endif + using (writableArchive.PauseEntryRebuilding()) { - var fileInfo = new FileInfo(path); - writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length, - fileInfo.LastWriteTime); +#if NET35 + foreach (var path in Directory.GetFiles(filePath, searchPattern, searchOption)) +#else + 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); + } } } public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)