Skip to content

Commit 7155b72

Browse files
dschogitster
authored andcommitted
Introduce remove_dir_recursively()
There was a function called remove_empty_dir_recursive() buried in refs.c. Expose a slightly enhanced version in dir.h: it can now optionally remove a non-empty directory. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 90446a0 commit 7155b72

File tree

3 files changed

+55
-45
lines changed

3 files changed

+55
-45
lines changed

dir.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,44 @@ int is_inside_dir(const char *dir)
685685
char buffer[PATH_MAX];
686686
return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
687687
}
688+
689+
int remove_dir_recursively(struct strbuf *path, int only_empty)
690+
{
691+
DIR *dir = opendir(path->buf);
692+
struct dirent *e;
693+
int ret = 0, original_len = path->len, len;
694+
695+
if (!dir)
696+
return -1;
697+
if (path->buf[original_len - 1] != '/')
698+
strbuf_addch(path, '/');
699+
700+
len = path->len;
701+
while ((e = readdir(dir)) != NULL) {
702+
struct stat st;
703+
if ((e->d_name[0] == '.') &&
704+
((e->d_name[1] == 0) ||
705+
((e->d_name[1] == '.') && e->d_name[2] == 0)))
706+
continue; /* "." and ".." */
707+
708+
strbuf_setlen(path, len);
709+
strbuf_addstr(path, e->d_name);
710+
if (lstat(path->buf, &st))
711+
; /* fall thru */
712+
else if (S_ISDIR(st.st_mode)) {
713+
if (!remove_dir_recursively(path, only_empty))
714+
continue; /* happy */
715+
} else if (!only_empty && !unlink(path->buf))
716+
continue; /* happy, too */
717+
718+
/* path too long, stat fails, or non-directory still exists */
719+
ret = -1;
720+
break;
721+
}
722+
closedir(dir);
723+
724+
strbuf_setlen(path, original_len);
725+
if (!ret)
726+
ret = rmdir(path->buf);
727+
return ret;
728+
}

dir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
6464
extern char *get_relative_cwd(char *buffer, int size, const char *dir);
6565
extern int is_inside_dir(const char *dir);
6666

67+
extern int remove_dir_recursively(struct strbuf *path, int only_empty);
68+
6769
#endif

refs.c

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "refs.h"
33
#include "object.h"
44
#include "tag.h"
5+
#include "dir.h"
56

67
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
78
#define REF_KNOWS_PEELED 04
@@ -671,57 +672,23 @@ static struct ref_lock *verify_lock(struct ref_lock *lock,
671672
return lock;
672673
}
673674

674-
static int remove_empty_dir_recursive(char *path, int len)
675-
{
676-
DIR *dir = opendir(path);
677-
struct dirent *e;
678-
int ret = 0;
679-
680-
if (!dir)
681-
return -1;
682-
if (path[len-1] != '/')
683-
path[len++] = '/';
684-
while ((e = readdir(dir)) != NULL) {
685-
struct stat st;
686-
int namlen;
687-
if ((e->d_name[0] == '.') &&
688-
((e->d_name[1] == 0) ||
689-
((e->d_name[1] == '.') && e->d_name[2] == 0)))
690-
continue; /* "." and ".." */
691-
692-
namlen = strlen(e->d_name);
693-
if ((len + namlen < PATH_MAX) &&
694-
strcpy(path + len, e->d_name) &&
695-
!lstat(path, &st) &&
696-
S_ISDIR(st.st_mode) &&
697-
!remove_empty_dir_recursive(path, len + namlen))
698-
continue; /* happy */
699-
700-
/* path too long, stat fails, or non-directory still exists */
701-
ret = -1;
702-
break;
703-
}
704-
closedir(dir);
705-
if (!ret) {
706-
path[len] = 0;
707-
ret = rmdir(path);
708-
}
709-
return ret;
710-
}
711-
712-
static int remove_empty_directories(char *file)
675+
static int remove_empty_directories(const char *file)
713676
{
714677
/* we want to create a file but there is a directory there;
715678
* if that is an empty directory (or a directory that contains
716679
* only empty directories), remove them.
717680
*/
718-
char path[PATH_MAX];
719-
int len = strlen(file);
681+
struct strbuf path;
682+
int result;
720683

721-
if (len >= PATH_MAX) /* path too long ;-) */
722-
return -1;
723-
strcpy(path, file);
724-
return remove_empty_dir_recursive(path, len);
684+
strbuf_init(&path, 20);
685+
strbuf_addstr(&path, file);
686+
687+
result = remove_dir_recursively(&path, 1);
688+
689+
strbuf_release(&path);
690+
691+
return result;
725692
}
726693

727694
static int is_refname_available(const char *ref, const char *oldref,

0 commit comments

Comments
 (0)