Browse Source

Implemented file_removeEmptyFolder.

David Piuva 3 years ago
parent
commit
a313e5954a
3 changed files with 75 additions and 3 deletions
  1. 15 1
      Source/DFPSR/api/fileAPI.cpp
  2. 10 2
      Source/DFPSR/api/fileAPI.h
  3. 50 0
      Source/test/tests/FileTest.cpp

+ 15 - 1
Source/DFPSR/api/fileAPI.cpp

@@ -364,7 +364,7 @@ bool file_setCurrentPath(const ReadableString &path) {
 	Buffer buffer;
 	const NativeChar *nativePath = toNativeString(file_optimizePath(path, LOCAL_PATH_SYNTAX), buffer);
 	#ifdef USE_MICROSOFT_WINDOWS
-		return SetCurrentDirectoryW(nativePath);
+		return SetCurrentDirectoryW(nativePath) != 0;
 	#else
 		return chdir(nativePath) == 0;
 	#endif
@@ -644,4 +644,18 @@ bool file_createFolder(const ReadableString &path) {
 	return result;
 }
 
+bool file_removeEmptyFolder(const ReadableString& path) {
+	bool result = false;
+	String optimizedPath = file_optimizePath(path, LOCAL_PATH_SYNTAX);
+	Buffer buffer;
+	const NativeChar *nativePath = toNativeString(optimizedPath, buffer);
+	// Remove the empty folder.
+	#ifdef USE_MICROSOFT_WINDOWS
+		result = (RemoveDirectoryW(nativePath) != 0);
+	#else
+		result = (rmdir(nativePath) == 0);
+	#endif
+	return result;
+}
+
 }

+ 10 - 2
Source/DFPSR/api/fileAPI.h

@@ -24,8 +24,8 @@
 /*
 TODO:
 * Test that overwriting a large file with a smaller file does not leave anything from the overwritten file on any system.
-* bool file_remove(const ReadableString& path);
-	WINBASEAPI WINBOOL WINAPI DeleteFileW (LPCWSTR lpFileName);
+* bool file_removeFile(const ReadableString& path);
+	bool DeleteFileW (LPCWSTR lpFileName);
 */
 
 #ifndef DFPSR_API_FILE
@@ -262,6 +262,14 @@ namespace dsr {
 	// Side-effects: Creates a folder at path.
 	// Post-condition: Returns true iff the operation was successful.
 	bool file_createFolder(const ReadableString &path);
+
+	// Path-syntax: According to the local computer.
+	// Pre-condition: The folder at path must be empty, so any recursion must be done manually.
+	//   Otherwise you might accidentally erase "C:\myFolder\importantDocuments" from giving C:\myFolder \junk instead of "C:\myFolder\junk" as command line arguments.
+	//   Better to implement your own recursive search that confirms for each file and folder that they are no longer needed, for such a dangerous operation.
+	// Side-effects: Removes the folder at path.
+	// Post-condition: Returns true iff the operation was successful.
+	bool file_removeEmptyFolder(const ReadableString& path);
 }
 
 #endif

+ 50 - 0
Source/test/tests/FileTest.cpp

@@ -101,4 +101,54 @@ START_TEST(File)
 		ASSERT_EQUAL(file_hasExtension(U"/folder/file."), true); // Not a named extension, but ending with a dot is not a pure extensionless path either.
 		ASSERT_EQUAL(file_hasExtension(U"/folder/file"), false);
 	}
+	{ // Folder creation and removal
+		// Prepare by removing any old folder from aborted tests.
+		if (file_getEntryType(U"FooBarTestFolder") == EntryType::Folder) file_removeEmptyFolder(U"FooBarTestFolder");
+		// The boolean results are compared with true rather than not-false, because it should still work if someone does that by mistake in the real program.
+		//   All booleans returned from system API calls in fileAPI are normalized to 1 and 0 using either direct assignments or comparisons.
+		//   Normalization using x == 0 or x != 0 is guaranteed to return precisely 1 or 0 according to the C++ standard.
+		// Check that the folder does not exist.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarTestFolder"), EntryType::NotFound);
+		// Create the folder.
+		ASSERT_EQUAL(file_createFolder(U"FooBarTestFolder"), true); 
+		// Check that the folder does exist.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarTestFolder"), EntryType::Folder);
+		// Remove the folder.
+		ASSERT_EQUAL(file_removeEmptyFolder(U"FooBarTestFolder"), true);
+		// Check that the folder does not exist.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarTestFolder"), EntryType::NotFound);
+	}
+	{ // Nested creation and removal
+		String childPathA = file_combinePaths(U"FooBarParent", U"FooBarChildA", LOCAL_PATH_SYNTAX);
+		String childPathB = file_combinePaths(U"FooBarParent", U"FooBarChildB", LOCAL_PATH_SYNTAX);
+		// Prepare by removing any old folder from aborted tests.
+		if (file_getEntryType(childPathA) == EntryType::Folder) file_removeEmptyFolder(childPathA);
+		if (file_getEntryType(childPathB) == EntryType::Folder) file_removeEmptyFolder(childPathB);
+		if (file_getEntryType(U"FooBarParent") == EntryType::Folder) file_removeEmptyFolder(U"FooBarParent");
+		// Check that the folder does not exist.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarParent"), EntryType::NotFound);
+		// Create the folder.
+		ASSERT_EQUAL(file_createFolder(U"FooBarParent"), true); 
+		// Check that the folder does exist.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarParent"), EntryType::Folder);
+		// Create a child folder.
+		ASSERT_EQUAL(file_getEntryType(childPathA), EntryType::NotFound);
+		ASSERT_EQUAL(file_getEntryType(childPathB), EntryType::NotFound);
+		ASSERT_EQUAL(file_createFolder(childPathA), true);
+		ASSERT_EQUAL(file_getEntryType(childPathA), EntryType::Folder);
+		ASSERT_EQUAL(file_getEntryType(childPathB), EntryType::NotFound);
+		ASSERT_EQUAL(file_createFolder(childPathB), true);
+		ASSERT_EQUAL(file_getEntryType(childPathA), EntryType::Folder);
+		ASSERT_EQUAL(file_getEntryType(childPathB), EntryType::Folder);
+		ASSERT_EQUAL(file_removeEmptyFolder(U"FooBarParent"), false); // Trying to remove the parent now should fail.
+		ASSERT_EQUAL(file_removeEmptyFolder(childPathA), true);
+		ASSERT_EQUAL(file_getEntryType(childPathA), EntryType::NotFound);
+		ASSERT_EQUAL(file_getEntryType(childPathB), EntryType::Folder);
+		ASSERT_EQUAL(file_removeEmptyFolder(U"FooBarParent"), false); // Trying to remove the parent now should fail.
+		ASSERT_EQUAL(file_removeEmptyFolder(childPathB), true);
+		ASSERT_EQUAL(file_getEntryType(childPathA), EntryType::NotFound);
+		ASSERT_EQUAL(file_getEntryType(childPathB), EntryType::NotFound);
+		ASSERT_EQUAL(file_removeEmptyFolder(U"FooBarParent"), true); // Trying to remove the parent now should succeed now that it's empty.
+		ASSERT_EQUAL(file_getEntryType(U"FooBarParent"), EntryType::NotFound); // Now the parent folder should no longer exist.
+	}
 END_TEST