From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: gitster@pobox.com, Daniel Barkalow <barkalow@iabervon.org>,
git@vger.kernel.org
Subject: [PATCH 1/2] Introduce remove_dir_recursively()
Date: Fri, 28 Sep 2007 06:06:44 +0100 (BST) [thread overview]
Message-ID: <Pine.LNX.4.64.0709280606350.28395@racer.site> (raw)
In-Reply-To: <Pine.LNX.4.64.0709280602580.28395@racer.site>
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>
---
dir.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
dir.h | 2 ++
refs.c | 36 ++----------------------------------
3 files changed, 49 insertions(+), 34 deletions(-)
diff --git a/dir.c b/dir.c
index eb6c3ab..0fae400 100644
--- a/dir.c
+++ b/dir.c
@@ -685,3 +685,48 @@ int is_inside_dir(const char *dir)
char buffer[PATH_MAX];
return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
}
+
+int remove_dir_recursively(char *path, int len, int only_empty)
+{
+ 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 ||
+ !memcpy(path + len, e->d_name, namlen) ||
+ (path[len + namlen] = '\0') ||
+ lstat(path, &st))
+ ; /* fall thru */
+ else if (S_ISDIR(st.st_mode)) {
+ if (!remove_dir_recursively(path, len + namlen,
+ only_empty))
+ continue; /* happy */
+ } else if (!only_empty &&
+ len + namlen + 1 < PATH_MAX &&
+ !unlink(path))
+ continue; /* happy, too */
+
+ /* 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;
+}
diff --git a/dir.h b/dir.h
index f55a87b..f52eea8 100644
--- a/dir.h
+++ b/dir.h
@@ -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(char *dir, int len, int only_empty);
+
#endif
diff --git a/refs.c b/refs.c
index 07e260c..f0336ee 100644
--- a/refs.c
+++ b/refs.c
@@ -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
@@ -673,40 +674,7 @@ static struct ref_lock *verify_lock(struct ref_lock *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;
+ return remove_dir_recursively(path, len, 1);
}
static int remove_empty_directories(char *file)
--
1.5.3.2.1102.g9487
next prev parent reply other threads:[~2007-09-28 5:08 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-28 5:06 [PATCH 0/2] rsync support Johannes Schindelin
2007-09-28 5:06 ` Johannes Schindelin [this message]
2007-09-28 9:05 ` [PATCH 1/2] Introduce remove_dir_recursively() Junio C Hamano
2007-09-28 12:35 ` Johannes Schindelin
2007-09-28 22:14 ` David Kastrup
2007-09-28 5:07 ` [PATCH 2/2] fetch/push: readd rsync support Johannes Schindelin
2007-09-28 5:20 ` Shawn O. Pearce
2007-09-28 12:22 ` Johannes Schindelin
2007-09-28 9:30 ` Junio C Hamano
2007-09-28 12:53 ` Johannes Schindelin
2007-09-28 15:28 ` [PATCH v2 0/2] rsync support, was Re: [PATCH 0/2] " Johannes Schindelin
2007-09-28 15:28 ` [PATCH v2 1/2] Introduce remove_dir_recursively() Johannes Schindelin
2007-09-28 15:29 ` [PATCH 2/2] fetch/push: readd rsync support Johannes Schindelin
2007-09-28 15:30 ` Johannes Schindelin
2007-09-28 21:20 ` Junio C Hamano
2007-09-28 22:48 ` Johannes Schindelin
2007-09-29 0:35 ` [PATCH v3 " Johannes Schindelin
2007-09-30 6:09 ` Junio C Hamano
2007-09-30 12:58 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0709280606350.28395@racer.site \
--to=johannes.schindelin@gmx.de \
--cc=barkalow@iabervon.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).