@matheusbsbs / matheus-bagliano / commits / eee49b6ce4
Fork 0

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>

Jens Lehmann committed Apr 10, 2010 at 19:01 UTC eee49b6ce4b7b3fed28794676c67ad3609f658ac
3 files changed +47 -17
submodule.c
+16 -17
@@ -12,8 +12,15 @@ static int add_submodule_odb(const char *path)
12 struct strbuf objects_directory = STRBUF_INIT;
13 struct alternate_object_database *alt_odb;
14 int ret = 0;
15 + const char *git_dir;
16
16 - strbuf_addf(&objects_directory, "%s/.git/objects/", path);
17 + strbuf_addf(&objects_directory, "%s/.git", path);
18 + git_dir = read_gitfile_gently(objects_directory.buf);
19 + if (git_dir) {
20 + strbuf_reset(&objects_directory);
21 + strbuf_addstr(&objects_directory, git_dir);
22 + }
23 + strbuf_addstr(&objects_directory, "/objects/");
24 if (!is_directory(objects_directory.buf)) {
25 ret = -1;
26 goto done;
@@ -132,7 +139,6 @@ void show_submodule_summary(FILE *f, const char *path,
139
140 unsigned is_submodule_modified(const char *path, int ignore_untracked)
141 {
135 - int i;
142 ssize_t len;
143 struct child_process cp;
144 const char *argv[] = {
@@ -141,16 +147,16 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
147 NULL,
148 NULL,
149 };
144 - const char *env[LOCAL_REPO_ENV_SIZE + 3];
150 struct strbuf buf = STRBUF_INIT;
151 unsigned dirty_submodule = 0;
152 const char *line, *next_line;
153 + const char *git_dir;
154
149 - for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++)
150 - env[i] = local_repo_env[i];
151 -
152 - strbuf_addf(&buf, "%s/.git/", path);
153 - if (!is_directory(buf.buf)) {
155 + strbuf_addf(&buf, "%s/.git", path);
156 + git_dir = read_gitfile_gently(buf.buf);
157 + if (!git_dir)
158 + git_dir = buf.buf;
159 + if (!is_directory(git_dir)) {
160 strbuf_release(&buf);
161 /* The submodule is not checked out, so it is not modified */
162 return 0;
@@ -158,21 +164,16 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
164 }
165 strbuf_reset(&buf);
166
161 - strbuf_addf(&buf, "GIT_WORK_TREE=%s", path);
162 - env[i++] = strbuf_detach(&buf, NULL);
163 - strbuf_addf(&buf, "GIT_DIR=%s/.git", path);
164 - env[i++] = strbuf_detach(&buf, NULL);
165 - env[i] = NULL;
166 -
167 if (ignore_untracked)
168 argv[2] = "-uno";
169
170 memset(&cp, 0, sizeof(cp));
171 cp.argv = argv;
172 - cp.env = env;
172 + cp.env = local_repo_env;
173 cp.git_cmd = 1;
174 cp.no_stdin = 1;
175 cp.out = -1;
176 + cp.dir = path;
177 if (start_command(&cp))
178 die("Could not run git status --porcelain");
179
@@ -201,8 +202,6 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
202 if (finish_command(&cp))
203 die("git status --porcelain failed");
204
204 - for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++)
205 - free((char *)env[i]);
205 strbuf_release(&buf);
206 return dirty_submodule;
207 }
t/t4041-diff-submodule.sh
+15
@@ -329,4 +329,19 @@ index 0000000..$head7
329 EOF
330 "
331
332 +test_expect_success 'setup .git file for sm2' '
333 + (cd sm2 &&
334 + REAL="$(pwd)/../.real" &&
335 + mv .git "$REAL"
336 + echo "gitdir: $REAL" >.git)
337 +'
338 +
339 +test_expect_success 'diff --submodule with .git file' '
340 + git diff --submodule HEAD^ >actual &&
341 + diff actual - <<-EOF
342 +Submodule sm1 $head6...0000000 (submodule deleted)
343 +Submodule sm2 0000000...$head7 (new submodule)
344 +EOF
345 +'
346 +
347 test_done
t/t7506-status-submodule.sh
+16
@@ -157,6 +157,22 @@ test_expect_success 'status with added and untracked file in modified submodule
157 EOF
158 '
159
160 +test_expect_success 'setup .git file for sub' '
161 + (cd sub &&
162 + rm -f new-file
163 + REAL="$(pwd)/../.real" &&
164 + mv .git "$REAL"
165 + echo "gitdir: $REAL" >.git) &&
166 + echo .real >>.gitignore &&
167 + git commit -m "added .real to .gitignore" .gitignore
168 +'
169 +
170 +test_expect_success 'status with added file in modified submodule with .git file' '
171 + (cd sub && git reset --hard && echo >foo && git add foo) &&
172 + git status >output &&
173 + grep "modified: sub (new commits, modified content)" output
174 +'
175 +
176 test_expect_success 'rm submodule contents' '
177 rm -rf sub/* sub/.git
178 '