From 14cdc858ce61004e4f56de49c6a69d08a47a3bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Fri, 22 Oct 2021 12:17:59 +0200 Subject: [PATCH] feat(fastzip): allow custom filesystemscanner --- .../Core/FileSystemScanner.cs | 261 +++++------------- src/ICSharpCode.SharpZipLib/Zip/FastZip.cs | 92 ++---- 2 files changed, 97 insertions(+), 256 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Core/FileSystemScanner.cs b/src/ICSharpCode.SharpZipLib/Core/FileSystemScanner.cs index 427e7d895..69bc1c615 100644 --- a/src/ICSharpCode.SharpZipLib/Core/FileSystemScanner.cs +++ b/src/ICSharpCode.SharpZipLib/Core/FileSystemScanner.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace ICSharpCode.SharpZipLib.Core { @@ -9,42 +12,24 @@ namespace ICSharpCode.SharpZipLib.Core /// public class ScanEventArgs : EventArgs { - #region Constructors - /// /// Initialise a new instance of /// /// The file or directory name. public ScanEventArgs(string name) { - name_ = name; + Name = name; } - #endregion Constructors - /// /// The file or directory name for this event. /// - public string Name - { - get { return name_; } - } + public string Name { get; } /// /// Get set a value indicating if scanning should continue or not. /// - public bool ContinueRunning - { - get { return continueRunning_; } - set { continueRunning_ = value; } - } - - #region Instance Fields - - private string name_; - private bool continueRunning_ = true; - - #endregion Instance Fields + public bool ContinueRunning { get; set; } = true; } /// @@ -52,8 +37,6 @@ public bool ContinueRunning /// public class ProgressEventArgs : EventArgs { - #region Constructors - /// /// Initialise a new instance of /// @@ -62,76 +45,37 @@ public class ProgressEventArgs : EventArgs /// The total number of bytes to process, 0 if not known public ProgressEventArgs(string name, long processed, long target) { - name_ = name; - processed_ = processed; - target_ = target; + Name = name; + Processed = processed; + Target = target; } - #endregion Constructors - /// /// The name for this event if known. /// - public string Name - { - get { return name_; } - } + public string Name { get; } /// /// Get set a value indicating whether scanning should continue or not. /// - public bool ContinueRunning - { - get { return continueRunning_; } - set { continueRunning_ = value; } - } + public bool ContinueRunning { get; set; } = true; /// /// Get a percentage representing how much of the has been processed /// /// 0.0 to 100.0 percent; 0 if target is not known. - public float PercentComplete - { - get - { - float result; - if (target_ <= 0) - { - result = 0; - } - else - { - result = ((float)processed_ / (float)target_) * 100.0f; - } - return result; - } - } + public float PercentComplete => Target <= 0 ? 0 : ((float)Processed / (float)Target) * 100.0f; /// /// The number of bytes processed so far /// - public long Processed - { - get { return processed_; } - } + public long Processed { get; } /// /// The number of bytes to process. /// /// Target may be 0 or negative if the value isnt known. - public long Target - { - get { return target_; } - } - - #region Instance Fields - - private string name_; - private long processed_; - private long target_; - private bool continueRunning_ = true; - - #endregion Instance Fields + public long Target { get; } } /// @@ -139,8 +83,6 @@ public long Target /// public class DirectoryEventArgs : ScanEventArgs { - #region Constructors - /// /// Initialize an instance of . /// @@ -149,26 +91,13 @@ public class DirectoryEventArgs : ScanEventArgs public DirectoryEventArgs(string name, bool hasMatchingFiles) : base(name) { - hasMatchingFiles_ = hasMatchingFiles; + HasMatchingFiles = hasMatchingFiles; } - #endregion Constructors - /// /// Get a value indicating if the directory contains any matching files or not. /// - public bool HasMatchingFiles - { - get { return hasMatchingFiles_; } - } - - private readonly - - #region Instance Fields - - bool hasMatchingFiles_; - - #endregion Instance Fields + public bool HasMatchingFiles { get; } } /// @@ -185,9 +114,8 @@ public class ScanFailureEventArgs : EventArgs /// The exception to use. public ScanFailureEventArgs(string name, Exception e) { - name_ = name; - exception_ = e; - continueRunning_ = true; + Name = name; + Exception = e; } #endregion Constructors @@ -195,35 +123,17 @@ public ScanFailureEventArgs(string name, Exception e) /// /// The applicable name. /// - public string Name - { - get { return name_; } - } + public string Name { get; } /// /// The applicable exception. /// - public Exception Exception - { - get { return exception_; } - } + public Exception Exception { get; } /// /// Get / set a value indicating whether scanning should continue. /// - public bool ContinueRunning - { - get { return continueRunning_; } - set { continueRunning_ = value; } - } - - #region Instance Fields - - private string name_; - private Exception exception_; - private bool continueRunning_; - - #endregion Instance Fields + public bool ContinueRunning { get; set; } = true; } #endregion EventArgs @@ -352,15 +262,12 @@ public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter) /// The exception detected. private bool OnDirectoryFailure(string directory, Exception e) { - DirectoryFailureHandler handler = DirectoryFailure; - bool result = (handler != null); - if (result) - { - var args = new ScanFailureEventArgs(directory, e); - handler(this, args); - alive_ = args.ContinueRunning; - } - return result; + if (DirectoryFailure == null) return false; + + var args = new ScanFailureEventArgs(directory, e); + DirectoryFailure(this, args); + alive_ = args.ContinueRunning; + return true; } /// @@ -370,17 +277,12 @@ private bool OnDirectoryFailure(string directory, Exception e) /// The exception detected. private bool OnFileFailure(string file, Exception e) { - FileFailureHandler handler = FileFailure; - - bool result = (handler != null); - - if (result) - { - var args = new ScanFailureEventArgs(file, e); - FileFailure(this, args); - alive_ = args.ContinueRunning; - } - return result; + if (FileFailure == null) return false; + + var args = new ScanFailureEventArgs(file, e); + FileFailure(this, args); + alive_ = args.ContinueRunning; + return true; } /// @@ -389,14 +291,11 @@ private bool OnFileFailure(string file, Exception e) /// The file name. private void OnProcessFile(string file) { - ProcessFileHandler handler = ProcessFile; - - if (handler != null) - { - var args = new ScanEventArgs(file); - handler(this, args); - alive_ = args.ContinueRunning; - } + if (ProcessFile == null) return; + + var args = new ScanEventArgs(file); + ProcessFile(this, args); + alive_ = args.ContinueRunning; } /// @@ -405,14 +304,10 @@ private void OnProcessFile(string file) /// The file name private void OnCompleteFile(string file) { - CompletedFileHandler handler = CompletedFile; - - if (handler != null) - { - var args = new ScanEventArgs(file); - handler(this, args); - alive_ = args.ContinueRunning; - } + if (CompletedFile == null) return; + var args = new ScanEventArgs(file); + CompletedFile(this, args); + alive_ = args.ContinueRunning; } /// @@ -443,39 +338,37 @@ public void Scan(string directory, bool recurse) ScanDir(directory, recurse); } + /// + /// The method used to enumerate files in the supplied + /// + /// + protected virtual IEnumerable GetFiles(string directory) => Directory.EnumerateFiles(directory); + + /// + /// The method used to enumerate directories in the supplied + /// + /// + protected virtual IEnumerable GetDirectories(string directory) => Directory.EnumerateDirectories(directory); + private void ScanDir(string directory, bool recurse) { try { - string[] names = System.IO.Directory.GetFiles(directory); - bool hasMatch = false; - for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) - { - if (!fileFilter_.IsMatch(names[fileIndex])) - { - names[fileIndex] = null; - } - else - { - hasMatch = true; - } - } - + var names = GetFiles(directory).Where(fileFilter_.IsMatch).ToArray(); + var hasMatch = names.Any(); + OnProcessDirectory(directory, hasMatch); if (alive_ && hasMatch) { - foreach (string fileName in names) + foreach (var fileName in names) { try { - if (fileName != null) + OnProcessFile(fileName); + if (!alive_) { - OnProcessFile(fileName); - if (!alive_) - { - break; - } + break; } } catch (Exception e) @@ -496,31 +389,29 @@ private void ScanDir(string directory, bool recurse) } } - if (alive_ && recurse) + if (!alive_ || !recurse) return; + + try { - try + var subDirectories = GetDirectories(directory) + .Where(d => d != null && directoryFilter_.IsMatch(d)); + foreach (var fulldir in subDirectories) { - string[] names = System.IO.Directory.GetDirectories(directory); - foreach (string fulldir in names) + ScanDir(fulldir, recurse: true); + if (!alive_) { - if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) - { - ScanDir(fulldir, true); - if (!alive_) - { - break; - } - } + break; } } - catch (Exception e) + } + catch (Exception e) + { + if (!OnDirectoryFailure(directory, e)) { - if (!OnDirectoryFailure(directory, e)) - { - throw; - } + throw; } } + } #region Instance Fields diff --git a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs index 13aedb021..89a3588c0 100644 --- a/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs +++ b/src/ICSharpCode.SharpZipLib/Zip/FastZip.cs @@ -206,7 +206,7 @@ public FastZip() public FastZip(TimeSetting timeSetting) { entryFactory_ = new ZipEntryFactory(timeSetting); - restoreDateTimeOnExtract_ = true; + RestoreDateTimeOnExtract = true; } /// @@ -216,7 +216,7 @@ public FastZip(TimeSetting timeSetting) public FastZip(DateTime time) { entryFactory_ = new ZipEntryFactory(time); - restoreDateTimeOnExtract_ = true; + RestoreDateTimeOnExtract = true; } /// @@ -235,20 +235,12 @@ public FastZip(FastZipEvents events) /// /// Get/set a value indicating whether empty directories should be created. /// - public bool CreateEmptyDirectories - { - get { return createEmptyDirectories_; } - set { createEmptyDirectories_ = value; } - } + public bool CreateEmptyDirectories { get; set; } /// /// Get / set the password value. /// - public string Password - { - get { return password_; } - set { password_ = value; } - } + public string Password { get; set; } /// /// Get / set the method of encrypting entries. @@ -265,11 +257,8 @@ public string Password /// public INameTransform NameTransform { - get { return entryFactory_.NameTransform; } - set - { - entryFactory_.NameTransform = value; - } + get => entryFactory_.NameTransform; + set => entryFactory_.NameTransform = value; } /// @@ -277,18 +266,8 @@ public INameTransform NameTransform /// public IEntryFactory EntryFactory { - get { return entryFactory_; } - set - { - if (value == null) - { - entryFactory_ = new ZipEntryFactory(); - } - else - { - entryFactory_ = value; - } - } + get => entryFactory_; + set => entryFactory_ = value ?? new ZipEntryFactory(); } /// @@ -302,48 +281,26 @@ public IEntryFactory EntryFactory /// NOTE: Setting the size for entries before they are added is the best solution! /// By default the EntryFactory used by FastZip will set the file size. /// - public UseZip64 UseZip64 - { - get { return useZip64_; } - set { useZip64_ = value; } - } + public UseZip64 UseZip64 { get; set; } = UseZip64.Dynamic; /// /// Get/set a value indicating whether file dates and times should /// be restored when extracting files from an archive. /// /// The default value is false. - public bool RestoreDateTimeOnExtract - { - get - { - return restoreDateTimeOnExtract_; - } - set - { - restoreDateTimeOnExtract_ = value; - } - } + public bool RestoreDateTimeOnExtract { get; set; } /// /// Get/set a value indicating whether file attributes should /// be restored during extract operations /// - public bool RestoreAttributesOnExtract - { - get { return restoreAttributesOnExtract_; } - set { restoreAttributesOnExtract_ = value; } - } + public bool RestoreAttributesOnExtract { get; set; } /// /// Get/set the Compression Level that will be used /// when creating the zip /// - public Deflater.CompressionLevel CompressionLevel - { - get { return compressionLevel_; } - set { compressionLevel_ = value; } - } + public Deflater.CompressionLevel CompressionLevel { get; set; } = CompressionLevel.DEFAULT_COMPRESSION; /// /// Reflects the opposite of the internal , setting it to false overrides the encoding used for reading and writing zip entries @@ -474,7 +431,7 @@ public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, /// For performing the actual file system scan /// true to leave open after the zip has been created, false to dispose it. /// The is closed after creation. - private void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, FileSystemScanner scanner, bool leaveOpen) + public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, FileSystemScanner scanner, bool leaveOpen) { NameTransform = new ZipNameTransform(sourceDirectory); sourceDirectory_ = sourceDirectory; @@ -485,9 +442,9 @@ private void CreateZip(Stream outputStream, string sourceDirectory, bool recurse outputStream_.IsStreamOwner = !leaveOpen; outputStream_.NameTransform = null; // all required transforms handled by us - if (false == string.IsNullOrEmpty(password_) && EntryEncryptionMethod != ZipEncryptionMethod.None) + if (false == string.IsNullOrEmpty(Password) && EntryEncryptionMethod != ZipEncryptionMethod.None) { - outputStream_.Password = password_; + outputStream_.Password = Password; } outputStream_.UseZip64 = UseZip64; @@ -526,7 +483,7 @@ private void CreateZip(Stream outputStream, string sourceDirectory, bool recurse /// A filter to apply to files. public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter) { - ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, restoreDateTimeOnExtract_); + ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, RestoreDateTimeOnExtract); } /// @@ -577,13 +534,13 @@ public void ExtractZip(string zipFileName, string targetDirectory, string fileFi fileFilter_ = new NameFilter(fileFilter); directoryFilter_ = new NameFilter(directoryFilter); - restoreDateTimeOnExtract_ = restoreDateTime; + RestoreDateTimeOnExtract = restoreDateTime; using (zipFile_ = new ZipFile(inputStream, !isStreamOwner)) { - if (password_ != null) + if (Password != null) { - zipFile_.Password = password_; + zipFile_.Password = Password; } System.Collections.IEnumerator enumerator = zipFile_.GetEnumerator(); @@ -784,7 +741,7 @@ private void ExtractFileEntry(ZipEntry entry, string targetName) } } - if (restoreDateTimeOnExtract_) + if (RestoreDateTimeOnExtract) { switch (entryFactory_.Setting) { @@ -890,7 +847,7 @@ private void ExtractEntry(ZipEntry entry) if (continueRunning_) { Directory.CreateDirectory(dirName); - if (entry.IsDirectory && restoreDateTimeOnExtract_) + if (entry.IsDirectory && RestoreDateTimeOnExtract) { switch (entryFactory_.Setting) { @@ -986,18 +943,11 @@ private static bool NameIsValid(string name) private Overwrite overwrite_; private ConfirmOverwriteDelegate confirmDelegate_; - private bool restoreDateTimeOnExtract_; - private bool restoreAttributesOnExtract_; - private bool createEmptyDirectories_; private FastZipEvents events_; private IEntryFactory entryFactory_ = new ZipEntryFactory(); private INameTransform extractNameTransform_; - private UseZip64 useZip64_ = UseZip64.Dynamic; - private CompressionLevel compressionLevel_ = CompressionLevel.DEFAULT_COMPRESSION; private StringCodec _stringCodec = new StringCodec(); - private string password_; - #endregion Instance Fields } }