]> git.proxmox.com Git - libgit2.git/commitdiff
Merge pull request #1423 from arrbee/submodule-status-errors
authorVicent Martí <vicent@github.com>
Tue, 19 Mar 2013 18:47:23 +0000 (11:47 -0700)
committerVicent Martí <vicent@github.com>
Tue, 19 Mar 2013 18:47:23 +0000 (11:47 -0700)
Three submodule status bug fixes

36 files changed:
src/diff.c
src/diff_output.c
src/iterator.c
src/path.c
tests-clar/diff/iterator.c
tests-clar/diff/workdir.c
tests-clar/resources/submod2/not-submodule/.gitted/HEAD [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/config [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/description [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/index [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/info/exclude [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/logs/HEAD [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master [new file with mode: 0644]
tests-clar/resources/submod2/not-submodule/README.txt [new file with mode: 0644]
tests-clar/resources/submod2/not/.gitted/notempty [new file with mode: 0644]
tests-clar/resources/submod2/not/README.txt [new file with mode: 0644]
tests-clar/resources/submod2/not_submodule/.gitted/COMMIT_EDITMSG [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/HEAD [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/config [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/description [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/index [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/info/exclude [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/logs/HEAD [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/logs/refs/heads/master [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e [deleted file]
tests-clar/resources/submod2/not_submodule/.gitted/refs/heads/master [deleted file]
tests-clar/resources/submod2/not_submodule/README.txt [deleted file]
tests-clar/submodule/lookup.c
tests-clar/submodule/modify.c
tests-clar/submodule/status.c

index fc37d139d34e40424d45ae96bbfa0728c3a36b3e..fb69f8920332fe0b31b5da7374ae57e7d1913e0d 100644 (file)
@@ -512,13 +512,17 @@ static int maybe_modified(
                        status = GIT_DELTA_UNMODIFIED;
 
                else if (S_ISGITLINK(nmode)) {
+                       int err;
                        git_submodule *sub;
 
                        if ((diff->opts.flags & GIT_DIFF_IGNORE_SUBMODULES) != 0)
                                status = GIT_DELTA_UNMODIFIED;
-                       else if (git_submodule_lookup(&sub, diff->repo, nitem->path) < 0)
-                               return -1;
-                       else if (git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL)
+                       else if ((err = git_submodule_lookup(&sub, diff->repo, nitem->path)) < 0) {
+                               if (err == GIT_EEXISTS)
+                                       status = GIT_DELTA_UNMODIFIED;
+                               else
+                                       return err;
+                       } else if (git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL)
                                status = GIT_DELTA_UNMODIFIED;
                        else {
                                unsigned int sm_status = 0;
index b938cc06dbae923f17a39c62a381e7be7ca54b39..fba6129b7ba5df2815e71737605df8eacd795a0f 100644 (file)
@@ -299,7 +299,12 @@ static int get_workdir_sm_content(
 
        if ((error = git_submodule_lookup(&sm, ctxt->repo, file->path)) < 0 ||
                (error = git_submodule_status(&sm_status, sm)) < 0)
+       {
+               /* GIT_EEXISTS means a "submodule" that has not been git added */
+               if (error == GIT_EEXISTS)
+                       error = 0;
                return error;
+       }
 
        /* update OID if we didn't have it previously */
        if ((file->flags & GIT_DIFF_FLAG_VALID_OID) == 0) {
index b15bcedd8b457de605f51730f9c245d3674e9a2e..805a3c987ac6c471571e783c475e1ae59ded42c2 100644 (file)
@@ -1150,11 +1150,13 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
                return 0;
 
        /* detect submodules */
-
        error = git_submodule_lookup(NULL, wi->base.repo, wi->entry.path);
        if (error == GIT_ENOTFOUND)
                giterr_clear();
 
+       if (error == GIT_EEXISTS) /* if contains .git, treat as untracked submod */
+               error = 0;
+
        /* if submodule, mark as GITLINK and remove trailing slash */
        if (!error) {
                size_t len = strlen(wi->entry.path);
index 5767faeedf36042bb2325e4c499e103c35c5c324..6437979d5ed8de9d6573d9e1aaf17362492ff6c1 100644 (file)
@@ -877,15 +877,22 @@ int git_path_dirload_with_stat(
                if (cmp_len && strncomp(ps->path, end_stat, cmp_len) > 0)
                        continue;
 
+               git_buf_truncate(&full, prefix_len);
+
                if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
                        (error = git_path_lstat(full.ptr, &ps->st)) < 0)
                        break;
 
-               git_buf_truncate(&full, prefix_len);
-
                if (S_ISDIR(ps->st.st_mode)) {
-                       ps->path[ps->path_len++] = '/';
-                       ps->path[ps->path_len] = '\0';
+                       if ((error = git_buf_joinpath(&full, full.ptr, ".git")) < 0)
+                               break;
+
+                       if (p_access(full.ptr, F_OK) == 0) {
+                               ps->st.st_mode = GIT_FILEMODE_COMMIT;
+                       } else {
+                               ps->path[ps->path_len++] = '/';
+                               ps->path[ps->path_len] = '\0';
+                       }
                }
        }
 
index f1efdfbba7ce6a06b0ef550b64a1577d7ef71014..15b10465a7f2ae134fb4d3665694fd1abf81b961 100644 (file)
@@ -720,13 +720,13 @@ void test_diff_iterator__workdir_builtin_ignores(void)
                { "root_test2", false },
                { "root_test3", false },
                { "root_test4.txt", false },
-               { "sub/", false },
+               { "sub", false },
                { "sub/.gitattributes", false },
                { "sub/abc", false },
                { "sub/dir/", true },
                { "sub/file", false },
                { "sub/ign/", true },
-               { "sub/sub/", false },
+               { "sub/sub", false },
                { "sub/sub/.gitattributes", false },
                { "sub/sub/dir", false }, /* file is not actually a dir */
                { "sub/sub/file", false },
@@ -746,9 +746,13 @@ void test_diff_iterator__workdir_builtin_ignores(void)
                cl_assert_equal_s(expected[idx].path, entry->path);
                cl_assert_(ignored == expected[idx].ignored, expected[idx].path);
 
-               if (!ignored && S_ISDIR(entry->mode))
+               if (!ignored &&
+                       (entry->mode == GIT_FILEMODE_TREE ||
+                        entry->mode == GIT_FILEMODE_COMMIT))
+               {
+                       /* it is possible to advance "into" a submodule */
                        cl_git_pass(git_iterator_advance_into(&entry, i));
-               else
+               else
                        cl_git_pass(git_iterator_advance(&entry, i));
        }
 
index 7e8915c4b01d1042e47b628129b0ea1036199b8b..983465b2971ff47c9c39481b96ecc6cfe628a4d0 100644 (file)
@@ -936,7 +936,8 @@ void test_diff_workdir__submodules(void)
        p_rename("submod2_target/.gitted", "submod2_target/.git");
 
        rewrite_gitmodules(git_repository_workdir(g_repo));
-       p_rename("submod2/not_submodule/.gitted", "submod2/not_submodule/.git");
+       p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git");
+       p_rename("submod2/not/.gitted", "submod2/not/.git");
 
        cl_fixture_cleanup("submod2_target");
 
@@ -954,21 +955,22 @@ void test_diff_workdir__submodules(void)
        /* essentially doing: git diff 873585b94bdeabccea991ea5e3ec1a277895b698 */
 
        memset(&exp, 0, sizeof(exp));
+
        cl_git_pass(git_diff_foreach(
                diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
 
-       /* the following differs from "git diff 873585" by one "untracked" file
-        * because the diff list includes the "not_submodule/" directory which
-        * is not displayed in the text diff.
+       /* the following differs from "git diff 873585" by two "untracked" file
+        * because the diff list includes the "not" and "not-submodule" dirs which
+        * are not displayed in the text diff.
         */
 
-       cl_assert_equal_i(10, exp.files);
+       cl_assert_equal_i(11, exp.files);
 
        cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
        cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
        cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
        cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
-       cl_assert_equal_i(9, exp.file_status[GIT_DELTA_UNTRACKED]);
+       cl_assert_equal_i(10, exp.file_status[GIT_DELTA_UNTRACKED]);
 
        /* the following numbers match "git diff 873585" exactly */
 
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/HEAD b/tests-clar/resources/submod2/not-submodule/.gitted/HEAD
new file mode 100644 (file)
index 0000000..cb089cd
--- /dev/null
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/config b/tests-clar/resources/submod2/not-submodule/.gitted/config
new file mode 100644 (file)
index 0000000..af10792
--- /dev/null
@@ -0,0 +1,6 @@
+[core]
+       repositoryformatversion = 0
+       filemode = true
+       bare = false
+       logallrefupdates = true
+       ignorecase = true
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/description b/tests-clar/resources/submod2/not-submodule/.gitted/description
new file mode 100644 (file)
index 0000000..498b267
--- /dev/null
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/index b/tests-clar/resources/submod2/not-submodule/.gitted/index
new file mode 100644 (file)
index 0000000..f3fafa5
Binary files /dev/null and b/tests-clar/resources/submod2/not-submodule/.gitted/index differ
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/info/exclude b/tests-clar/resources/submod2/not-submodule/.gitted/info/exclude
new file mode 100644 (file)
index 0000000..a5196d1
--- /dev/null
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/logs/HEAD b/tests-clar/resources/submod2/not-submodule/.gitted/logs/HEAD
new file mode 100644 (file)
index 0000000..1749e7d
--- /dev/null
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer <rb@github.com> 1342560358 -0700      commit (initial): Initial commit
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master b/tests-clar/resources/submod2/not-submodule/.gitted/logs/refs/heads/master
new file mode 100644 (file)
index 0000000..1749e7d
--- /dev/null
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer <rb@github.com> 1342560358 -0700      commit (initial): Initial commit
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 b/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444
new file mode 100644 (file)
index 0000000..8892531
Binary files /dev/null and b/tests-clar/resources/submod2/not-submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 differ
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 b/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627
new file mode 100644 (file)
index 0000000..c4e1a77
Binary files /dev/null and b/tests-clar/resources/submod2/not-submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 differ
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e b/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e
new file mode 100644 (file)
index 0000000..e9f1942
Binary files /dev/null and b/tests-clar/resources/submod2/not-submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e differ
diff --git a/tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master b/tests-clar/resources/submod2/not-submodule/.gitted/refs/heads/master
new file mode 100644 (file)
index 0000000..0bd8514
--- /dev/null
@@ -0,0 +1 @@
+68e92c611b80ee1ed8f38314ff9577f0d15b2444
diff --git a/tests-clar/resources/submod2/not-submodule/README.txt b/tests-clar/resources/submod2/not-submodule/README.txt
new file mode 100644 (file)
index 0000000..71ff992
--- /dev/null
@@ -0,0 +1 @@
+This is a git repo but not a submodule
diff --git a/tests-clar/resources/submod2/not/.gitted/notempty b/tests-clar/resources/submod2/not/.gitted/notempty
new file mode 100644 (file)
index 0000000..9b33ac4
--- /dev/null
@@ -0,0 +1 @@
+fooled you
diff --git a/tests-clar/resources/submod2/not/README.txt b/tests-clar/resources/submod2/not/README.txt
new file mode 100644 (file)
index 0000000..4f6935b
--- /dev/null
@@ -0,0 +1 @@
+what am I really
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/COMMIT_EDITMSG b/tests-clar/resources/submod2/not_submodule/.gitted/COMMIT_EDITMSG
deleted file mode 100644 (file)
index 5852f44..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Initial commit
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/HEAD b/tests-clar/resources/submod2/not_submodule/.gitted/HEAD
deleted file mode 100644 (file)
index cb089cd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-ref: refs/heads/master
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/config b/tests-clar/resources/submod2/not_submodule/.gitted/config
deleted file mode 100644 (file)
index af10792..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[core]
-       repositoryformatversion = 0
-       filemode = true
-       bare = false
-       logallrefupdates = true
-       ignorecase = true
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/description b/tests-clar/resources/submod2/not_submodule/.gitted/description
deleted file mode 100644 (file)
index 498b267..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/index b/tests-clar/resources/submod2/not_submodule/.gitted/index
deleted file mode 100644 (file)
index f3fafa5..0000000
Binary files a/tests-clar/resources/submod2/not_submodule/.gitted/index and /dev/null differ
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/info/exclude b/tests-clar/resources/submod2/not_submodule/.gitted/info/exclude
deleted file mode 100644 (file)
index a5196d1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# git ls-files --others --exclude-from=.git/info/exclude
-# Lines that start with '#' are comments.
-# For a project mostly in C, the following would be a good set of
-# exclude patterns (uncomment them if you want to use them):
-# *.[oa]
-# *~
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/logs/HEAD b/tests-clar/resources/submod2/not_submodule/.gitted/logs/HEAD
deleted file mode 100644 (file)
index 1749e7d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer <rb@github.com> 1342560358 -0700      commit (initial): Initial commit
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/logs/refs/heads/master b/tests-clar/resources/submod2/not_submodule/.gitted/logs/refs/heads/master
deleted file mode 100644 (file)
index 1749e7d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0000000000000000000000000000000000000000 68e92c611b80ee1ed8f38314ff9577f0d15b2444 Russell Belfer <rb@github.com> 1342560358 -0700      commit (initial): Initial commit
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 b/tests-clar/resources/submod2/not_submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444
deleted file mode 100644 (file)
index 8892531..0000000
Binary files a/tests-clar/resources/submod2/not_submodule/.gitted/objects/68/e92c611b80ee1ed8f38314ff9577f0d15b2444 and /dev/null differ
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 b/tests-clar/resources/submod2/not_submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627
deleted file mode 100644 (file)
index c4e1a77..0000000
Binary files a/tests-clar/resources/submod2/not_submodule/.gitted/objects/71/ff9927d7c8a5639e062c38a7d35c433c424627 and /dev/null differ
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e b/tests-clar/resources/submod2/not_submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e
deleted file mode 100644 (file)
index e9f1942..0000000
Binary files a/tests-clar/resources/submod2/not_submodule/.gitted/objects/f0/1d56b18efd353ef2bb93a4585d590a0847195e and /dev/null differ
diff --git a/tests-clar/resources/submod2/not_submodule/.gitted/refs/heads/master b/tests-clar/resources/submod2/not_submodule/.gitted/refs/heads/master
deleted file mode 100644 (file)
index 0bd8514..0000000
+++ /dev/null
@@ -1 +0,0 @@
-68e92c611b80ee1ed8f38314ff9577f0d15b2444
diff --git a/tests-clar/resources/submod2/not_submodule/README.txt b/tests-clar/resources/submod2/not_submodule/README.txt
deleted file mode 100644 (file)
index 71ff992..0000000
+++ /dev/null
@@ -1 +0,0 @@
-This is a git repo but not a submodule
index 868b51e558c277e00032347df3c0d9c2bcec63db..acf8f646275cc1c96806699d6a02573dfcf76538 100644 (file)
@@ -13,7 +13,7 @@ void test_submodule_lookup__initialize(void)
 
        /* must create submod2_target before rewrite so prettify will work */
        rewrite_gitmodules(git_repository_workdir(g_repo));
-       p_rename("submod2/not_submodule/.gitted", "submod2/not_submodule/.git");
+       p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git");
 }
 
 void test_submodule_lookup__cleanup(void)
@@ -39,7 +39,7 @@ void test_submodule_lookup__simple_lookup(void)
        cl_assert(sm);
 
        /* lookup git repo subdir that is not added as submodule */
-       cl_assert(git_submodule_lookup(&sm, g_repo, "not_submodule") == GIT_EEXISTS);
+       cl_assert(git_submodule_lookup(&sm, g_repo, "not-submodule") == GIT_EEXISTS);
 
        /* lookup existing directory that is not a submodule */
        cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_dir") == GIT_ENOTFOUND);
index f6d41fdf2437f7086f2026122ed88bd41bf6bc22..94eb3738abb2d156c491183db530756ecee1eb8a 100644 (file)
@@ -18,7 +18,7 @@ void test_submodule_modify__initialize(void)
 
        /* must create submod2_target before rewrite so prettify will work */
        rewrite_gitmodules(git_repository_workdir(g_repo));
-       p_rename("submod2/not_submodule/.gitted", "submod2/not_submodule/.git");
+       p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git");
 }
 
 void test_submodule_modify__cleanup(void)
index 3fd6960c9dd69e1be6aaaf933c081a96ffde5252..282e827580ab29f964209b26e72b13479d48fe0e 100644 (file)
@@ -3,6 +3,7 @@
 #include "path.h"
 #include "submodule_helpers.h"
 #include "fileops.h"
+#include "iterator.h"
 
 static git_repository *g_repo = NULL;
 
@@ -15,7 +16,8 @@ void test_submodule_status__initialize(void)
 
        /* must create submod2_target before rewrite so prettify will work */
        rewrite_gitmodules(git_repository_workdir(g_repo));
-       p_rename("submod2/not_submodule/.gitted", "submod2/not_submodule/.git");
+       p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git");
+       p_rename("submod2/not/.gitted", "submod2/not/.git");
 }
 
 void test_submodule_status__cleanup(void)
@@ -52,7 +54,12 @@ void test_submodule_status__ignore_none(void)
        cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged"));
        cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES));
 
-       cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
+       cl_assert_equal_i(GIT_ENOTFOUND,
+               git_submodule_lookup(&sm, g_repo, "just_a_dir"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not-submodule"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
        cl_git_pass(git_submodule_status(&status, sm));
@@ -138,7 +145,7 @@ void test_submodule_status__ignore_untracked(void)
 
        cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 
-       cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
+       cl_git_fail(git_submodule_lookup(&sm, g_repo, "not-submodule"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
        cl_git_pass(git_submodule_status(&status, sm));
@@ -198,7 +205,12 @@ void test_submodule_status__ignore_dirty(void)
 
        cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 
-       cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
+       cl_assert_equal_i(GIT_ENOTFOUND,
+               git_submodule_lookup(&sm, g_repo, "just_a_dir"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not-submodule"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
        cl_git_pass(git_submodule_status(&status, sm));
@@ -258,7 +270,12 @@ void test_submodule_status__ignore_all(void)
 
        cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign));
 
-       cl_git_fail(git_submodule_lookup(&sm, g_repo, "not_submodule"));
+       cl_assert_equal_i(GIT_ENOTFOUND,
+               git_submodule_lookup(&sm, g_repo, "just_a_dir"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not-submodule"));
+       cl_assert_equal_i(GIT_EEXISTS,
+               git_submodule_lookup(&sm, g_repo, "not"));
 
        cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index"));
        cl_git_pass(git_submodule_status(&status, sm));
@@ -305,3 +322,64 @@ void test_submodule_status__ignore_all(void)
 
        git_buf_free(&path);
 }
+
+typedef struct {
+       size_t counter;
+       const char **paths;
+} submodule_expectations;
+
+static int confirm_submodule_status(
+       const char *path, unsigned int status_flags, void *payload)
+{
+       submodule_expectations *exp = payload;
+
+       while (git__suffixcmp(exp->paths[exp->counter], "/") == 0)
+               exp->counter++;
+
+       cl_assert_equal_s(exp->paths[exp->counter++], path);
+
+       GIT_UNUSED(status_flags);
+
+       return 0;
+}
+
+void test_submodule_status__iterator(void)
+{
+       git_iterator *iter;
+       const git_index_entry *entry;
+       size_t i;
+       static const char *expected[] = {
+               ".gitmodules",
+               "just_a_dir/",
+               "just_a_dir/contents",
+               "just_a_file",
+               "not",
+               "not-submodule",
+               "README.txt",
+               "sm_added_and_uncommited",
+               "sm_changed_file",
+               "sm_changed_head",
+               "sm_changed_index",
+               "sm_changed_untracked_file",
+               "sm_missing_commits",
+               "sm_unchanged",
+               NULL
+       };
+       submodule_expectations exp = { 0, expected };
+       git_status_options opts = GIT_STATUS_OPTIONS_INIT;
+
+       cl_git_pass(git_iterator_for_workdir(&iter, g_repo,
+               GIT_ITERATOR_IGNORE_CASE | GIT_ITERATOR_INCLUDE_TREES, NULL, NULL));
+       cl_git_pass(git_iterator_current(&entry, iter));
+
+       for (i = 0; entry; ++i) {
+               cl_assert_equal_s(expected[i], entry->path);
+               cl_git_pass(git_iterator_advance(&entry, iter));
+       }
+
+       git_iterator_free(iter);
+
+       opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNMODIFIED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS;
+
+       cl_git_pass(git_status_foreach_ext(g_repo, &opts, confirm_submodule_status, &exp));
+}