rev-parse: add --show-superproject-working-tree

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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller
2017-03-08 15:07:42 -08:00
committed by Junio C Hamano
parent e0688e9b28
commit bf0231c661
5 changed files with 117 additions and 0 deletions

View File

@ -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;
}