diff --git a/nob.h b/nob.h index 8ef6c3f..1c02fe9 100644 --- a/nob.h +++ b/nob.h @@ -285,6 +285,7 @@ NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children); NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size); NOBDEF Nob_File_Type nob_get_file_type(const char *path); NOBDEF bool nob_delete_file(const char *path); +NOBDEF bool nob_delete_dir(const char *path); #define nob_return_defer(value) do { result = (value); goto defer; } while(0) @@ -1422,6 +1423,47 @@ NOBDEF bool nob_delete_file(const char *path) #endif // _WIN32 } +NOBDEF bool nob_delete_dir(const char *path) +{ + bool result = true; + nob_log(NOB_INFO, "deleting %s", path); + Nob_File_Paths children = {0}; + if (!nob_read_entire_dir(path, &children)) return false; + for (size_t i = 0; i < children.count; ++i) { + const char *child = children.items[i]; + Nob_String_Builder child_path = {0}; + nob_sb_append_cstr(&child_path, path); + nob_sb_append_cstr(&child_path, "/"); + nob_sb_append_cstr(&child_path, child); + nob_sb_append_null(&child_path); + Nob_File_Type type = nob_get_file_type(child_path.items); + if (type < 0) { + nob_return_defer(false); + } + if (type == NOB_FILE_DIRECTORY) { + if (strcmp(child, ".") != 0 && strcmp(child, "..") != 0) { + if (!nob_delete_dir(child_path.items)) { + nob_return_defer(false); + } + } + } else { + if (!nob_delete_file(child_path.items)) { + nob_return_defer(false); + } + } + nob_sb_free(child_path); + continue; + + defer: + nob_sb_free(child_path); + return result; + } + if (!nob_delete_file(path)) { + result = false; + } + return result; +} + NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path) { bool result = true; @@ -2003,6 +2045,7 @@ NOBDEF int closedir(DIR *dirp) #define write_entire_file nob_write_entire_file #define get_file_type nob_get_file_type #define delete_file nob_delete_file + #define delete_dir nob_delete_dir #define return_defer nob_return_defer #define da_append nob_da_append #define da_free nob_da_free diff --git a/tests/delete_dir.c b/tests/delete_dir.c new file mode 100644 index 0000000..c1d0bf8 --- /dev/null +++ b/tests/delete_dir.c @@ -0,0 +1,41 @@ +#include "shared.h" +#define NOB_IMPLEMENTATION +#define NOB_STRIP_PREFIX +#include "nob.h" + +bool create_dirs() +{ + if (!nob_mkdir_if_not_exists("delete_dir")) return false; + if (!nob_mkdir_if_not_exists("delete_dir/nested")) return false; + if (!write_entire_file("delete_dir/bar.txt", NULL, 0)) return false; + if (!write_entire_file("delete_dir/baz.txt", NULL, 0)) return false; + if (!write_entire_file("delete_dir/nested/foo.txt", NULL, 0)) return false; + if (!write_entire_file("delete_dir/nested/bar.txt", NULL, 0)) return false; + if (!write_entire_file("delete_dir/nested/baz.txt", NULL, 0)) return false; + return true; +} + +bool delete_dir_without_symlinks() +{ + if (!create_dirs()) return false; + if (!nob_delete_dir("delete_dir")) return false; + if (nob_file_exists("delete_dir")) return false; + return true; +} + +bool delete_dir_with_symlinks() +{ + if (!create_dirs()) return false; + if (symlink("delete_dir/nested", "delete_dir/nested/link") != 0) return false; + if (!nob_delete_dir("delete_dir")) return false; + if (nob_file_exists("delete_dir")) return false; + return true; +} + +int main(void) +{ + if (!delete_dir_without_symlinks()) return 1; + if (!delete_dir_with_symlinks()) return 1; + + return 0; +}