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": {