Commit Diff


commit - e71ece5e66f81979a2671e7476eaaf5330c250a8
commit + b429680214ae2d783b8083bd77fcfba47b00f193
blob - ad6b35a85bec0a09837929f09ec18edbf3c000b3
blob + 4efe218df4705b4872b4fbc19bac6377aacf3d44
--- .codespellrc
+++ .codespellrc
@@ -1,3 +1,3 @@
 [codespell]
 skip = .git,.mypy_cache,build,testdata
-ignore-words-list = fpr,claus,feld,nd,bu,ue,te,fo,afile
+ignore-words-list = fpr,claus,feld,nd,bu,ue,te,fo,afile,manuel
blob - f8394b70e96c50def4b75cefd43767682f51892c
blob + 3e446cbf91cdcde876da75c530189719a92b4fa3
--- .github/workflows/pythontest.yml
+++ .github/workflows/pythontest.yml
@@ -50,7 +50,7 @@ jobs:
       - name: codespell
         run: |
           pip install --upgrade codespell
-          codespell .
+          codespell --config .codespellrc .
       - name: Coverage test suite run
         run: |
           pip install --upgrade coverage
blob - 9948240f563288356649e9bebf4587b1c85a24e1
blob + 112e0cd238044a9aaee44fcdfb0c38888a751c0c
--- Makefile
+++ Makefile
@@ -78,3 +78,8 @@ apidocs:
 
 fix:
 	ruff check --fix .
+
+.PHONY: codespell
+
+codespell:
+	codespell --config .codespellrc .
blob - 0cf8440918f484e0a905a35ea15405026c9eaec7
blob + a1823e516b89e8e81b5417bc7e22a6a079fd618f
--- NEWS
+++ NEWS
@@ -6,6 +6,9 @@
  * Raise exception when default identity can't be found.
    (Jelmer Vernooij)
 
+ * Add a dedicated exception class for unresolved
+   deltas. (Jelmer Vernooij, #1221)
+
 0.21.6	2023-09-02
 
  * index: Handle different stages of conflicted paths.
blob - 82e92994deaf0d55feb23214584ba299d7f690cc
blob + 8f373accb91528669d473c2efca813656e687647
--- dulwich/client.py
+++ dulwich/client.py
@@ -2210,7 +2210,7 @@ class Urllib3HttpGitClient(AbstractHttpGitClient):
             import urllib3.util
 
             basic_auth = urllib3.util.make_headers(basic_auth=credentials)
-            self.pool_manager.headers.update(basic_auth)
+            self.pool_manager.headers.update(basic_auth)  # type: ignore
 
         self.config = config
 
blob - 24b27f83d0efb08f038357a54a354aa223032acb
blob + 03ae5943b86502b28b939379c86832554b05316f
--- dulwich/pack.py
+++ dulwich/pack.py
@@ -108,6 +108,13 @@ ProgressFn = Callable[[int, str], None]
 PackHint = Tuple[int, Optional[bytes]]
 
 
+class UnresolvedDeltas(Exception):
+    """"Delta objects could not be resolved."""
+
+    def __init__(self, shas):
+        self.shas = shas
+
+
 class ObjectContainer(Protocol):
 
     def add_object(self, obj: ShaFile) -> None:
@@ -1443,7 +1450,7 @@ class DeltaChainIterator(Generic[T]):
 
     def _ensure_no_pending(self) -> None:
         if self._pending_ref:
-            raise KeyError([sha_to_hex(s) for s in self._pending_ref])
+            raise UnresolvedDeltas([sha_to_hex(s) for s in self._pending_ref])
 
     def _walk_ref_chains(self):
         if not self._resolve_ext_ref:
@@ -2442,7 +2449,7 @@ class Pack:
                 yield child
         assert not ofs_pending
         if not allow_missing and todo:
-            raise KeyError(todo.pop())
+            raise UnresolvedDeltas(todo)
 
     def iter_unpacked(self, include_comp=False):
         ofs_to_entries = {ofs: (sha, crc32) for (sha, ofs, crc32) in self.index.iterentries()}
blob - b63f0c47eadc034d9f745cdc158697159dd32ff0
blob + ca87f2a95b81272d6e2204d45976e4c965655482
--- dulwich/tests/test_pack.py
+++ dulwich/tests/test_pack.py
@@ -46,6 +46,7 @@ from ..pack import (
     PackData,
     PackStreamReader,
     UnpackedObject,
+    UnresolvedDeltas,
     _delta_encode_size,
     _encode_copy_operation,
     apply_delta,
@@ -592,7 +593,7 @@ class TestThinPack(PackTests):
 
     def test_iterobjects(self):
         with self.make_pack(False) as p:
-            self.assertRaises(KeyError, list, p.iterobjects())
+            self.assertRaises(UnresolvedDeltas, list, p.iterobjects())
         with self.make_pack(True) as p:
             self.assertEqual(
                 sorted(
@@ -1216,8 +1217,8 @@ class DeltaChainIteratorTests(TestCase):
         try:
             list(pack_iter._walk_all_chains())
             self.fail()
-        except KeyError as e:
-            self.assertEqual(([blob.id],), e.args)
+        except UnresolvedDeltas as e:
+            self.assertEqual([blob.id], e.shas)
 
     def test_bad_ext_ref_thin_pack(self):
         b1, b2, b3 = self.store_blobs([b"foo", b"bar", b"baz"])
@@ -1238,8 +1239,8 @@ class DeltaChainIteratorTests(TestCase):
         try:
             list(pack_iter._walk_all_chains())
             self.fail()
-        except KeyError as e:
-            self.assertEqual((sorted([b2.id, b3.id]),), (sorted(e.args[0]),))
+        except UnresolvedDeltas as e:
+            self.assertEqual((sorted([b2.id, b3.id]),), (sorted(e.shas),))
 
 
 class DeltaEncodeSizeTests(TestCase):