Commit Diff


commit - 25eaa548f307f6a9b12153f62c2e66929b72a931
commit + e5b559621a323b6031c9bc473de545244744302c
blob - 71de0a97318ce099eeb356458c6f8e9153a0ef9a
blob + 4a2a83350706f7cfa28e7581baf9d6a1c97aefbb
--- dulwich/client.py
+++ dulwich/client.py
@@ -126,7 +126,7 @@ from dulwich.pack import (
 )
 from dulwich.refs import (
     read_info_refs,
-    ANNOTATED_TAG_SUFFIX,
+    PEELED_TAG_SUFFIX,
     _import_remote_refs,
 )
 from dulwich.repo import Repo
@@ -992,7 +992,7 @@ def check_wants(wants, refs):
 
     """
     missing = set(wants) - {
-        v for (k, v) in refs.items() if not k.endswith(ANNOTATED_TAG_SUFFIX)
+        v for (k, v) in refs.items() if not k.endswith(PEELED_TAG_SUFFIX)
     }
     if missing:
         raise InvalidWants(missing)
blob - ccef377c35774ca0f40daa705116704d70fdbffa
blob + 8d9b70351637dabed4e9545e0aae95cff2faa33d
--- dulwich/object_store.py
+++ dulwich/object_store.py
@@ -77,7 +77,7 @@ from dulwich.pack import (
     PACK_SPOOL_FILE_MAX_SIZE,
 )
 from dulwich.protocol import DEPTH_INFINITE
-from dulwich.refs import ANNOTATED_TAG_SUFFIX, Ref
+from dulwich.refs import PEELED_TAG_SUFFIX, Ref
 
 INFODIR = "info"
 PACKDIR = "pack"
@@ -115,7 +115,7 @@ class BaseObjectStore:
             sha
             for (ref, sha) in refs.items()
             if (sha not in self or _want_deepen(sha))
-            and not ref.endswith(ANNOTATED_TAG_SUFFIX)
+            and not ref.endswith(PEELED_TAG_SUFFIX)
             and not sha == ZERO_SHA
         ]
 
@@ -277,7 +277,7 @@ class BaseObjectStore:
         warnings.warn(
             "Please use dulwich.object_store.peel_sha()",
             DeprecationWarning, stacklevel=2)
-        return peel_sha(self, sha)
+        return peel_sha(self, sha)[1]
 
     def _get_depth(
         self, head, get_parents=lambda commit: commit.parents, max_depth=None,
@@ -1642,7 +1642,7 @@ def iter_tree_contents(
             yield entry
 
 
-def peel_sha(store: ObjectContainer, sha: bytes) -> ShaFile:
+def peel_sha(store: ObjectContainer, sha: bytes) -> Tuple[ShaFile, ShaFile]:
     """Peel all tags from a SHA.
 
     Args:
@@ -1651,10 +1651,10 @@ def peel_sha(store: ObjectContainer, sha: bytes) -> Sh
         intermediate tags; if the original ref does not point to a tag,
         this will equal the original SHA1.
     """
-    obj = store[sha]
+    unpeeled = obj = store[sha]
     obj_class = object_class(obj.type_name)
     while obj_class is Tag:
         assert isinstance(obj, Tag)
         obj_class, sha = obj.object
         obj = store[sha]
-    return obj
+    return unpeeled, obj
blob - 31d590f8a356e3a7829dfdf267e04c359bac0dcc
blob + 1fc178af8699bbec8acab64786a05c1d2d6e3244
--- dulwich/refs.py
+++ dulwich/refs.py
@@ -25,6 +25,7 @@
 from contextlib import suppress
 import os
 from typing import Dict, Optional
+import warnings
 
 from dulwich.errors import (
     PackedRefsException,
@@ -50,7 +51,10 @@ SYMREF = b"ref: "
 LOCAL_BRANCH_PREFIX = b"refs/heads/"
 LOCAL_TAG_PREFIX = b"refs/tags/"
 BAD_REF_CHARS = set(b"\177 ~^:?*[")
-ANNOTATED_TAG_SUFFIX = b"^{}"
+PEELED_TAG_SUFFIX = b"^{}"
+
+# For backwards compatibility
+ANNOTATED_TAG_SUFFIX = PEELED_TAG_SUFFIX
 
 
 class SymrefLoop(Exception):
@@ -593,7 +597,7 @@ class InfoRefsContainer(RefsContainer):
         self._peeled = {}
         for line in f.readlines():
             sha, name = line.rstrip(b"\n").split(b"\t")
-            if name.endswith(ANNOTATED_TAG_SUFFIX):
+            if name.endswith(PEELED_TAG_SUFFIX):
                 name = name[:-3]
                 if not check_ref_format(name):
                     raise ValueError("invalid ref name %r" % name)
@@ -1153,7 +1157,7 @@ def read_info_refs(f):
 
 def write_info_refs(refs, store: ObjectContainer):
     """Generate info refs."""
-    # Avoid recursive import :(
+    # TODO: Avoid recursive import :(
     from dulwich.object_store import peel_sha
     for name, sha in sorted(refs.items()):
         # get_refs() includes HEAD as a special case, but we don't want to
@@ -1164,10 +1168,10 @@ def write_info_refs(refs, store: ObjectContainer):
             o = store[sha]
         except KeyError:
             continue
-        peeled = peel_sha(store, sha)
+        unpeeled, peeled = peel_sha(store, sha)
         yield o.id + b"\t" + name + b"\n"
         if o.id != peeled.id:
-            yield peeled.id + b"\t" + name + ANNOTATED_TAG_SUFFIX + b"\n"
+            yield peeled.id + b"\t" + name + PEELED_TAG_SUFFIX + b"\n"
 
 
 def is_local_branch(x):
@@ -1179,7 +1183,7 @@ def strip_peeled_refs(refs):
     return {
         ref: sha
         for (ref, sha) in refs.items()
-        if not ref.endswith(ANNOTATED_TAG_SUFFIX)
+        if not ref.endswith(PEELED_TAG_SUFFIX)
     }
 
 
@@ -1275,6 +1279,27 @@ def _import_remote_refs(
     tags = {
         n[len(LOCAL_TAG_PREFIX) :]: v
         for (n, v) in stripped_refs.items()
-        if n.startswith(LOCAL_TAG_PREFIX) and not n.endswith(ANNOTATED_TAG_SUFFIX)
+        if n.startswith(LOCAL_TAG_PREFIX) and not n.endswith(PEELED_TAG_SUFFIX)
     }
     refs_container.import_refs(LOCAL_TAG_PREFIX, tags, message=message, prune=prune_tags)
+
+
+def serialize_refs(store, refs):
+    # TODO: Avoid recursive import :(
+    from dulwich.object_store import peel_sha
+    ret = {}
+    for ref, sha in refs.items():
+        try:
+            unpeeled, peeled = peel_sha(store, sha)
+        except KeyError:
+            warnings.warn(
+                "ref %s points at non-present sha %s"
+                % (ref.decode("utf-8", "replace"), sha.decode("ascii")),
+                UserWarning,
+            )
+            continue
+        else:
+            if isinstance(unpeeled, Tag):
+                ret[ref + PEELED_TAG_SUFFIX] = peeled.id
+            ret[ref] = unpeeled.id
+    return ret
blob - 3cd323f5a44bb429b2c8fd3d7c13d18c6f61d887
blob + e3faf8d12db1cc30b0f449743335830d599a1bc3
--- dulwich/repo.py
+++ dulwich/repo.py
@@ -46,7 +46,9 @@ from typing import (
     Iterable,
     Set
 )
+import warnings
 
+
 if TYPE_CHECKING:
     # There are no circular imports here, but we try to defer imports as long
     # as possible to reduce start-up time for anything that doesn't need
@@ -105,6 +107,7 @@ from dulwich.refs import (  # noqa: F401
     ANNOTATED_TAG_SUFFIX,
     LOCAL_BRANCH_PREFIX,
     LOCAL_TAG_PREFIX,
+    serialize_refs,
     check_ref_format,
     RefsContainer,
     DictRefsContainer,
@@ -118,9 +121,6 @@ from dulwich.refs import (  # noqa: F401
     _set_head,
     _set_origin_head,
 )
-
-
-import warnings
 
 
 CONTROLDIR = ".git"
@@ -520,21 +520,7 @@ class BaseRepo:
         if depth not in (None, 0):
             raise NotImplementedError("depth not supported yet")
 
-        refs = {}
-        for ref, sha in self.get_refs().items():
-            try:
-                obj = self.object_store[sha]
-            except KeyError:
-                warnings.warn(
-                    "ref %s points at non-present sha %s"
-                    % (ref.decode("utf-8", "replace"), sha.decode("ascii")),
-                    UserWarning,
-                )
-                continue
-            else:
-                if isinstance(obj, Tag):
-                    refs[ref + ANNOTATED_TAG_SUFFIX] = obj.object[1]
-                refs[ref] = sha
+        refs = serialize_refs(self.object_store, self.get_refs())
 
         wants = determine_wants(refs)
         if not isinstance(wants, list):
@@ -772,7 +758,7 @@ class BaseRepo:
         cached = self.refs.get_peeled(ref)
         if cached is not None:
             return cached
-        return peel_sha(self.object_store, self.refs[ref]).id
+        return peel_sha(self.object_store, self.refs[ref])[1].id
 
     def get_walker(self, include: Optional[List[bytes]] = None,
                    *args, **kwargs):
blob - 9b045eeddbada1386098f6c3630b629a693cb6ff
blob + b97d33048f27a3d47af4b0d3edae818b1534211e
--- dulwich/server.py
+++ dulwich/server.py
@@ -128,7 +128,7 @@ from dulwich.protocol import (
 )
 from dulwich.refs import (
     RefsContainer,
-    ANNOTATED_TAG_SUFFIX,
+    PEELED_TAG_SUFFIX,
     write_info_refs,
 )
 from dulwich.repo import (
@@ -499,9 +499,9 @@ def _find_shallow(store: ObjectContainer, heads, depth
 
     todo = []  # stack of (sha, depth)
     for head_sha in heads:
-        obj = peel_sha(store, head_sha)
-        if isinstance(obj, Commit):
-            todo.append((obj.id, 1))
+        _unpeeled, peeled = peel_sha(store, head_sha)
+        if isinstance(peeled, Commit):
+            todo.append((peeled.id, 1))
 
     not_shallow = set()
     shallow = set()
@@ -635,7 +635,7 @@ class _ProtocolGraphWalker:
                 self.proto.write_pkt_line(line)
                 if peeled_sha != sha:
                     self.proto.write_pkt_line(
-                        format_ref_line(ref + ANNOTATED_TAG_SUFFIX, peeled_sha))
+                        format_ref_line(ref + PEELED_TAG_SUFFIX, peeled_sha))
 
             # i'm done..
             self.proto.write_pkt_line(None)
blob - c03a11956bdd8f3a1c4abc67ae7c3fecdc52bd81
blob + 54b4f5d3f64b4f3f078e5a4404f6c0e504b44970
--- dulwich/tests/test_object_store.py
+++ dulwich/tests/test_object_store.py
@@ -264,7 +264,7 @@ class ObjectStoreTests:
         tag2 = self.make_tag(b"2", testobject)
         tag3 = self.make_tag(b"3", testobject)
         for obj in [testobject, tag1, tag2, tag3]:
-            self.assertEqual(testobject, peel_sha(self.store, obj.id))
+            self.assertEqual((obj, testobject), peel_sha(self.store, obj.id))
 
     def test_get_raw(self):
         self.store.add_object(testobject)