Browse Source

Refactor server capability code into base Handler.

UploadPackHandler and ReceivePackHandler now both handle client
capabilities using a consistent interface, the set_client_capabilites
and has_capability functions. Both now error as soon as an unknown
capability is requested by the client.

Also renames the following methods:
  capabilities -> capability_line
  default_capabilities -> capabilities
This is because capability_line is the less general of the two
methods, as it is only useful when advertising capabilities to the
client.

Changed capabilities tests to use the base class and test new
functionality.

Change-Id: If7d3feeac27834119d6d4e4021569401e5444d51
Dave Borowitz 15 years ago
parent
commit
ef3f2e1a51
2 changed files with 26 additions and 2 deletions
  1. 19 2
      dulwich/server.py
  2. 7 0
      dulwich/tests/test_server.py

+ 19 - 2
dulwich/server.py

@@ -160,6 +160,7 @@ class Handler(object):
     def capabilities(self):
         raise NotImplementedError(self.capabilities)
 
+<<<<<<< HEAD
     def set_client_capabilities(self, caps):
         my_caps = self.capabilities()
         for cap in caps:
@@ -167,6 +168,19 @@ class Handler(object):
                 raise GitProtocolError('Client asked for capability %s that '
                                        'was not advertised.' % cap)
         self._client_capabilities = set(caps)
+=======
+    def innocuous_capabilities(self):
+        return ("include-tag", "thin-pack", "no-progress", "ofs-delta")
+
+    def set_client_capabilities(self, caps):
+        allowable_caps = set(self.innocuous_capabilities())
+        allowable_caps.update(self.capabilities())
+        for cap in caps:
+            if cap not in allowable_caps:
+                raise GitProtocolError('Client asked for capability %s that '
+                                       'was not advertised.' % cap)
+        self._client_capabilities = caps
+>>>>>>> Refactor server capability code into base Handler.
 
     def has_capability(self, cap):
         if self._client_capabilities is None:
@@ -189,11 +203,14 @@ class UploadPackHandler(Handler):
         return ("multi_ack_detailed", "multi_ack", "side-band-64k", "thin-pack",
                 "ofs-delta", "no-progress")
 
+<<<<<<< HEAD
     def progress(self, message):
         if self.has_capability("no-progress"):
             return
         self.proto.write_sideband(2, message)
 
+=======
+>>>>>>> Refactor server capability code into base Handler.
     def handle(self):
         write = lambda x: self.proto.write_sideband(1, x)
 
@@ -521,8 +538,8 @@ class ReceivePackHandler(Handler):
         if self.advertise_refs or not self.stateless_rpc:
             if refs:
                 self.proto.write_pkt_line(
-                    "%s %s\x00%s\n" % (refs[0][1], refs[0][0],
-                                       self.capability_line()))
+                  "%s %s\x00%s\n" % (refs[0][1], refs[0][0],
+                                     self.capability_line()))
                 for i in range(1, len(refs)):
                     ref = refs[i]
                     self.proto.write_pkt_line("%s %s\n" % (ref[1], ref[0]))

+ 7 - 0
dulwich/tests/test_server.py

@@ -93,6 +93,7 @@ class HandlerTestCase(TestCase):
 
     def test_set_client_capabilities(self):
         set_caps = self._handler.set_client_capabilities
+
         self.assertSucceeds(set_caps, [])
         self.assertSucceeds(set_caps, ['cap2'])
         self.assertSucceeds(set_caps, ['cap1', 'cap2'])
@@ -100,6 +101,12 @@ class HandlerTestCase(TestCase):
         self.assertSucceeds(set_caps, ['cap3', 'cap1', 'cap2'])
         self.assertRaises(GitProtocolError, set_caps, ['capxxx', 'cap1'])
 
+        # ignore innocuous but unknown capabilities
+        self.assertRaises(GitProtocolError, set_caps, ['ignoreme'])
+        self.assertFalse('ignoreme' in self._handler.capabilities())
+        self._handler.innocuous_capabilities = lambda: ('ignoreme',)
+        self.assertSucceeds(set_caps, ['ignoreme'])
+
     def test_has_capability(self):
         self.assertRaises(GitProtocolError, self._handler.has_capability, 'cap')
         caps = self._handler.capabilities()