diff --git a/submodule.c b/submodule.c index 93e3fefd39..e72781d9f2 100644 --- a/submodule.c +++ b/submodule.c @@ -1041,12 +1041,12 @@ out: unsigned is_submodule_modified(const char *path, int ignore_untracked) { - ssize_t len; struct child_process cp = CHILD_PROCESS_INIT; struct strbuf buf = STRBUF_INIT; + FILE *fp; unsigned dirty_submodule = 0; - const char *line, *next_line; const char *git_dir; + int ignore_cp_exit_code = 0; strbuf_addf(&buf, "%s/.git", path); git_dir = read_gitfile(buf.buf); @@ -1072,29 +1072,27 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked) if (start_command(&cp)) die("Could not run 'git status --porcelain' in submodule %s", path); - len = strbuf_read(&buf, cp.out, 1024); - line = buf.buf; - while (len > 2) { - if ((line[0] == '?') && (line[1] == '?')) + fp = xfdopen(cp.out, "r"); + while (strbuf_getwholeline(&buf, fp, '\n') != EOF) { + if ((buf.buf[0] == '?') && (buf.buf[1] == '?')) dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED; else dirty_submodule |= DIRTY_SUBMODULE_MODIFIED; if ((dirty_submodule & DIRTY_SUBMODULE_MODIFIED) && ((dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) || - ignore_untracked)) + ignore_untracked)) { + /* + * We're not interested in any further information from + * the child any more, neither output nor its exit code. + */ + ignore_cp_exit_code = 1; break; - - next_line = strchr(line, '\n'); - if (!next_line) - break; - next_line++; - len -= (next_line - line); - line = next_line; + } } - close(cp.out); + fclose(fp); - if (finish_command(&cp)) + if (finish_command(&cp) && !ignore_cp_exit_code) die("'git status --porcelain' failed in submodule %s", path); strbuf_release(&buf); diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index d31b34da83..51f8d0d034 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -177,8 +177,24 @@ test_expect_success 'status with added file in modified submodule with .git file test_i18ngrep "modified: sub (new commits, modified content)" output ' +test_expect_success 'status with a lot of untracked files in the submodule' ' + ( + cd sub + i=0 && + while test $i -lt 1024 + do + >some-file-$i + i=$(( $i + 1 )) + done + ) && + git status --porcelain sub 2>err.actual && + test_must_be_empty err.actual && + rm err.actual +' + test_expect_success 'rm submodule contents' ' - rm -rf sub/* sub/.git + rm -rf sub && + mkdir sub ' test_expect_success 'status clean (empty submodule dir)' '