Skip to content

Commit c7e1a73

Browse files
jlehmanngitster
authored andcommitted
git diff --submodule: Show detailed dirty status of submodules
When encountering a dirty submodule while doing "git diff --submodule" print an extra line for new untracked content and another for modified but already tracked content. And if the HEAD of the submodule is equal to the ref diffed against in the superproject, drop the output which would just show the same SHA1s and no commit message headlines. To achieve that, the dirty_submodule bitfield is expanded to two bits. The output of "git status" inside the submodule is parsed to set the according bits. Signed-off-by: Jens Lehmann <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5ce9086 commit c7e1a73

File tree

5 files changed

+58
-21
lines changed

5 files changed

+58
-21
lines changed

diff-lib.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
180180
changed = ce_match_stat(ce, &st, ce_option);
181181
if (S_ISGITLINK(ce->ce_mode)
182182
&& !DIFF_OPT_TST(&revs->diffopt, IGNORE_SUBMODULES)
183-
&& (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
184-
&& is_submodule_modified(ce->name)) {
185-
changed = 1;
186-
dirty_submodule = 1;
183+
&& (!changed || (revs->diffopt.output_format & DIFF_FORMAT_PATCH))) {
184+
dirty_submodule = is_submodule_modified(ce->name);
185+
if (dirty_submodule)
186+
changed = 1;
187187
}
188188
if (!changed) {
189189
ce_mark_uptodate(ce);
@@ -243,10 +243,10 @@ static int get_stat_data(struct cache_entry *ce,
243243
changed = ce_match_stat(ce, &st, 0);
244244
if (S_ISGITLINK(ce->ce_mode)
245245
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)
246-
&& (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH))
247-
&& is_submodule_modified(ce->name)) {
248-
changed = 1;
249-
*dirty_submodule = 1;
246+
&& (!changed || (diffopt->output_format & DIFF_FORMAT_PATCH))) {
247+
*dirty_submodule = is_submodule_modified(ce->name);
248+
if (*dirty_submodule)
249+
changed = 1;
250250
}
251251
if (changed) {
252252
mode = ce_mode_from_stat(ce, st.st_mode);

diffcore.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ struct diff_filespec {
4242
#define DIFF_FILE_VALID(spec) (((spec)->mode) != 0)
4343
unsigned should_free : 1; /* data should be free()'ed */
4444
unsigned should_munmap : 1; /* data should be munmap()'ed */
45-
unsigned dirty_submodule : 1; /* For submodules: its work tree is dirty */
45+
unsigned dirty_submodule : 2; /* For submodules: its work tree is dirty */
46+
#define DIRTY_SUBMODULE_UNTRACKED 1
47+
#define DIRTY_SUBMODULE_MODIFIED 2
4648

4749
struct userdiff_driver *driver;
4850
/* data should be considered "binary"; -1 means "don't know yet" */

submodule.c

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "commit.h"
66
#include "revision.h"
77
#include "run-command.h"
8+
#include "diffcore.h"
89

910
static int add_submodule_odb(const char *path)
1011
{
@@ -85,13 +86,21 @@ void show_submodule_summary(FILE *f, const char *path,
8586
message = "(revision walker failed)";
8687
}
8788

89+
if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
90+
fprintf(f, "Submodule %s contains untracked content\n", path);
91+
if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
92+
fprintf(f, "Submodule %s contains modified content\n", path);
93+
94+
if (!hashcmp(one, two)) {
95+
strbuf_release(&sb);
96+
return;
97+
}
98+
8899
strbuf_addf(&sb, "Submodule %s %s..", path,
89100
find_unique_abbrev(one, DEFAULT_ABBREV));
90101
if (!fast_backward && !fast_forward)
91102
strbuf_addch(&sb, '.');
92103
strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
93-
if (dirty_submodule)
94-
strbuf_add(&sb, "-dirty", 6);
95104
if (message)
96105
strbuf_addf(&sb, " %s\n", message);
97106
else
@@ -121,9 +130,10 @@ void show_submodule_summary(FILE *f, const char *path,
121130
strbuf_release(&sb);
122131
}
123132

124-
int is_submodule_modified(const char *path)
133+
unsigned is_submodule_modified(const char *path)
125134
{
126-
int len, i;
135+
int i;
136+
ssize_t len;
127137
struct child_process cp;
128138
const char *argv[] = {
129139
"status",
@@ -132,6 +142,8 @@ int is_submodule_modified(const char *path)
132142
};
133143
const char *env[LOCAL_REPO_ENV_SIZE + 3];
134144
struct strbuf buf = STRBUF_INIT;
145+
unsigned dirty_submodule = 0;
146+
const char *line, *next_line;
135147

136148
for (i = 0; i < LOCAL_REPO_ENV_SIZE; i++)
137149
env[i] = local_repo_env[i];
@@ -161,6 +173,24 @@ int is_submodule_modified(const char *path)
161173
die("Could not run git status --porcelain");
162174

163175
len = strbuf_read(&buf, cp.out, 1024);
176+
line = buf.buf;
177+
while (len > 2) {
178+
if ((line[0] == '?') && (line[1] == '?')) {
179+
dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
180+
if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
181+
break;
182+
} else {
183+
dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
184+
if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
185+
break;
186+
}
187+
next_line = strchr(line, '\n');
188+
if (!next_line)
189+
break;
190+
next_line++;
191+
len -= (next_line - line);
192+
line = next_line;
193+
}
164194
close(cp.out);
165195

166196
if (finish_command(&cp))
@@ -169,5 +199,5 @@ int is_submodule_modified(const char *path)
169199
for (i = LOCAL_REPO_ENV_SIZE; env[i]; i++)
170200
free((char *)env[i]);
171201
strbuf_release(&buf);
172-
return len != 0;
202+
return dirty_submodule;
173203
}

submodule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ void show_submodule_summary(FILE *f, const char *path,
55
unsigned char one[20], unsigned char two[20],
66
unsigned dirty_submodule,
77
const char *del, const char *add, const char *reset);
8-
int is_submodule_modified(const char *path);
8+
unsigned is_submodule_modified(const char *path);
99

1010
#endif

t/t4041-diff-submodule.sh

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,23 +201,24 @@ test_expect_success 'submodule contains untracked content' "
201201
echo new > sm1/new-file &&
202202
git diff-index -p --submodule=log HEAD >actual &&
203203
diff actual - <<-EOF
204-
Submodule sm1 $head6..$head6-dirty:
204+
Submodule sm1 contains untracked content
205205
EOF
206206
"
207207

208208
test_expect_success 'submodule contains untracked and modifed content' "
209209
echo new > sm1/foo6 &&
210210
git diff-index -p --submodule=log HEAD >actual &&
211211
diff actual - <<-EOF
212-
Submodule sm1 $head6..$head6-dirty:
212+
Submodule sm1 contains untracked content
213+
Submodule sm1 contains modified content
213214
EOF
214215
"
215216

216217
test_expect_success 'submodule contains modifed content' "
217218
rm -f sm1/new-file &&
218219
git diff-index -p --submodule=log HEAD >actual &&
219220
diff actual - <<-EOF
220-
Submodule sm1 $head6..$head6-dirty:
221+
Submodule sm1 contains modified content
221222
EOF
222223
"
223224

@@ -235,7 +236,8 @@ test_expect_success 'modified submodule contains untracked content' "
235236
echo new > sm1/new-file &&
236237
git diff-index -p --submodule=log HEAD >actual &&
237238
diff actual - <<-EOF
238-
Submodule sm1 $head6..$head8-dirty:
239+
Submodule sm1 contains untracked content
240+
Submodule sm1 $head6..$head8:
239241
> change
240242
EOF
241243
"
@@ -244,7 +246,9 @@ test_expect_success 'modified submodule contains untracked and modifed content'
244246
echo modification >> sm1/foo6 &&
245247
git diff-index -p --submodule=log HEAD >actual &&
246248
diff actual - <<-EOF
247-
Submodule sm1 $head6..$head8-dirty:
249+
Submodule sm1 contains untracked content
250+
Submodule sm1 contains modified content
251+
Submodule sm1 $head6..$head8:
248252
> change
249253
EOF
250254
"
@@ -253,7 +257,8 @@ test_expect_success 'modified submodule contains modifed content' "
253257
rm -f sm1/new-file &&
254258
git diff-index -p --submodule=log HEAD >actual &&
255259
diff actual - <<-EOF
256-
Submodule sm1 $head6..$head8-dirty:
260+
Submodule sm1 contains modified content
261+
Submodule sm1 $head6..$head8:
257262
> change
258263
EOF
259264
"

0 commit comments

Comments
 (0)