diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/fileops.c | 23 | ||||
-rw-r--r-- | src/fileops.h | 17 |
2 files changed, 33 insertions, 7 deletions
diff --git a/src/fileops.c b/src/fileops.c index b3bb3890e..9da1bf789 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -298,13 +298,20 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode) static int _rmdir_recurs_foreach(void *opaque, git_buf *path) { - int force = *(int *)opaque; + enum git_directory_removal_type removal_type = *(enum git_directory_removal_type *)opaque; + + assert(removal_type == GIT_DIRREMOVAL_EMPTY_HIERARCHY + || removal_type == GIT_DIRREMOVAL_FILES_AND_DIRS + || removal_type == GIT_DIRREMOVAL_ONLY_EMPTY_DIRS); if (git_path_isdir(path->ptr) == true) { if (git_path_direach(path, _rmdir_recurs_foreach, opaque) < 0) return -1; if (p_rmdir(path->ptr) < 0) { + if (removal_type == GIT_DIRREMOVAL_ONLY_EMPTY_DIRS && errno == ENOTEMPTY) + return 0; + giterr_set(GITERR_OS, "Could not remove directory '%s'", path->ptr); return -1; } @@ -312,7 +319,7 @@ static int _rmdir_recurs_foreach(void *opaque, git_buf *path) return 0; } - if (force) { + if (removal_type == GIT_DIRREMOVAL_FILES_AND_DIRS) { if (p_unlink(path->ptr) < 0) { giterr_set(GITERR_OS, "Could not remove directory. File '%s' cannot be removed", path->ptr); return -1; @@ -321,18 +328,22 @@ static int _rmdir_recurs_foreach(void *opaque, git_buf *path) return 0; } - giterr_set(GITERR_OS, "Could not remove directory. File '%s' still present", path->ptr); - return -1; + if (removal_type == GIT_DIRREMOVAL_EMPTY_HIERARCHY) { + giterr_set(GITERR_OS, "Could not remove directory. File '%s' still present", path->ptr); + return -1; + } + + return 0; } -int git_futils_rmdir_r(const char *path, int force) +int git_futils_rmdir_r(const char *path, enum git_directory_removal_type removal_type) { int error; git_buf p = GIT_BUF_INIT; error = git_buf_sets(&p, path); if (!error) - error = _rmdir_recurs_foreach(&force, &p); + error = _rmdir_recurs_foreach(&removal_type, &p); git_buf_free(&p); return error; } diff --git a/src/fileops.h b/src/fileops.h index 865b3c9b0..9cc2d1699 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -58,10 +58,25 @@ extern int git_futils_mkdir_r(const char *path, const char *base, const mode_t m */ extern int git_futils_mkpath2file(const char *path, const mode_t mode); +typedef enum { + GIT_DIRREMOVAL_EMPTY_HIERARCHY = 0, + GIT_DIRREMOVAL_FILES_AND_DIRS = 1, + GIT_DIRREMOVAL_ONLY_EMPTY_DIRS = 2, +} git_directory_removal_type; + /** * Remove path and any files and directories beneath it. + * + * @param path Path to to top level directory to process. + * + * @param removal_type GIT_DIRREMOVAL_EMPTY_HIERARCHY to remove a hierarchy + * of empty directories (will fail if any file is found), GIT_DIRREMOVAL_FILES_AND_DIRS + * to remove a hierarchy of files and folders, GIT_DIRREMOVAL_ONLY_EMPTY_DIRS to only remove + * empty directories (no failure on file encounter). + * + * @return 0 on success; -1 on error. */ -extern int git_futils_rmdir_r(const char *path, int force); +extern int git_futils_rmdir_r(const char *path, enum git_directory_removal_type removal_type); /** * Create and open a temporary file with a `_git2_` suffix. |