зеркало из https://github.com/microsoft/git.git
Teach diff --submodule and status to handle .git files in submodules
The simple test for an existing .git directory gives an incorrect result if .git is a file that records "gitdir: overthere". So for submodules that use a .git file, "git status" and the diff family - when the "--submodule" option is given - did assume the submodule was not populated at all when a .git file was used, thus generating wrong output or no output at all. This is fixed by using read_gitfile_gently() to get the correct location of the .git directory. While at it, is_submodule_modified() was cleaned up to use the "dir" member of "struct child_process" instead of setting the GIT_WORK_TREE and GIT_DIR environment variables. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
3bfc450476
Коммит
eee49b6ce4
33
submodule.c
33
submodule.c
|
@ -12,8 +12,15 @@ static int add_submodule_odb(const char *path)
|
||||||
struct strbuf objects_directory = STRBUF_INIT;
|
struct strbuf objects_directory = STRBUF_INIT;
|
||||||
struct alternate_object_database *alt_odb;
|
struct alternate_object_database *alt_odb;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
const char *git_dir;
|
||||||
|
|
||||||
strbuf_addf(&objects_directory, "%s/.git/objects/", path);
|
strbuf_addf(&objects_directory, "%s/.git", path);
|
||||||
|
git_dir = read_gitfile_gently(objects_directory.buf);
|
||||||
|
if (git_dir) {
|
||||||
|
strbuf_reset(&objects_directory);
|
||||||
|
strbuf_addstr(&objects_directory, git_dir);
|
||||||
|
}
|
||||||
|
strbuf_addstr(&objects_directory, "/objects/");
|
||||||
if (!is_directory(objects_directory.buf)) {
|
if (!is_directory(objects_directory.buf)) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -132,7 +139,6 @@ void show_submodule_summary(FILE *f, const char *path,
|
||||||
|
|
||||||
unsigned is_submodule_modified(const char *path, int ignore_untracked)
|
unsigned is_submodule_modified(const char *path, int ignore_untracked)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct child_process cp;
|
struct child_process cp;
|
||||||
const char *argv[] = {
|
const char *argv[] = {
|
||||||
|
@ -141,16 +147,16 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
const char *env[LOCAL_REPO_ENV_SIZE + 3];
|
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
unsigned dirty_submodule = 0;
|
unsigned dirty_submodule = 0;
|
||||||
const char *line, *next_line;
|
const char *line, *next_line;
|
||||||
|
const char *git_dir;
|
||||||
|
|
||||||
for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++)
|
strbuf_addf(&buf, "%s/.git", path);
|
||||||
env[i] = local_repo_env[i];
|
git_dir = read_gitfile_gently(buf.buf);
|
||||||
|
if (!git_dir)
|
||||||
strbuf_addf(&buf, "%s/.git/", path);
|
git_dir = buf.buf;
|
||||||
if (!is_directory(buf.buf)) {
|
if (!is_directory(git_dir)) {
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
/* The submodule is not checked out, so it is not modified */
|
/* The submodule is not checked out, so it is not modified */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -158,21 +164,16 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
|
||||||
}
|
}
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
|
|
||||||
strbuf_addf(&buf, "GIT_WORK_TREE=%s", path);
|
|
||||||
env[i++] = strbuf_detach(&buf, NULL);
|
|
||||||
strbuf_addf(&buf, "GIT_DIR=%s/.git", path);
|
|
||||||
env[i++] = strbuf_detach(&buf, NULL);
|
|
||||||
env[i] = NULL;
|
|
||||||
|
|
||||||
if (ignore_untracked)
|
if (ignore_untracked)
|
||||||
argv[2] = "-uno";
|
argv[2] = "-uno";
|
||||||
|
|
||||||
memset(&cp, 0, sizeof(cp));
|
memset(&cp, 0, sizeof(cp));
|
||||||
cp.argv = argv;
|
cp.argv = argv;
|
||||||
cp.env = env;
|
cp.env = local_repo_env;
|
||||||
cp.git_cmd = 1;
|
cp.git_cmd = 1;
|
||||||
cp.no_stdin = 1;
|
cp.no_stdin = 1;
|
||||||
cp.out = -1;
|
cp.out = -1;
|
||||||
|
cp.dir = path;
|
||||||
if (start_command(&cp))
|
if (start_command(&cp))
|
||||||
die("Could not run git status --porcelain");
|
die("Could not run git status --porcelain");
|
||||||
|
|
||||||
|
@ -201,8 +202,6 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
|
||||||
if (finish_command(&cp))
|
if (finish_command(&cp))
|
||||||
die("git status --porcelain failed");
|
die("git status --porcelain failed");
|
||||||
|
|
||||||
for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++)
|
|
||||||
free((char *)env[i]);
|
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
return dirty_submodule;
|
return dirty_submodule;
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,4 +329,19 @@ index 0000000..$head7
|
||||||
EOF
|
EOF
|
||||||
"
|
"
|
||||||
|
|
||||||
|
test_expect_success 'setup .git file for sm2' '
|
||||||
|
(cd sm2 &&
|
||||||
|
REAL="$(pwd)/../.real" &&
|
||||||
|
mv .git "$REAL"
|
||||||
|
echo "gitdir: $REAL" >.git)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'diff --submodule with .git file' '
|
||||||
|
git diff --submodule HEAD^ >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
Submodule sm1 $head6...0000000 (submodule deleted)
|
||||||
|
Submodule sm2 0000000...$head7 (new submodule)
|
||||||
|
EOF
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -157,6 +157,22 @@ test_expect_success 'status with added and untracked file in modified submodule
|
||||||
EOF
|
EOF
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'setup .git file for sub' '
|
||||||
|
(cd sub &&
|
||||||
|
rm -f new-file
|
||||||
|
REAL="$(pwd)/../.real" &&
|
||||||
|
mv .git "$REAL"
|
||||||
|
echo "gitdir: $REAL" >.git) &&
|
||||||
|
echo .real >>.gitignore &&
|
||||||
|
git commit -m "added .real to .gitignore" .gitignore
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'status with added file in modified submodule with .git file' '
|
||||||
|
(cd sub && git reset --hard && echo >foo && git add foo) &&
|
||||||
|
git status >output &&
|
||||||
|
grep "modified: sub (new commits, modified content)" output
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'rm submodule contents' '
|
test_expect_success 'rm submodule contents' '
|
||||||
rm -rf sub/* sub/.git
|
rm -rf sub/* sub/.git
|
||||||
'
|
'
|
||||||
|
|
Загрузка…
Ссылка в новой задаче