Fisheye: Tag 0af8a75694d1f18b587fc6e18525f8f0d0f27227 refers to a dead (removed) revision in file `Core/Common/src/Core.Common.IO/DirectoryHelper.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Core/Common/src/Core.Common.Util/DirectoryHelper.cs =================================================================== diff -u --- Core/Common/src/Core.Common.Util/DirectoryHelper.cs (revision 0) +++ Core/Common/src/Core.Common.Util/DirectoryHelper.cs (revision 0af8a75694d1f18b587fc6e18525f8f0d0f27227) @@ -0,0 +1,81 @@ +// Copyright (C) Stichting Deltares 2021. All rights reserved. +// +// This file is part of Riskeer. +// +// Riskeer is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System; +using System.IO; +using System.Threading; + +namespace Core.Common.Util +{ + /// + /// Class containing helper methods for correctly dealing with directories. + /// + public static class DirectoryHelper + { + /// + /// Tries to delete the directory specified by . + /// + /// The path of the directory to delete. + /// The number of retries in case an occurs. + /// This helper method is a solution to latency issues caused by file locks, which normally cause an + /// . The file locks at stake will be released as soon as the application becomes idle, + /// which explains retrying the delete action for times. + /// Thrown when: + /// + /// a file with the same name and location exists; + /// the directory is read-only; + /// the directory is the application's current working directory; + /// the directory contains a read-only file; + /// the directory is being used by another process. + /// + /// + /// Thrown when the caller does not have the required permissions. + /// Thrown when the specified path is a zero-length string, contains only white spaces, or contains one or more invalid characters. + /// Thrown when is null. + /// Thrown when the specified path exceeds the system defined maximum length. + /// Thrown when the specified path: + /// + /// does not exist or could not be found; + /// is invalid (for example, it is on an unmapped drive). + /// + /// + public static void TryDelete(string path, int numberOfRetries = 5) + { + try + { + Directory.Delete(path, true); + } + catch (IOException) + { + if (numberOfRetries != 0) + { + Thread.Sleep(100); + + TryDelete(path, numberOfRetries - 1); + } + else + { + throw; + } + } + } + } +} \ No newline at end of file Fisheye: Tag 0af8a75694d1f18b587fc6e18525f8f0d0f27227 refers to a dead (removed) revision in file `Core/Common/test/Core.Common.IO.Test/DirectoryHelperTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Index: Core/Common/test/Core.Common.TestUtil/DirectoryDisposeHelper.cs =================================================================== diff -u -rd70be6f1085d61194caa344db80ba4938fd08218 -r0af8a75694d1f18b587fc6e18525f8f0d0f27227 --- Core/Common/test/Core.Common.TestUtil/DirectoryDisposeHelper.cs (.../DirectoryDisposeHelper.cs) (revision d70be6f1085d61194caa344db80ba4938fd08218) +++ Core/Common/test/Core.Common.TestUtil/DirectoryDisposeHelper.cs (.../DirectoryDisposeHelper.cs) (revision 0af8a75694d1f18b587fc6e18525f8f0d0f27227) @@ -23,7 +23,7 @@ using System.IO; using System.Linq; using System.Security.AccessControl; -using Core.Common.IO; +using Core.Common.Util; namespace Core.Common.TestUtil { Index: Core/Common/test/Core.Common.Util.Test/DirectoryHelperTest.cs =================================================================== diff -u --- Core/Common/test/Core.Common.Util.Test/DirectoryHelperTest.cs (revision 0) +++ Core/Common/test/Core.Common.Util.Test/DirectoryHelperTest.cs (revision 0af8a75694d1f18b587fc6e18525f8f0d0f27227) @@ -0,0 +1,57 @@ +// Copyright (C) Stichting Deltares 2021. All rights reserved. +// +// This file is part of Riskeer. +// +// Riskeer is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using System.IO; +using System.IO.Compression; +using Core.Common.TestUtil; +using NUnit.Framework; + +namespace Core.Common.Util.Test +{ + [TestFixture] + public class DirectoryHelperTest + { + [Test] + public void GivenDirectoryWithFilesThatAreLockedDueToSystemLatency_WhenCallingTryDelete_ThenDirectoryCorrectlyRemoved() + { + // Given + string folderPath = TestHelper.GetScratchPadPath($"{nameof(DirectoryHelperTest)}.{nameof(GivenDirectoryWithFilesThatAreLockedDueToSystemLatency_WhenCallingTryDelete_ThenDirectoryCorrectlyRemoved)}"); + string nestedFolderPath = Path.Combine(folderPath, "Nested"); + string zipPath = Path.Combine(folderPath, "Archive.zip"); + + Directory.CreateDirectory(nestedFolderPath); + + using (File.Create(Path.Combine(nestedFolderPath, "File1.txt"))) {} + + using (File.Create(Path.Combine(nestedFolderPath, "File2.txt"))) {} + + using (File.Create(Path.Combine(nestedFolderPath, "File3.txt"))) {} + + ZipFile.CreateFromDirectory(nestedFolderPath, zipPath); + + // When + DirectoryHelper.TryDelete(folderPath); + + // Then + Assert.IsFalse(Directory.Exists(folderPath)); + } + } +} \ No newline at end of file Index: Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.IO/Exporters/MacroStabilityInwardsCalculationGroupExporter.cs =================================================================== diff -u -rd70be6f1085d61194caa344db80ba4938fd08218 -r0af8a75694d1f18b587fc6e18525f8f0d0f27227 --- Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.IO/Exporters/MacroStabilityInwardsCalculationGroupExporter.cs (.../MacroStabilityInwardsCalculationGroupExporter.cs) (revision d70be6f1085d61194caa344db80ba4938fd08218) +++ Riskeer/MacroStabilityInwards/src/Riskeer.MacroStabilityInwards.IO/Exporters/MacroStabilityInwardsCalculationGroupExporter.cs (.../MacroStabilityInwardsCalculationGroupExporter.cs) (revision 0af8a75694d1f18b587fc6e18525f8f0d0f27227) @@ -26,7 +26,6 @@ using Components.Persistence.Stability; using Core.Common.Base.Data; using Core.Common.Base.IO; -using Core.Common.IO; using Core.Common.IO.Exceptions; using Core.Common.Util; using log4net;