git@vger.kernel.org mailing list mirror (one of many)
 help / Atom feed
From: Stefan Beller <sbeller@google.com>
To: szeder.dev@gmail.com, email@benjaminfuchs.de, git@vger.kernel.org, sandals@crustytoothpaste.net, ville.skytta@iki.fi
Cc: Stefan Beller <sbeller@google.com>
Subject: [PATCHv4] rev-parse: add --show-superproject-working-tree
Date: Wed,  8 Mar 2017 15:07:42 -0800
Message-ID: <20170308230742.5185-1-sbeller@google.com> (raw)
In-Reply-To: <xmqqmvcv1jz9.fsf@gitster.mtv.corp.google.com>

In some situations it is useful to know if the given repository
is a submodule of another repository.

Add the flag --show-superproject-working-tree to git-rev-parse
to make it easy to find out if there is a superproject. When no
superproject exists, the output will be empty.

Signed-off-by: Stefan Beller <sbeller@google.com>
---

> I can accept "it is not an error to ask for the root of the
> superproject's working tree when we do not have any---that is one
> way to ask if we have a superproject or not".  But if that is the
> case, the code can stay the same, but the documentation should say
> so, something like...

 *this patch*
 
* Documentation shamelessly stolen from Junio.

Thanks,
Stefan

 Documentation/git-rev-parse.txt |  6 +++
 builtin/rev-parse.c             |  7 ++++
 submodule.c                     | 82 +++++++++++++++++++++++++++++++++++++++++
 submodule.h                     |  8 ++++
 t/t1500-rev-parse.sh            | 14 +++++++
 5 files changed, 117 insertions(+)

diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 91c02b8c85..c40c470448 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -261,6 +261,12 @@ print a message to stderr and exit with nonzero status.
 --show-toplevel::
 	Show the absolute path of the top-level directory.
 
+--show-superproject-working-tree
+	Show the absolute path of the root of the superproject's
+	working tree (if exists) that uses the current repository as
+	its submodule.  Outputs nothing if the current repository is
+	not used as a submodule by any project.
+
 --shared-index-path::
 	Show the path to the shared index file in split index mode, or
 	empty if not in split-index mode.
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index e08677e559..2549643267 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -12,6 +12,7 @@
 #include "diff.h"
 #include "revision.h"
 #include "split-index.h"
+#include "submodule.h"
 
 #define DO_REVS		1
 #define DO_NOREV	2
@@ -779,6 +780,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 					puts(work_tree);
 				continue;
 			}
+			if (!strcmp(arg, "--show-superproject-working-tree")) {
+				const char *superproject = get_superproject_working_tree();
+				if (superproject)
+					puts(superproject);
+				continue;
+			}
 			if (!strcmp(arg, "--show-prefix")) {
 				if (prefix)
 					puts(prefix);
diff --git a/submodule.c b/submodule.c
index 3b98766a6b..bb405653fd 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1514,3 +1514,85 @@ void absorb_git_dir_into_superproject(const char *prefix,
 		strbuf_release(&sb);
 	}
 }
+
+const char *get_superproject_working_tree(void)
+{
+	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())
+		/*
+		 * FIXME:
+		 * We might have a superproject, but it is harder
+		 * to determine.
+		 */
+		return NULL;
+
+	if (!one_up)
+		return NULL;
+
+	subpath = relative_path(cwd, one_up, &sb);
+
+	prepare_submodule_repo_env(&cp.env_array);
+	argv_array_pop(&cp.env_array);
+
+	argv_array_pushl(&cp.args, "--literal-pathspecs", "-C", "..",
+			"ls-files", "-z", "--stage", "--full-name", "--",
+			subpath, NULL);
+	strbuf_reset(&sb);
+
+	cp.no_stdin = 1;
+	cp.no_stderr = 1;
+	cp.out = -1;
+	cp.git_cmd = 1;
+
+	if (start_command(&cp))
+		die(_("could not start ls-files in .."));
+
+	len = 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;
+
+		/*
+		 * 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);
+	}
+	strbuf_release(&sb);
+
+	code = finish_command(&cp);
+
+	if (code == 128)
+		/* '../' is not a git repository */
+		return NULL;
+	if (code == 0 && len == 0)
+		/* There is an unrelated git repository at '../' */
+		return NULL;
+	if (code)
+		die(_("ls-tree returned unexpected return code %d"), code);
+
+	return ret;
+}
diff --git a/submodule.h b/submodule.h
index 05ab674f06..c8a0c9cb29 100644
--- a/submodule.h
+++ b/submodule.h
@@ -93,4 +93,12 @@ extern void prepare_submodule_repo_env(struct argv_array *out);
 extern void absorb_git_dir_into_superproject(const char *prefix,
 					     const char *path,
 					     unsigned flags);
+
+/*
+ * 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.
+ */
+extern const char *get_superproject_working_tree(void);
+
 #endif
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index 9ed8b8ccba..03d3c7f6d6 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -116,4 +116,18 @@ test_expect_success 'git-path inside sub-dir' '
 	test_cmp expect actual
 '
 
+test_expect_success 'showing the superproject correctly' '
+	git rev-parse --show-superproject-working-tree >out &&
+	test_must_be_empty out &&
+
+	test_create_repo super &&
+	test_commit -C super test_commit &&
+	test_create_repo sub &&
+	test_commit -C sub test_commit &&
+	git -C super submodule add ../sub dir/sub &&
+	echo $(pwd)/super >expect  &&
+	git -C super/dir/sub rev-parse --show-superproject-working-tree >out &&
+	test_cmp expect out
+'
+
 test_done
-- 
2.12.0.190.g6e60aba09d.dirty


  reply index

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-30 20:44 [PATCH 0/4] git-prompt.sh: Full patch for submodule indicator Benjamin Fuchs
2017-01-30 20:44 ` [PATCH 1/4] git-prompt.sh: add " Benjamin Fuchs
2017-01-30 23:48   ` Junio C Hamano
2017-01-31  0:10     ` Benjamin Fuchs
2017-01-31  3:11       ` Junio C Hamano
2017-02-06  4:23         ` Stefan Beller
2017-02-06  5:55           ` Jacob Keller
2017-02-06 10:13             ` Stefan Beller
2017-01-30 20:44 ` [PATCH 3/4] git-prompt.sh: fix for submodule 'dirty' indicator Benjamin Fuchs
2017-01-30 20:44 ` [PATCH 4/4] git-prompt.sh: add tests for submodule indicator Benjamin Fuchs
2017-01-31 18:32   ` SZEDER Gábor
2017-01-31 22:06     ` Junio C Hamano
2017-01-30 20:44 [PATCH 2/4] git-prompt.sh: rework of " Benjamin Fuchs
2017-01-31 18:06 ` SZEDER Gábor
2017-01-31 22:12 [PATCH 4/4] git-prompt.sh: add tests for " Stefan Beller
2017-03-07  3:45 ` [RFC PATCH] rev-parse: add --show-superproject-working-tree Stefan Beller
2017-03-07  5:13   ` Junio C Hamano
2017-03-07  7:16     ` Junio C Hamano
2017-03-07  7:23       ` Junio C Hamano
2017-03-07 18:44   ` Junio C Hamano
2017-03-07 20:40     ` Stefan Beller
2017-03-07 22:49 Junio C Hamano
2017-03-08  0:56 ` [PATCHv2] " Stefan Beller
2017-03-08  1:30   ` Junio C Hamano
2017-03-08  6:01 Junio C Hamano
2017-03-08 19:20 ` [PATCHv3] " Stefan Beller
2017-03-08 22:28 Junio C Hamano
2017-03-08 23:07 ` Stefan Beller [this message]
2017-03-08 23:51   ` [PATCHv4] " Junio C Hamano
2017-03-17 22:28   ` Jonathan Nieder
2017-03-17 22:51     ` [PATCH] Documentation/git-worktree: use working tree for trees on the file system Stefan Beller
2017-03-17 22:55       ` Jonathan Nieder
2017-03-17 23:04         ` Stefan Beller
2017-03-18 17:24           ` Junio C Hamano
2017-03-18  1:47         ` Junio C Hamano
2017-03-18  1:36       ` Junio C Hamano
2017-03-20 17:29         ` Stefan Beller
2017-03-20 18:12           ` Junio C Hamano
2017-03-20 18:50             ` Jonathan Nieder
2017-03-20 19:22               ` [PATCH 0/2] use "working trees" instead of "worktree" in our API Stefan Beller
2017-03-20 19:22                 ` [PATCH 1/2] git.c: introduce --working-tree superseding --work-tree Stefan Beller
2017-03-20 19:58                   ` Jonathan Nieder
2017-03-20 19:22                 ` [PATCH 2/2] revparse: introduce --is-inside-working-tree Stefan Beller
2017-03-20 20:00                   ` Jonathan Nieder
2017-03-20 19:37                 ` [PATCH 0/2] use "working trees" instead of "worktree" in our API Junio C Hamano
2017-03-21 10:37               ` [PATCH] Documentation/git-worktree: use working tree for trees on the file system Duy Nguyen
2017-03-21 15:48                 ` Junio C Hamano
2017-03-23 17:06                   ` Michael J Gruber
2017-03-23 17:55                     ` Junio C Hamano
2017-03-25 12:07                       ` Duy Nguyen
2017-04-07 13:59                         ` Michael J Gruber
2017-04-07 16:14                           ` Jacob Keller
2017-03-25 12:05                   ` Duy Nguyen

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170308230742.5185-1-sbeller@google.com \
    --to=sbeller@google.com \
    --cc=email@benjaminfuchs.de \
    --cc=git@vger.kernel.org \
    --cc=sandals@crustytoothpaste.net \
    --cc=szeder.dev@gmail.com \
    --cc=ville.skytta@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

git@vger.kernel.org mailing list mirror (one of many)

Archives are clonable:
	git clone --mirror https://public-inbox.org/git
	git clone --mirror http://ou63pmih66umazou.onion/git
	git clone --mirror http://czquwvybam4bgbro.onion/git
	git clone --mirror http://hjrcffqmbrq6wope.onion/git

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.version-control.git
	nntp://ou63pmih66umazou.onion/inbox.comp.version-control.git
	nntp://czquwvybam4bgbro.onion/inbox.comp.version-control.git
	nntp://hjrcffqmbrq6wope.onion/inbox.comp.version-control.git
	nntp://news.gmane.org/gmane.comp.version-control.git

 note: .onion URLs require Tor: https://www.torproject.org/
       or Tor2web: https://www.tor2web.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox