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

[WIP 1/2] submodule: refactor acquisition of superproject info

From
JTJonathan Tan <jonathantanmy@google.com>
Date
Dec 1, 2017, 22:50 UTC
Message-ID
<14e821d45e4ac2faea1f9023d43c43c4675672e7.1512168087.git.jonathantanmy@google.com>
In-Reply-To
<cover.1512168087.git.jonathantanmy@google.com>
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
 submodule.c | 76 +++++++++++++++++++++++++++++++++++++------------------------
 submodule.h |  3 +++
 2 files changed, 49 insertions(+), 30 deletions(-)
diff --git a/submodule.c b/submodule.c
index bb531e0e5..ce511180e 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1977,16 +1977,24 @@ void absorb_git_dir_into_superproject(const char *prefix,
 	}
 }
 
-const char *get_superproject_working_tree(void)
+/*
+ * Get the full filename of the gitlink entry corresponding to the
+ * superproject having this repo as a submodule.
+ *
+ * full_name will point to an internal buffer upon success.
+ *
+ * Return 0 if successful, 1 if not (for example, if the parent
+ * directory is not a repo or an unrelated one).
+ */
+int get_superproject_entry(const char **full_name)
 {
+	static struct strbuf sb = STRBUF_INIT;
+
 	struct child_process cp = CHILD_PROCESS_INIT;
-	struct strbuf sb = STRBUF_INIT;
 	const char *one_up = real_path_if_valid("../");
 	const char *cwd = xgetcwd();
-	const char *ret = NULL;
 	const char *subpath;
 	int code;
-	ssize_t len;
 
 	if (!is_inside_work_tree())
 		/*
@@ -1994,11 +2002,15 @@ const char *get_superproject_working_tree(void)
 		 * We might have a superproject, but it is harder
 		 * to determine.
 		 */
-		return NULL;
+		return 1;
 
 	if (!one_up)
-		return NULL;
+		return 1;
 
+	/*
+	 * No need to reset sb, since relative_path() will do it if
+	 * necessary.
+	 */
 	subpath = relative_path(cwd, one_up, &sb);
 
 	prepare_submodule_repo_env(&cp.env_array);
@@ -2017,45 +2029,49 @@ const char *get_superproject_working_tree(void)
 	if (start_command(&cp))
 		die(_("could not start ls-files in .."));
 
-	len = strbuf_read(&sb, cp.out, PATH_MAX);
+	strbuf_read(&sb, cp.out, PATH_MAX);
 	close(cp.out);
 
-	if (starts_with(sb.buf, "160000")) {
-		int super_sub_len;
-		int cwd_len = strlen(cwd);
-		char *super_sub, *super_wt;
+	code = finish_command(&cp);
 
+	if (starts_with(sb.buf, "160000")) {
 		/*
 		 * There is a superproject having this repo as a submodule.
 		 * The format is <mode> SP <hash> SP <stage> TAB <full name> \0,
 		 * We're only interested in the name after the tab.
 		 */
-		super_sub = strchr(sb.buf, '\t') + 1;
-		super_sub_len = sb.buf + sb.len - super_sub - 1;
-
-		if (super_sub_len > cwd_len ||
-		    strcmp(&cwd[cwd_len - super_sub_len], super_sub))
-			die (_("BUG: returned path string doesn't match cwd?"));
-
-		super_wt = xstrdup(cwd);
-		super_wt[cwd_len - super_sub_len] = '\0';
-
-		ret = real_path(super_wt);
-		free(super_wt);
+		char *tab = strchr(sb.buf, '\t');
+		if (!tab)
+			die("BUG: ls-files returned line with no tab");
+		*full_name = tab + 1;
+		return 0;
 	}
-	strbuf_release(&sb);
-
-	code = finish_command(&cp);
 
 	if (code == 128)
 		/* '../' is not a git repository */
-		return NULL;
-	if (code == 0 && len == 0)
+		return 1;
+	if (code == 0)
 		/* There is an unrelated git repository at '../' */
+		return 1;
+	die(_("ls-tree returned unexpected return code %d"), code);
+}
+
+const char *get_superproject_working_tree(void)
+{
+	const char *full_name;
+	char *super_wt;
+	size_t len;
+	const char *ret;
+
+	if (get_superproject_entry(&full_name))
 		return NULL;
-	if (code)
-		die(_("ls-tree returned unexpected return code %d"), code);
 
+	super_wt = xstrdup(xgetcwd());
+	if (!strip_suffix(super_wt, full_name, &len))
+		die("BUG: returned path string doesn't match cwd?");
+	super_wt[len] = '\0';
+	ret = real_path(super_wt);
+	free(super_wt);
 	return ret;
 }
 
diff --git a/submodule.h b/submodule.h
index f0da0277a..29ab302cc 100644
--- a/submodule.h
+++ b/submodule.h
@@ -134,6 +134,9 @@ extern void absorb_git_dir_into_superproject(const char *prefix,
  * Return the absolute path of the working tree of the superproject, which this
  * project is a submodule of. If this repository is not a submodule of
  * another repository, return NULL.
+ *
+ * The return value, if not NULL, points to the same shared buffer as the one
+ * returned by real_path().
  */
 extern const char *get_superproject_working_tree(void);
 
-- 
2.15.0.531.g2ccb3012c9-goog
Previous: Jonathan TanNext: Stefan Beller
Message 2 of 5 in “[WIP 0/2] Submodule ref backend that mirrors superproject”
  1. Jonathan TanDec 1, 2017
  2. 1/2 submodule: refactor acquisition of superproject infoJonathan Tan, Dec 1, 2017
  3. Stefan BellerDec 5, 2017
  4. 2/2 submodule: read-only super-backed ref backendJonathan Tan, Dec 1, 2017
  5. Stefan BellerDec 5, 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.