git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Fix 'git clean' failure on NFS.

From
Török Edwin <edwintorok@gmail.com>
Date
Jun 18, 2010, 11:07 UTC
Message-ID
<1276859235-13534-1-git-send-email-edwintorok@gmail.com>
In-Reply-To
<loom.20100618T122039-876@post.gmane.org>

readdir() used to do a single pass, which is not always enough. If you unlink some files/rmdir some subdirs then there might be some files you haven't seen yet *before* the readdir cursor (files get rearranged in the directory, etc.).

The fix is to do an additional readdir() pass if we unlinked/rmdired something. This is easily accomplished by using rewinddir.

Signed-off-by: Török Edwin <edwintorok@gmail.com>
---
 dir.c |   16 ++++++++++++++--
 1 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/dir.c b/dir.c
index 5615f33..7260907 100644
--- a/dir.c
+++ b/dir.c
@@ -999,6 +999,7 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 	struct dirent *e;
 	int ret = 0, original_len = path->len, len;
 	int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY);
+	int did_rm;
 	unsigned char submodule_head[20];
 
 	if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
@@ -1013,6 +1014,8 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 		strbuf_addch(path, '/');
 
 	len = path->len;
+	do {
+	did_rm = 0;
 	while ((e = readdir(dir)) != NULL) {
 		struct stat st;
 		if (is_dot_or_dotdot(e->d_name))
@@ -1023,15 +1026,24 @@ int remove_dir_recursively(struct strbuf *path, int flag)
 		if (lstat(path->buf, &st))
 			; /* fall thru */
 		else if (S_ISDIR(st.st_mode)) {
-			if (!remove_dir_recursively(path, only_empty))
+			if (!remove_dir_recursively(path, only_empty)) {
+				did_rm = 1;
 				continue; /* happy */
-		} else if (!only_empty && !unlink(path->buf))
+			}
+		} else if (!only_empty && !unlink(path->buf)) {
+			did_rm = 1;
 			continue; /* happy, too */
+		}
 
 		/* path too long, stat fails, or non-directory still exists */
 		ret = -1;
 		break;
 	}
+	/* if we unlinked/rmdir-ed anything there might be files we haven't seen
+	 * yet before the readdir() cursor, rewind and walk directory again
+	 * until we can't unlink any more. */
+	rewinddir(dir);
+	} while (did_rm && !ret);
 	closedir(dir);
 
 	strbuf_setlen(path, original_len);
-- 
1.7.0
Previous: Török EdwinNext: Johannes Sixt
Message 4 of 10 in “[BUG] git clean not working on FreeBSD/NFS”
  1. Török EdwinJun 17, 2010
  2. Henrik GrubbströmJun 17, 2010
  3. Török EdwinJun 18, 2010
  4. Fix 'git clean' failure on NFS.Török Edwin, Jun 18, 2010
  5. Johannes SixtJun 18, 2010
  6. Török EdwinJun 18, 2010
  7. Erik Faye-LundJun 18, 2010
  8. Török EdwinJun 18, 2010
  9. Erik Faye-LundJun 18, 2010
  10. Török EdwinJun 18, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.