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

[PATCH v5 5/6] remove_subtree(): reimplement using iterators

From
Daniel Ferreira <bnmvco@gmail.com>
Date
Mar 30, 2017, 03:32 UTC
Message-ID
<1490844730-47634-6-git-send-email-bnmvco@gmail.com>
In-Reply-To
<1490844730-47634-1-git-send-email-bnmvco@gmail.com>
From: Daniel Ferreira <daniel.calibeta@gmail.com>

Use dir_iterator to traverse through remove_subtree()'s directory tree, avoiding the need for recursive calls to readdir(). Simplify remove_subtree()'s code.

A conversion similar in purpose was previously done at 46d092a ("for_each_reflog(): reimplement using iterators", 2016-05-21).

Signed-off-by: Daniel Ferreira <bnmvco@gmail.com>
---
 entry.c | 41 +++++++++++++++--------------------------
 1 file changed, 15 insertions(+), 26 deletions(-)
diff --git a/entry.c b/entry.c
index c6eea24..30197b2 100644
--- a/entry.c
+++ b/entry.c
@@ -2,6 +2,8 @@
 #include "blob.h"
 #include "dir.h"
 #include "streaming.h"
+#include "iterator.h"
+#include "dir-iterator.h"

 static void create_directories(const char *path, int path_len,
 			       const struct checkout *state)
@@ -44,33 +46,20 @@ static void create_directories(const char *path, int path_len,
 	free(buf);
 }

-static void remove_subtree(struct strbuf *path)
+static void remove_subtree(const char *path)
 {
-	DIR *dir = opendir(path->buf);
-	struct dirent *de;
-	int origlen = path->len;
-
-	if (!dir)
-		die_errno("cannot opendir '%s'", path->buf);
-	while ((de = readdir(dir)) != NULL) {
-		struct stat st;
-
-		if (is_dot_or_dotdot(de->d_name))
-			continue;
-
-		strbuf_addch(path, '/');
-		strbuf_addstr(path, de->d_name);
-		if (lstat(path->buf, &st))
-			die_errno("cannot lstat '%s'", path->buf);
-		if (S_ISDIR(st.st_mode))
-			remove_subtree(path);
-		else if (unlink(path->buf))
-			die_errno("cannot unlink '%s'", path->buf);
-		strbuf_setlen(path, origlen);
+	struct dir_iterator *diter = dir_iterator_begin(path, DIR_ITERATOR_POST_ORDER_TRAVERSAL);
+
+	while (dir_iterator_advance(diter) == ITER_OK) {
+		if (S_ISDIR(diter->st.st_mode)) {
+			if (rmdir(diter->path.buf))
+				die_errno("cannot rmdir '%s'", diter->path.buf);
+		} else if (unlink(diter->path.buf))
+			die_errno("cannot unlink '%s'", diter->path.buf);
 	}
-	closedir(dir);
-	if (rmdir(path->buf))
-		die_errno("cannot rmdir '%s'", path->buf);
+
+	if (rmdir(path))
+		die_errno("cannot rmdir '%s'", path);
 }

 static int create_file(const char *path, unsigned int mode)
@@ -282,7 +271,7 @@ int checkout_entry(struct cache_entry *ce,
 				return 0;
 			if (!state->force)
 				return error("%s is a directory", path.buf);
-			remove_subtree(&path);
+			remove_subtree(path.buf);
 		} else if (unlink(path.buf))
 			return error_errno("unable to unlink old '%s'", path.buf);
 	} else if (state->not_new)
--
2.7.4 (Apple Git-66)
Previous: Daniel Ferreira (theiostream)Next: Daniel Ferreira
Message 15 of 19 in “[GSoC] remove_subtree(): reimplement using iterators”
  1. 0/6 [GSoC] remove_subtree(): reimplement using iteratorsDaniel Ferreira, Mar 30, 2017
  2. 1/6 dir_iterator: add helpers to dir_iterator_advanceDaniel Ferreira, Mar 30, 2017
  3. 2/6 dir_iterator: refactor state machine modelDaniel Ferreira, Mar 30, 2017
  4. Michael HaggertyMar 30, 2017
  5. 3/6 dir_iterator: iterate over dir after its contentsDaniel Ferreira, Mar 30, 2017
  6. Michael HaggertyMar 30, 2017
  7. 4/6 dir_iterator: add tests for dir_iterator APIDaniel Ferreira, Mar 30, 2017
  8. Michael HaggertyMar 30, 2017
  9. Daniel Ferreira (theiostream)Mar 30, 2017
  10. Jeff KingApr 1, 2017
  11. Junio C HamanoApr 1, 2017
  12. Michael HaggertyMar 30, 2017
  13. Michael HaggertyMar 30, 2017
  14. Daniel Ferreira (theiostream)Mar 30, 2017
  15. 5/6 remove_subtree(): reimplement using iteratorsDaniel Ferreira, Mar 30, 2017
  16. 6/6 remove_subtree(): test removing nested directoriesDaniel Ferreira, Mar 30, 2017
  17. Michael HaggertyMar 30, 2017
  18. Michael HaggertyMar 30, 2017
  19. Duy NguyenMar 30, 2017

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.