Skip to content

Commit

Permalink
Introduce remove_dir_recursively()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dscho authored and gitster committed Sep 30, 2007
1 parent 90446a0 commit 7155b72
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 45 deletions.
41 changes: 41 additions & 0 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,3 +685,44 @@ int is_inside_dir(const char *dir)
char buffer[PATH_MAX];
return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
}

int remove_dir_recursively(struct strbuf *path, int only_empty)
{
DIR *dir = opendir(path->buf);
struct dirent *e;
int ret = 0, original_len = path->len, len;

if (!dir)
return -1;
if (path->buf[original_len - 1] != '/')
strbuf_addch(path, '/');

len = path->len;
while ((e = readdir(dir)) != NULL) {
struct stat st;
if ((e->d_name[0] == '.') &&
((e->d_name[1] == 0) ||
((e->d_name[1] == '.') && e->d_name[2] == 0)))
continue; /* "." and ".." */

strbuf_setlen(path, len);
strbuf_addstr(path, e->d_name);
if (lstat(path->buf, &st))
; /* fall thru */
else if (S_ISDIR(st.st_mode)) {
if (!remove_dir_recursively(path, only_empty))
continue; /* happy */
} else if (!only_empty && !unlink(path->buf))
continue; /* happy, too */

/* path too long, stat fails, or non-directory still exists */
ret = -1;
break;
}
closedir(dir);

strbuf_setlen(path, original_len);
if (!ret)
ret = rmdir(path->buf);
return ret;
}
2 changes: 2 additions & 0 deletions dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,6 @@ extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
extern char *get_relative_cwd(char *buffer, int size, const char *dir);
extern int is_inside_dir(const char *dir);

extern int remove_dir_recursively(struct strbuf *path, int only_empty);

#endif
57 changes: 12 additions & 45 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "refs.h"
#include "object.h"
#include "tag.h"
#include "dir.h"

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

static int remove_empty_dir_recursive(char *path, int len)
{
DIR *dir = opendir(path);
struct dirent *e;
int ret = 0;

if (!dir)
return -1;
if (path[len-1] != '/')
path[len++] = '/';
while ((e = readdir(dir)) != NULL) {
struct stat st;
int namlen;
if ((e->d_name[0] == '.') &&
((e->d_name[1] == 0) ||
((e->d_name[1] == '.') && e->d_name[2] == 0)))
continue; /* "." and ".." */

namlen = strlen(e->d_name);
if ((len + namlen < PATH_MAX) &&
strcpy(path + len, e->d_name) &&
!lstat(path, &st) &&
S_ISDIR(st.st_mode) &&
!remove_empty_dir_recursive(path, len + namlen))
continue; /* happy */

/* path too long, stat fails, or non-directory still exists */
ret = -1;
break;
}
closedir(dir);
if (!ret) {
path[len] = 0;
ret = rmdir(path);
}
return ret;
}

static int remove_empty_directories(char *file)
static int remove_empty_directories(const char *file)
{
/* we want to create a file but there is a directory there;
* if that is an empty directory (or a directory that contains
* only empty directories), remove them.
*/
char path[PATH_MAX];
int len = strlen(file);
struct strbuf path;
int result;

if (len >= PATH_MAX) /* path too long ;-) */
return -1;
strcpy(path, file);
return remove_empty_dir_recursive(path, len);
strbuf_init(&path, 20);
strbuf_addstr(&path, file);

result = remove_dir_recursively(&path, 1);

strbuf_release(&path);

return result;
}

static int is_refname_available(const char *ref, const char *oldref,
Expand Down

0 comments on commit 7155b72

Please sign in to comment.