diff --git a/BasicNodes/File/DeleteSourceDirectory.cs b/BasicNodes/File/DeleteSourceDirectory.cs index 9fc7f464..95be8339 100644 --- a/BasicNodes/File/DeleteSourceDirectory.cs +++ b/BasicNodes/File/DeleteSourceDirectory.cs @@ -59,12 +59,18 @@ public class DeleteSourceDirectory : Node /// /// the node parameters /// the output to call next, -1 to abort flow, 0 to end flow - private int DeleteTopMostOnly(NodeParameters args) + public int DeleteTopMostOnly(NodeParameters args) { string libraryPath = args.LibraryFileName[..^args.RelativeFile.Length] .TrimEnd('/') .TrimEnd('\\'); string dir = args.OriginalIsDirectory ? args.LibraryFileName : FileHelper.GetDirectory(args.LibraryFileName); + if (string.Equals(dir, libraryPath, StringComparison.InvariantCultureIgnoreCase)) + { + args.Logger?.WLog("Cannot delete library root: " + dir); + return 2; + } + args.Logger?.ILog("Deleting top level directory only: " + dir); var existsResult = args.FileService.DirectoryExists(dir); if (existsResult.Failed(out var error)) diff --git a/BasicNodes/Tests/DeleteSourceDirectoryTests.cs b/BasicNodes/Tests/DeleteSourceDirectoryTests.cs new file mode 100644 index 00000000..be650c45 --- /dev/null +++ b/BasicNodes/Tests/DeleteSourceDirectoryTests.cs @@ -0,0 +1,121 @@ +#if(DEBUG) + +using System.IO; +using FileFlows.BasicNodes.File; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace BasicNodes.Tests; + +[TestClass] +public class DeleteSourceDirectoryTests : TestBase +{ + + [TestMethod] + public void AtLibraryRoot() + { + var args = GetNodeParameters(TempFile); + args.RelativeFile = TempFile[(TempPath.Length + 1)..]; + args.LibraryPath = TempPath; + + var element = new DeleteSourceDirectory(); + element.TopMostOnly = true; + element.PreExecute(args); + + Assert.AreEqual(2, element.Execute(args)); + Assert.IsTrue(Logger.ToString().Contains("Cannot delete library root: ")); + } + + [TestMethod] + public void DeleteSub() + { + string sub1 = Path.Combine(TempPath, "sub1"); + string sub2 = Path.Combine(sub1, "sub2"); + Directory.CreateDirectory(sub2); + string newTemp = Path.Combine(sub2, "testfile.txt"); + System.IO.File.Move(TempFile, newTemp); + + var args = GetNodeParameters(newTemp); + args.RelativeFile = newTemp[(TempPath.Length + 1)..]; + args.LibraryPath = TempPath; + + var element = new DeleteSourceDirectory(); + element.TopMostOnly = true; + element.PreExecute(args); + + Assert.AreEqual(1, element.Execute(args)); + Assert.IsTrue(Directory.Exists(sub1)); + Assert.IsFalse(Directory.Exists(sub2)); + } + + [TestMethod] + public void DeleteSubNotEmpty() + { + string sub1 = Path.Combine(TempPath, "sub1"); + string sub2 = Path.Combine(sub1, "sub2"); + Directory.CreateDirectory(sub2); + string newTemp = Path.Combine(sub2, "testfile.txt"); + System.IO.File.Move(TempFile, newTemp); + + var args = GetNodeParameters(newTemp); + args.RelativeFile = newTemp[(TempPath.Length + 1)..]; + args.LibraryPath = TempPath; + + var element = new DeleteSourceDirectory(); + element.TopMostOnly = true; + element.IfEmpty = true; + element.PreExecute(args); + + Assert.AreEqual(2, element.Execute(args)); + Assert.IsTrue(Directory.Exists(sub1)); + Assert.IsTrue(Directory.Exists(sub2)); + } + + [TestMethod] + public void DeleteSubNotEmpty_Matching_1() + { + string sub1 = Path.Combine(TempPath, "sub1"); + string sub2 = Path.Combine(sub1, "sub2"); + Directory.CreateDirectory(sub2); + string newTemp = Path.Combine(sub2, "testfile.txt"); + System.IO.File.Move(TempFile, newTemp); + + var args = GetNodeParameters(newTemp); + args.RelativeFile = newTemp[(TempPath.Length + 1)..]; + args.LibraryPath = TempPath; + + var element = new DeleteSourceDirectory(); + element.TopMostOnly = true; + element.IfEmpty = true; + element.IncludePatterns = [@"\.txt$"]; + element.PreExecute(args); + + Assert.AreEqual(2, element.Execute(args)); + Assert.IsTrue(Directory.Exists(sub1)); + Assert.IsTrue(Directory.Exists(sub2)); + } + + [TestMethod] + public void DeleteSubNotEmpty_Matching_2() + { + string sub1 = Path.Combine(TempPath, "sub1"); + string sub2 = Path.Combine(sub1, "sub2"); + Directory.CreateDirectory(sub2); + string newTemp = Path.Combine(sub2, "testfile.txt"); + System.IO.File.Move(TempFile, newTemp); + + var args = GetNodeParameters(newTemp); + args.RelativeFile = newTemp[(TempPath.Length + 1)..]; + args.LibraryPath = TempPath; + + var element = new DeleteSourceDirectory(); + element.TopMostOnly = true; + element.IfEmpty = true; + element.IncludePatterns = [@"\.csv"]; + element.PreExecute(args); + + Assert.AreEqual(1, element.Execute(args)); + Assert.IsTrue(Directory.Exists(sub1)); + Assert.IsFalse(Directory.Exists(sub2)); + } +} +#endif \ No newline at end of file diff --git a/BasicNodes/i18n/en.json b/BasicNodes/i18n/en.json index d7e7bfa1..72db3207 100644 --- a/BasicNodes/i18n/en.json +++ b/BasicNodes/i18n/en.json @@ -134,7 +134,9 @@ "IfEmpty": "If Empty", "IfEmpty-Help": "Only delete the source folder if the it is empty", "IncludePatterns": "Include Patterns", - "IncludePatterns-Help": "Optional, if set only files matching these patterns will be counted to see if the folder is empty. Any of these patterns can match." + "IncludePatterns-Help": "Optional, if set only files matching these patterns will be counted to see if the folder is empty. Any of these patterns can match.", + "TopMostOnly": "Topmost Folder Only", + "TopMostOnly-Help": "When enabled, only the folder directly containing the file will be deleted, leaving higher-level folders intact." } }, "Executor": {