Add new option to recursive_delete: keep_parent_dir
authorThomas Jarosch <thomas.jarosch@intra2net.com>
Tue, 15 Dec 2015 10:06:24 +0000 (11:06 +0100)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Tue, 15 Dec 2015 10:06:58 +0000 (11:06 +0100)
Also added unit tests for the new feature.

src/filefunc.cpp
src/filefunc.hxx
test/test_filefunc.cpp

index c061e08..4316048 100644 (file)
@@ -731,10 +731,13 @@ bool chown(const std::string& path, const I2n::User& user, const I2n::Group& gro
 /**
  * Recursive delete of files and directories
  * @param path File or directory to delete
+ * @param keep_parent_dir Keep parent directory (=empty out directory) [optional]
  * @param error Will contain the error if the return value is false [optional]
  * @return true on success, false otherwise
  */
-bool recursive_delete(const std::string &path, std::string *error)
+bool recursive_delete(const std::string &path,
+                      bool keep_parent_dir,
+                      std::string *error)
 {
     bool rtn = true;
 
@@ -759,14 +762,14 @@ bool recursive_delete(const std::string &path, std::string *error)
                 }
 
                 // Delete subdir or file.
-                rtn = recursive_delete(path + "/" + filename, error);
+                rtn = recursive_delete(path + "/" + filename, false, error);
                 if (rtn == false) {
                     break;
                 }
             }
 
             closedir(dir);
-            if (!rmdir(path)) {
+            if (keep_parent_dir == false && !rmdir(path)) {
                 throw runtime_error("can't remove directory " + path);
             }
         } else {
index acfd637..a2f4bc0 100644 (file)
@@ -177,7 +177,9 @@ bool dirsync(const std::string& path);
 bool chmod(const std::string& path, int mode);
 bool chown(const std::string& path, const I2n::User& user, const I2n::Group& group= I2n::Group());
 
-bool recursive_delete(const std::string &path, std::string *error=NULL);
+bool recursive_delete(const std::string &path,
+                      bool keep_parent_dir=false,
+                      std::string *error=NULL);
 
 std::string mkdtemp(const std::string &path_template, std::string *error=NULL);
 bool mkdir(const std::string &path, const mode_t &mode=0700, std::string *error=NULL);
@@ -192,8 +194,9 @@ mode_t umask(mode_t mask);
 /*
 ** more specialized tool function(s)
 */
-bool remove_unlisted_files(const std::string &directory, const std::set<std::string> &keep_files,
-                                            const std::string &prefix="");
+bool remove_unlisted_files(const std::string &directory,
+                           const std::set<std::string> &keep_files,
+                           const std::string &prefix="");
 
 }
 
index 6dbf24b..88515d1 100644 (file)
@@ -360,7 +360,56 @@ BOOST_AUTO_TEST_CASE(TestMkdtemp)
     BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
 
     // Unlink it
+    BOOST_CHECK_EQUAL(true, rmdir(unique_dir));
+}
+
+BOOST_AUTO_TEST_CASE(TestRecursiveDelete)
+{
+    // Create unique directory
+    string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
+    BOOST_REQUIRE(unique_dir.size() > 0);
+
+    // Test if it's really a directory
+    BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
+
+    // Create dirs and files below it
+    const std::string sub_dir = unique_dir + "/" + "some_subdir";
+    const std::string some_file = sub_dir + "/" + "some_file";
+    BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
+    BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
+
+    // Unlink it
     BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir));
+    BOOST_CHECK_EQUAL(false, Stat(unique_dir).is_directory());
+}
+
+BOOST_AUTO_TEST_CASE(TestRecursiveDeleteKeepParentDir)
+{
+    // Create unique directory
+    string unique_dir = I2n::mkdtemp("foobar.XXXXXX");
+    BOOST_REQUIRE(unique_dir.size() > 0);
+
+    // Test if it's really a directory
+    BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
+
+    // Create dirs and files below it
+    const std::string sub_dir = unique_dir + "/" + "some_subdir";
+    const std::string some_file = sub_dir + "/" + "some_file";
+    const std::string other_file = unique_dir + "/" + "other_file";
+
+    BOOST_CHECK_EQUAL(true, I2n::mkdir(sub_dir));
+    BOOST_CHECK_EQUAL(true, write_file(some_file, "foobar"));
+    BOOST_CHECK_EQUAL(true, write_file(other_file, "foobar"));
+
+    // Unlink it
+    BOOST_CHECK_EQUAL(true, I2n::recursive_delete(unique_dir, true));
+
+    // check result
+    BOOST_CHECK_EQUAL(true, Stat(unique_dir).is_directory());
+    BOOST_CHECK_EQUAL(false, Stat(sub_dir).is_directory());
+    BOOST_CHECK_EQUAL(false, Stat(other_file).is_regular_file());
+
+    BOOST_CHECK_EQUAL(true, I2n::rmdir(unique_dir));
 }
 
 BOOST_AUTO_TEST_CASE(TestMkdtempBrokenTemplate)