Migrate 'is_submodule_modified' to the new porcelain format of
git-status.

As the old porcelain only reported ' M' for submodules, no
matter what happened inside the submodule (untracked files,
changes to tracked files or move of HEAD), the new API
properly reports the different scenarios.

In a followup patch we will make use of these finer grained
reporting for git-status.

Signed-off-by: Stefan Beller <sbel...@google.com>
---
 submodule.c | 53 ++++++++++++++++++++++++-----------------------------
 1 file changed, 24 insertions(+), 29 deletions(-)

diff --git a/submodule.c b/submodule.c
index 3200b7bb2b..d355ddb46b 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1041,17 +1041,9 @@ int fetch_populated_submodules(const struct argv_array 
*options,
 
 unsigned is_submodule_modified(const char *path, int ignore_untracked)
 {
-       ssize_t len;
        struct child_process cp = CHILD_PROCESS_INIT;
-       const char *argv[] = {
-               "status",
-               "--porcelain",
-               NULL,
-               NULL,
-       };
        struct strbuf buf = STRBUF_INIT;
        unsigned dirty_submodule = 0;
-       const char *line, *next_line;
        const char *git_dir;
 
        strbuf_addf(&buf, "%s/.git", path);
@@ -1066,42 +1058,45 @@ unsigned is_submodule_modified(const char *path, int 
ignore_untracked)
        }
        strbuf_reset(&buf);
 
+       argv_array_pushl(&cp.args, "status", "--porcelain=2", NULL);
        if (ignore_untracked)
-               argv[2] = "-uno";
+               argv_array_push(&cp.args, "-uno");
 
-       cp.argv = argv;
        prepare_submodule_repo_env(&cp.env_array);
        cp.git_cmd = 1;
        cp.no_stdin = 1;
        cp.out = -1;
        cp.dir = path;
        if (start_command(&cp))
-               die("Could not run 'git status --porcelain' in submodule %s", 
path);
+               die("Could not run 'git status --porcelain=2' in submodule %s", 
path);
 
-       len = strbuf_read(&buf, cp.out, 1024);
-       line = buf.buf;
-       while (len > 2) {
-               if ((line[0] == '?') && (line[1] == '?')) {
+       while (strbuf_getwholeline_fd(&buf, cp.out, '\n') != EOF) {
+               /* regular untracked files */
+               if (buf.buf[0] == '?')
                        dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
-                       if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
-                               break;
-               } else {
-                       dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
-                       if (ignore_untracked ||
-                           (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED))
-                               break;
+
+               /* regular unmerged and renamed files */
+               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
+                               dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
                }
-               next_line = strchr(line, '\n');
-               if (!next_line)
-                       break;
-               next_line++;
-               len -= (next_line - line);
-               line = next_line;
+
+               if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED &&
+                   dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
+                               break;
        }
        close(cp.out);
 
        if (finish_command(&cp))
-               die("'git status --porcelain' failed in submodule %s", path);
+               die("'git status --porcelain=2' failed in submodule %s", path);
 
        strbuf_release(&buf);
        return dirty_submodule;
-- 
2.12.1.438.gb674c4c09c

Reply via email to