Subject: [PATCH 14/20] worktree.c: add collect_per_worktree_git_paths()

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Wed, 3 Feb 2016 16:35:44 +0700

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 worktree.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 worktree.h |  6 ++++++
 2 files changed, 64 insertions(+)

diff --git a/worktree.c b/worktree.c
index d4513b1..047319b 100644
--- a/worktree.c
+++ b/worktree.c
@@ -257,6 +257,64 @@ int update_worktree_gitfile(const char *gitfile,
 	return 0;
 }
 
+static int collect_per_worktree_1(struct strbuf *base, int commonlen,
+				  struct string_list *paths)
+{
+	int base_len = base->len;
+	struct dirent *d;
+	DIR *dir;
+	int ret = 0;
+
+	dir = opendir(base->buf);
+	if (!dir)
+		return sys_error(_("failed to open '%s'"), base->buf);
+
+	while ((d = readdir(dir))) {
+		struct stat st;
+
+		if (is_dot_or_dotdot(d->d_name))
+			continue;
+
+		strbuf_setlen(base, base_len);
+		strbuf_addstr(base, d->d_name);
+
+		if (stat(base->buf, &st)) {
+			if (errno == ENOENT)
+				continue;
+			ret = sys_error(_("failed to stat '%s'"), base->buf);
+			break;
+		}
+		if (!S_ISDIR(st.st_mode)) {
+			const char *path = base->buf + commonlen;
+			if (!is_git_path_shared(path))
+				string_list_append(paths, path);
+			continue;
+		}
+
+		strbuf_addch(base, '/');
+		if ((ret = collect_per_worktree_1(base, commonlen, paths)))
+			break;
+	}
+	closedir(dir);
+	return ret;
+}
+
+int collect_per_worktree_git_paths(struct string_list *paths)
+{
+	struct strbuf base = STRBUF_INIT;
+	int ret;
+
+	/* force adjust_git_path() to always adjust paths */
+	git_common_dir_env = 1;
+
+	strbuf_addstr(&base, get_git_common_dir());
+	if (base.len && base.buf[base.len - 1] != '/')
+		strbuf_addch(&base, '/');
+	ret = collect_per_worktree_1(&base, base.len, paths);
+	strbuf_release(&base);
+	return ret;
+}
+
 char *find_shared_symref(const char *symref, const char *target)
 {
 	char *existing = NULL;
diff --git a/worktree.h b/worktree.h
index 55f3449..8da1a13 100644
--- a/worktree.h
+++ b/worktree.h
@@ -52,6 +52,12 @@ extern int update_worktree_gitfile(const char *gitfile,
 				   const char *id);
 
 /*
+ * Given .git directory in "base", search all paths, collect the list
+ * of paths that are not shared in "paths".
+ */
+extern int collect_per_worktree_git_paths(struct string_list *paths);
+
+/*
  * Free up the memory for worktree
  */
 extern void clear_worktree(struct worktree *);
-- 
2.7.0.377.g4cd97dd