зеркало из https://github.com/microsoft/git.git
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:
Родитель
e0688e9b28
Коммит
bf0231c661
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
82
submodule.c
82
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче