Add check_wants.
authorJelmer Vernooij <jelmer@jelmer.uk>
Tue, 11 Sep 2018 22:43:23 +0000 (23:43 +0100)
committerJelmer Vernooij <jelmer@jelmer.uk>
Tue, 11 Sep 2018 22:43:23 +0000 (23:43 +0100)
dulwich/client.py
dulwich/tests/test_client.py

index 9b9eb73513d980978714cbd0c40be6d63238dd10..efdc62fe9b82629dd6c9fd7a4644c9e238e56efe 100644 (file)
@@ -103,9 +103,19 @@ from dulwich.pack import (
     )
 from dulwich.refs import (
     read_info_refs,
+    ANNOTATED_TAG_SUFFIX,
     )
 
 
+class InvalidWants(Exception):
+    """Invalid wants."""
+
+    def __init__(self, wants):
+        Exception.__init__(
+            self,
+            "requested wants not in server provided refs: %r" % wants)
+
+
 def _fileno_can_read(fileno):
     """Check if a file descriptor is readable."""
     return len(select.select([fileno], [], [], 0)[0]) > 0
@@ -613,6 +623,19 @@ class GitClient(object):
                 pack_data(data)
 
 
+def check_wants(wants, refs):
+    """Check that a set of wants is valid.
+
+    :param wants: Set of object SHAs to fetch
+    :param refs: Refs dictionary to check against
+    """
+    missing = set(wants) - {
+            v for (k, v) in refs.items()
+            if not k.endswith(ANNOTATED_TAG_SUFFIX)}
+    if missing:
+        raise InvalidWants(missing)
+
+
 class TraditionalGitClient(GitClient):
     """Traditional Git client."""
 
index 8decf2486b67e5008b444970268277ba229632d3..56c3ff5f8693fbf306982c9437a6694a77a8a0b3 100644 (file)
@@ -42,6 +42,7 @@ from dulwich import (
     client,
     )
 from dulwich.client import (
+    InvalidWants,
     LocalGitClient,
     TraditionalGitClient,
     TCPGitClient,
@@ -53,6 +54,7 @@ from dulwich.client import (
     SubprocessSSHVendor,
     PLinkSSHVendor,
     UpdateRefsError,
+    check_wants,
     default_urllib3_manager,
     get_transport_and_path,
     get_transport_and_path_from_url,
@@ -1178,3 +1180,21 @@ class RsyncUrlTests(TestCase):
 
     def test_path(self):
         self.assertRaises(ValueError, parse_rsync_url, '/path')
+
+
+class CheckWantsTests(TestCase):
+
+    def test_fine(self):
+        check_wants(['2f3dc7a53fb752a6961d3a56683df46d4d3bf262'],
+                    {'refs/heads/blah': '2f3dc7a53fb752a6961d3a56683df46d4d3bf262'})
+
+    def test_missing(self):
+        self.assertRaises(InvalidWants, check_wants,
+                ['2f3dc7a53fb752a6961d3a56683df46d4d3bf262'],
+                {'refs/heads/blah': '3f3dc7a53fb752a6961d3a56683df46d4d3bf262'})
+
+    def test_annotated(self):
+        self.assertRaises(InvalidWants, check_wants,
+                ['2f3dc7a53fb752a6961d3a56683df46d4d3bf262'],
+                {'refs/heads/blah': '3f3dc7a53fb752a6961d3a56683df46d4d3bf262',
+                 'refs/heads/blah^{}': '2f3dc7a53fb752a6961d3a56683df46d4d3bf262'})