Browse Source

return peeled refs from GitClient.get_refs() if protocol-v2 is used

This aligns protocol-v2 behaviour with earlier protocol versions.
Add test coverage for this behaviour, too.

Fixes issue #1410
Stefan Sperling 4 months ago
parent
commit
65307ed577
2 changed files with 30 additions and 2 deletions
  1. 9 2
      dulwich/client.py
  2. 21 0
      tests/compat/test_client.py

+ 9 - 2
dulwich/client.py

@@ -1378,6 +1378,7 @@ class TraditionalGitClient(GitClient):
                 proto.write_pkt_line(b"command=ls-refs\n")
                 proto.write(b"0001")  # delim-pkt
                 proto.write_pkt_line(b"symrefs")
+                proto.write_pkt_line(b"peel")
                 for prefix in ref_prefix:
                     proto.write_pkt_line(b"ref-prefix " + prefix)
                 proto.write_pkt_line(None)
@@ -1458,13 +1459,16 @@ class TraditionalGitClient(GitClient):
             proto.write_pkt_line(b"command=ls-refs\n")
             proto.write(b"0001")  # delim-pkt
             proto.write_pkt_line(b"symrefs")
+            proto.write_pkt_line(b"peel")
             proto.write_pkt_line(None)
             with proto:
                 try:
-                    refs, _symrefs, _peeled = read_pkt_refs_v2(proto.read_pkt_seq())
+                    refs, _symrefs, peeled = read_pkt_refs_v2(proto.read_pkt_seq())
                 except HangupException as exc:
                     raise _remote_error_from_stderr(stderr) from exc
                 proto.write_pkt_line(None)
+                for refname, refvalue in peeled.items():
+                    refs[refname + PEELED_TAG_SUFFIX] = refvalue
                 return refs
         else:
             with proto:
@@ -2407,6 +2411,7 @@ class AbstractHttpGitClient(GitClient):
                         pkt_line(b"command=ls-refs\n")
                         + b"0001"
                         + pkt_line(b"symrefs")
+                        + pkt_line(b"peel")
                         + b"0000",
                     )
                     proto = Protocol(read, None)
@@ -2673,7 +2678,9 @@ class AbstractHttpGitClient(GitClient):
     def get_refs(self, path):
         """Retrieve the current refs from a git smart server."""
         url = self._get_url(path)
-        refs, _, _, _, _ = self._discover_references(b"git-upload-pack", url)
+        refs, _, _, _, peeled = self._discover_references(b"git-upload-pack", url)
+        for refname, refvalue in peeled.items():
+            refs[refname + PEELED_TAG_SUFFIX] = refvalue
         return refs
 
     def get_url(self, path):

+ 21 - 0
tests/compat/test_client.py

@@ -37,6 +37,7 @@ from unittest.mock import patch
 from urllib.parse import unquote
 
 from dulwich import client, file, index, objects, protocol, repo
+from dulwich.porcelain import tag_create
 
 from .. import SkipTest, expectedFailure
 from .utils import (
@@ -249,6 +250,26 @@ class DulwichClientTestBase:
                 dest.refs.set_if_equals(r[0], None, r[1])
             self.assertDestEqualsSrc()
 
+    def test_get_refs_with_peeled_tag(self):
+        tag_create(
+            os.path.join(self.gitroot, "server_new.export"),
+            b"v1.0",
+            message="tagging".encode("ascii"),
+            annotated=True,
+        )
+        c = self._client()
+        refs = c.get_refs(self._build_path("/server_new.export"))
+        self.assertEqual(
+            [
+                b"HEAD",
+                b"refs/heads/branch",
+                b"refs/heads/master",
+                b"refs/tags/v1.0",
+                b"refs/tags/v1.0^{}",
+            ],
+            sorted(refs.keys()),
+        )
+
     def test_fetch_pack_depth(self):
         c = self._client()
         with repo.Repo(os.path.join(self.gitroot, "dest")) as dest: