submodule.c: correctly handle nested submodules in is_submodule_modified
authorStefan Beller <sbeller@google.com>
Wed, 29 Mar 2017 22:26:16 +0000 (15:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 30 Mar 2017 00:37:21 +0000 (17:37 -0700)
Suppose I have a superproject 'super', with two submodules 'super/sub'
and 'super/sub1'. 'super/sub' itself contains a submodule
'super/sub/subsub'. Now suppose I run, from within 'super':

echo hi >sub/subsub/stray-file
echo hi >sub1/stray-file

Currently we get would see the following output in git-status:

git status --short
m sub
? sub1

With this patch applied, the untracked file in the nested submodule is
displayed as an untracked file on the 'super' level as well.

git status --short
? sub
? sub1

This doesn't change the output of 'git status --porcelain=1' for nested
submodules, because its output is always ' M' for either untracked files
or local modifications no matter the nesting level of the submodule.

'git status --porcelain=2' is affected by this change in a nested
submodule, though. Without this patch it would report the direct submodule
as modified and having no untracked files. With this patch it would report
untracked files. Chalk this up as a bug fix.

This bug fix also affects the default output (non-short, non-porcelain)
of git-status, which is not tested here.

Signed-off-by: Stefan Beller <sbeller@google.com>
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-status.txt
submodule.c
t/t3600-rm.sh
t/t7506-status-submodule.sh
index 67f1a910f3c330a2e7c7389e43e7c120a54ec882..d70abc6afe3aa40aaaab2e055ee75d8ee22cdb69 100644 (file)
@@ -189,6 +189,8 @@ Submodules have more state and instead report
 since modified content or untracked files in a submodule cannot be added
 via `git add` in the superproject to prepare a commit.
 
+'m' and '?' are applied recursively. For example if a nested submodule
+in a submodule contains an untracked file, this is reported as '?' as well.
 
 If -b is used the short-format status is preceded by a line
 
index fa21c7bb72436c295430f815b528006d4bd95128..3da65100e39b85ff9aaa2f40f60c9b35820c6512 100644 (file)
@@ -1078,8 +1078,25 @@ 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;
+
+               if (buf.buf[0] == 'u' ||
+                   buf.buf[0] == '1' ||
+                   buf.buf[0] == '2') {
+                       /* T = line type, XY = status, SSSS = submodule state */
+                       if (buf.len < strlen("T XY SSSS"))
+                               die("BUG: invalid status --porcelain=2 line %s",
+                                   buf.buf);
+
+                       if (buf.buf[5] == 'S' && buf.buf[8] == 'U')
+                               /* nested untracked file */
+                               dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
+
+                       if (buf.buf[0] == 'u' ||
+                           buf.buf[0] == '2' ||
+                           memcmp(buf.buf + 5, "S..U", 4))
+                               /* other change */
+                               dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
+               }
 
                if ((dirty_submodule & DIRTY_SUBMODULE_MODIFIED) &&
                    ((dirty_submodule & DIRTY_SUBMODULE_UNTRACKED) ||
index a6e5c5bd5607dcf5ebd398179e30deba319ab127..b58793448b55c3ad339703a4bbe316c5aaf8320b 100755 (executable)
@@ -659,7 +659,7 @@ test_expect_success 'rm of a populated nested submodule with nested untracked fi
        test -d submod &&
        test -f submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
-       test_cmp expect.modified_inside actual &&
+       test_cmp expect.modified_untracked actual &&
        git rm -f submod &&
        test ! -d submod &&
        git status -s -uno --ignore-submodules=none >actual &&
index 1fa2ff29093b7728dcaec367515fbb48ff265de0..055c90736e9c0cfb60fef7db643f30c7573de581 100755 (executable)
@@ -356,7 +356,7 @@ test_expect_success 'status with untracked file in nested submodule (porcelain=2
        git -C super status --porcelain=2 >output &&
        sanitize_output output &&
        diff output - <<-\EOF
-       1 .M S.M. 160000 160000 160000 HASH HASH sub1
+       1 .M S..U 160000 160000 160000 HASH HASH sub1
        1 .M S..U 160000 160000 160000 HASH HASH sub2
        1 .M S..U 160000 160000 160000 HASH HASH sub3
        EOF
@@ -365,7 +365,7 @@ test_expect_success 'status with untracked file in nested submodule (porcelain=2
 test_expect_success 'status with untracked file in nested submodule (short)' '
        git -C super status --short >output &&
        diff output - <<-\EOF
-        m sub1
+        ? sub1
         ? sub2
         ? sub3
        EOF