Stefan Beller wrote:
> When a nested submodule has untracked files, it would be reported as
> "modified submodule" in the superproject, because submodules are not
> parsed correctly in is_submodule_modified as they are bucketed into
> the modified pile as "they are not an untracked file".
>
> Signed-off-by: Stefan Beller <[email protected]>
> ---
> submodule.c | 16 ++++++++++++++--
> t/t3600-rm.sh | 2 +-
> t/t7506-status-submodule.sh | 2 +-
> 3 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/submodule.c b/submodule.c
> index 467f1de763..ec7e9b1b06 100644
> --- a/submodule.c
> +++ b/submodule.c
> @@ -1078,8 +1078,20 @@ unsigned is_submodule_modified(const char *path, int
> ignore_untracked)
> /* regular untracked files */
> if (buf.buf[0] == '?')
> dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
> - else
> - dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
> +
> + /* regular unmerged and renamed files */
> + if (buf.buf[0] == 'u' ||
> + buf.buf[0] == '1' ||
> + buf.buf[0] == '2') {
> + if (buf.buf[5] == 'S') {
Can this overflow the buffer? Submodule state is supposed to be 4
characters, so could do
/*
* T XY SSSS:
* T = line type, XY = status, SSSS = submodule state
*/
if (buf.len < 1 + 1 + 2 + 1 + 4)
die("BUG: invalid status --porcelain=2 line %s",
buf.buf);
if (buf.buf[5] == 'S' && buf.buf[8] == 'U')
/* untracked file */
dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
if (memcmp(buf.buf + 5, "S..U", 4))
/* other change */
dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
}
> + /* nested submodule handling */
> + if (buf.buf[6] == 'C' || buf.buf[7] == 'M')
> + dirty_submodule |=
> DIRTY_SUBMODULE_MODIFIED;
> + if (buf.buf[8] == 'U')
> + dirty_submodule |=
> DIRTY_SUBMODULE_UNTRACKED;
> + } else
> + dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
> + }
I get lost in these cases. What does it mean if we see S..., for
example?
As an example, if I am understanding correctly, before this patch, if
I have a submodule-in-submodule:
$ find . -name .git
.git
sub/.git
sub/subsub/.git
and I put a stray file in the sub-sub module:
$ echo stray-file >sub/subsub/x.o
then status --porcelain=2 tells me that sub is modified:
$ git status --porcelain=2
1 .M S.M. [...] sub
What should it say after the patch? Is the XY field ".." or ".M"?
Some tests covering these cases with --porcelain=2 and a brief mention
in documentation may help.
Thanks,
Jonathan
diff --git i/submodule.c w/submodule.c
index ec7e9b1b06..aec1b2cdca 100644
--- i/submodule.c
+++ w/submodule.c
@@ -1083,13 +1083,18 @@ unsigned is_submodule_modified(const char *path, int
ignore_untracked)
if (buf.buf[0] == 'u' ||
buf.buf[0] == '1' ||
buf.buf[0] == '2') {
- if (buf.buf[5] == 'S') {
- /* nested submodule handling */
- if (buf.buf[6] == 'C' || buf.buf[7] == 'M')
- dirty_submodule |=
DIRTY_SUBMODULE_MODIFIED;
- if (buf.buf[8] == 'U')
- dirty_submodule |=
DIRTY_SUBMODULE_UNTRACKED;
- } else
+ /*
+ * T XY SSSS:
+ * T = line type, XY = status, SSSS = submodule state
+ */
+ if (buf.len < 1 + 1 + 2 + 1 + 4)
+ die("BUG: invalid status --porcelain=2 line %s",
+ buf.buf);
+ if (buf.buf[5] == 'S' && buf.buf[8] == 'U')
+ /* untracked file */
+ dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
+ if (memcmp(buf.buf + 5, "S..U", 4))
+ /* other change */
dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
}