Subject: [PATCH 1/4] submodule-config: add submodules_of_tree() helper

From: Glen Choo <[email-masked]>
Date: Mon, 22 Nov 2021 14:32:49 -0800

As we introduce a submodule UX with branches, we would like to be able
to get the submodule commit ids in a superproject tree because those ids
are the source of truth e.g. "git branch --recurse-submodules topic
start-point" should create branches based off the commit ids recorded in
the superproject's 'start-point' tree.

To make this easy, introduce a submodules_of_tree() helper function that
iterates through a tree and returns the tree's gitlink entries as a
list.

Signed-off-by: Glen Choo <[email-masked]>
---
 submodule-config.c | 19 +++++++++++++++++++
 submodule-config.h | 13 +++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/submodule-config.c b/submodule-config.c
index f95344028b..97da373301 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 #include "object-store.h"
 #include "parse-options.h"
+#include "tree-walk.h"
 
 /*
  * submodule cache lookup structure
@@ -726,6 +727,24 @@ const struct submodule *submodule_from_path(struct repository *r,
 	return config_from(r->submodule_cache, treeish_name, path, lookup_path);
 }
 
+struct submodule_entry_list *
+submodules_of_tree(struct repository *r, const struct object_id *treeish_name)
+{
+	struct tree_desc tree;
+	struct name_entry entry;
+	struct submodule_entry_list *ret;
+
+	CALLOC_ARRAY(ret, 1);
+	fill_tree_descriptor(r, &tree, treeish_name);
+	while (tree_entry(&tree, &entry)) {
+		if (!S_ISGITLINK(entry.mode))
+			continue;
+		ALLOC_GROW(ret->name_entries, ret->entry_nr + 1, ret->entry_alloc);
+		ret->name_entries[ret->entry_nr++] = entry;
+	}
+	return ret;
+}
+
 void submodule_free(struct repository *r)
 {
 	if (r->submodule_cache)
diff --git a/submodule-config.h b/submodule-config.h
index 65875b94ea..4379ec77e3 100644
--- a/submodule-config.h
+++ b/submodule-config.h
@@ -6,6 +6,7 @@
 #include "hashmap.h"
 #include "submodule.h"
 #include "strbuf.h"
+#include "tree-walk.h"
 
 /**
  * The submodule config cache API allows to read submodule
@@ -67,6 +68,18 @@ const struct submodule *submodule_from_name(struct repository *r,
 					    const struct object_id *commit_or_tree,
 					    const char *name);
 
+struct submodule_entry_list {
+	struct name_entry *name_entries;
+	int entry_nr;
+	int entry_alloc;
+};
+
+/**
+ * Given a tree-ish, return all submodules in the tree.
+ */
+struct submodule_entry_list *
+submodules_of_tree(struct repository *r, const struct object_id *treeish_name);
+
 /**
  * Given a tree-ish in the superproject and a path, return the submodule that
  * is bound at the path in the named tree.
-- 
2.33.GIT