Commit Diff


commit - a36e3c039fb1cd09ddd1729531b1cf9fb99924ab
commit + cd0990259901351400deda93b529ec601cfa52e8
blob - 1a32cba7c1d31c5b72e5a441694d35fe8dd8739d
blob + 2bd10877cd808773a2d5a1605d932e55fd39faa9
--- dulwich/config.py
+++ dulwich/config.py
@@ -780,9 +780,15 @@ def parse_submodules(config: ConfigFile) -> Iterator[T
     for section in config.keys():
         section_kind, section_name = section
         if section_kind == b"submodule":
-            sm_path = config.get(section, b"path")
-            sm_url = config.get(section, b"url")
-            yield (sm_path, sm_url, section_name)
+            try:
+                sm_path = config.get(section, b"path")
+                sm_url = config.get(section, b"url")
+                yield (sm_path, sm_url, section_name)
+            except KeyError:
+                # If either path or url is missing, just ignore this
+                # submodule entry and move on to the next one. This is
+                # how git itself handles malformed .gitmodule entries.
+                pass
 
 
 def iter_instead_of(config: Config, push: bool = False) -> Iterable[Tuple[str, str]]:
blob - bae048eb8cb49312297092a659afe04fa65afda8
blob + a0504779241d7815df318aab87762de1fe8b12c8
--- dulwich/tests/test_config.py
+++ dulwich/tests/test_config.py
@@ -438,7 +438,32 @@ class SubmodulesTests(TestCase):
             got,
         )
 
+    def testMalformedSubmodules(self):
+        cf = ConfigFile.from_file(
+            BytesIO(
+                b"""\
+[submodule "core/lib"]
+\tpath = core/lib
+\turl = https://github.com/phhusson/QuasselC.git
 
+[submodule "dulwich"]
+\turl = https://github.com/jelmer/dulwich
+"""
+            )
+        )
+        got = list(parse_submodules(cf))
+        self.assertEqual(
+            [
+                (
+                    b"core/lib",
+                    b"https://github.com/phhusson/QuasselC.git",
+                    b"core/lib",
+                )
+            ],
+            got,
+        )
+
+
 class ApplyInsteadOfTests(TestCase):
     def test_none(self):
         config = ConfigDict()