Jelmer Vernooij 16 лет назад
Родитель
Сommit
7568783174
5 измененных файлов с 72 добавлено и 42 удалено
  1. 1 0
      bin/dul-daemon
  2. 11 9
      dulwich/client.py
  3. 41 1
      dulwich/protocol.py
  4. 16 29
      dulwich/server.py
  5. 3 3
      dulwich/tests/test_pack.py

+ 1 - 0
bin/dul-daemon

@@ -17,6 +17,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
+import sys
 from dulwich.server import GitBackend, TCPGitServer
 
 if __name__ == "__main__":

+ 11 - 9
dulwich/client.py

@@ -49,13 +49,9 @@ class GitClient(object):
 
     """
 
-    def __init__(self, fileno, read, write, host):
+    def __init__(self, fileno, read, write):
         self.proto = Protocol(read, write)
         self.fileno = fileno
-        self.host = host
-
-    def send_cmd(self, name, *args):
-        self.proto.write_pkt_line("%s %s" % (name, "".join(["%s\0" % a for a in args])))
 
     def capabilities(self):
         return "multi_ack side-band-64k thin-pack ofs-delta"
@@ -73,7 +69,6 @@ class GitClient(object):
         return refs, server_capabilities
 
     def send_pack(self, path):
-        self.send_cmd("git-receive-pack", path, "host=%s" % self.host)
         refs, server_capabilities = self.read_refs()
         changed_refs = [] # FIXME
         if not changed_refs:
@@ -93,8 +88,6 @@ class GitClient(object):
         :param pack_data: Callback called for each bit of data in the pack
         :param progress: Callback for progress reports (strings)
         """
-        self.send_cmd("git-upload-pack", path, "host=%s" % self.host)
-
         (refs, server_capabilities) = self.read_refs()
        
         wants = determine_wants(refs)
@@ -142,4 +135,13 @@ class TCPGitClient(GitClient):
         self._socket.connect((host, port))
         self.rfile = self._socket.makefile('rb', -1)
         self.wfile = self._socket.makefile('wb', 0)
-        super(TCPGitClient, self).__init__(self._socket.fileno(), self.rfile.read, self.wfile.write, host)
+        self.host = host
+        super(TCPGitClient, self).__init__(self._socket.fileno(), self.rfile.read, self.wfile.write)
+
+    def send_pack(self, path):
+        self.proto.send_cmd("git-receive-pack", path, "host=%s" % self.host)
+        super(TCPGitClient, self).send_pack(path)
+
+    def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
+        self.proto.send_cmd("git-upload-pack", path, "host=%s" % self.host)
+        super(TCPGitClient, self).fetch_pack(path, determine_wants, graph_walker, pack_data, progress)

+ 41 - 1
dulwich/protocol.py

@@ -19,6 +19,22 @@
 
 TCP_GIT_PORT = 9418
 
+class ProtocolFile(object):
+    """
+    Some network ops are like file ops. The file ops expect to operate on
+    file objects, so provide them with a dummy file.
+    """
+
+    def __init__(self, read, write):
+        self.read = read
+        self.write = write
+
+    def tell(self):
+        pass
+
+    def close(self):
+        pass
+
 class Protocol(object):
 
     def __init__(self, read, write):
@@ -70,10 +86,34 @@ class Protocol(object):
             self.write_pkt_line("%s%s" % (chr(channel), blob[:65530]))
             blob = blob[65530:]
 
+    def send_cmd(self, cmd, *args):
+        """
+        Send a command and some arguments to a git server
+
+        Only used for git://
+
+        :param cmd: The remote service to access
+        :param args: List of arguments to send to remove service
+        """
+        self.proto.write_pkt_line("%s %s" % (name, "".join(["%s\0" % a for a in args])))
+
+    def read_cmd(self):
+        """
+        Read a command and some arguments from the git client
+
+        Only used for git://
+
+        :return: A tuple of (command, [list of arguments])
+        """
+        line = self.read_pkt_line()
+        splice_at = line.find(" ")
+        cmd, args = line[:splice_at], line[splice_at+1:]
+        return cmd, args.split(chr(0))
+ 
 
 def extract_capabilities(text):
     if not "\0" in text:
-        return text
+        return text, None
     capabilities = text.split("\0")
     return (capabilities[0], capabilities[1:])
 

+ 16 - 29
dulwich/server.py

@@ -17,7 +17,7 @@
 # MA  02110-1301, USA.
 
 import SocketServer
-from dulwich.protocol import Protocol, TCP_GIT_PORT, extract_capabilities
+from dulwich.protocol import Protocol, ProtocolFile, TCP_GIT_PORT, extract_capabilities
 from dulwich.repo import Repo
 from dulwich.pack import PackData, Pack, write_pack_data
 import os, sha, tempfile
@@ -84,7 +84,7 @@ class GitBackend(Backend):
 
     def apply_pack(self, refs, read):
         # store the incoming pack in the repository
-        fd, name = tempfile.mkstemp(suffix='.pack', prefix='', dir=self.repo.pack_dir())
+        fd, name = tempfile.mkstemp(suffix='.pack', prefix='pack-', dir=self.repo.pack_dir())
         os.write(fd, read())
         os.close(fd)
 
@@ -113,10 +113,10 @@ class GitBackend(Backend):
             if sha in sha_queue:
                 continue
 
-            sha_queue.append((1,sha))
+            sha_queue.append(sha)
 
             c = self.repo.commit(sha)
-            for p in c.parents():
+            for p in c.parents:
                 if not p in commits_to_send:
                     commits_to_send.append(p)
 
@@ -124,23 +124,23 @@ class GitBackend(Backend):
                 for mode, name, x in tree.entries():
                     if not x in sha_queue:
                         try:
-                            t = self.repo.get_tree(x)
-                            sha_queue.append((2, x))
+                            t = self.repo.tree(x)
+                            sha_queue.append(x)
                             parse_tree(t, sha_queue)
                         except:
-                            sha_queue.append((3, x))
+                            sha_queue.append(x)
 
-            treesha = c.tree()
+            treesha = c.tree
             if treesha not in sha_queue:
-                sha_queue.append((2, treesha))
-                t = self.repo.get_tree(treesha)
+                sha_queue.append(treesha)
+                t = self.repo.tree(treesha)
                 parse_tree(t, sha_queue)
 
             progress("counting objects: %d\r" % len(sha_queue))
 
         progress("counting objects: %d, done.\n" % len(sha_queue))
 
-        write_pack_data(write, (self.repo.get_object(sha).as_raw_string() for sha in sha_queue))
+        write_pack_data(ProtocolFile(None, write), (self.repo.get_object(sha) for sha in sha_queue), len(sha_queue))
 
         progress("how was that, then?\n")
 
@@ -257,24 +257,11 @@ class ReceivePackHandler(Handler):
         # there is NO ack from the server before it reports victory.
 
 
-class TCPGitRequestHandler(SocketServer.StreamRequestHandler, Handler):
-
-    def __init__(self, request, client_address, server):
-        SocketServer.StreamRequestHandler.__init__(self, request, client_address, server)
+class TCPGitRequestHandler(SocketServer.StreamRequestHandler):
 
     def handle(self):
-        #FIXME: StreamRequestHandler seems to be the thing that calls handle(),
-        #so we can't call this in a sane place??
-        Handler.__init__(self, self.server.backend, self.rfile.read, self.wfile.write)
-
-        request = self.proto.read_pkt_line()
-
-        # up until the space is the command to run, everything after is parameters
-        splice_point = request.find(' ')
-        command, params = request[:splice_point], request[splice_point+1:]
-
-        # params are null seperated
-        params = params.split(chr(0))
+        proto = Protocol(self.rfile.read, self.wfile.write)
+        command, args = proto.read_cmd()
 
         # switch case to handle the specific git command
         if command == 'git-upload-pack':
@@ -284,7 +271,7 @@ class TCPGitRequestHandler(SocketServer.StreamRequestHandler, Handler):
         else:
             return
 
-        h = cls(self.backend, self.proto.read, self.proto.write)
+        h = cls(self.server.backend, self.rfile.read, self.wfile.write)
         h.handle()
 
 
@@ -295,6 +282,6 @@ class TCPGitServer(SocketServer.TCPServer):
 
     def __init__(self, backend, listen_addr, port=TCP_GIT_PORT):
         self.backend = backend
-        SocketServer.TCPServer.__init__(self, addr, TCPGitRequestHandler)
+        SocketServer.TCPServer.__init__(self, (listen_addr, port), TCPGitRequestHandler)
 
 

+ 3 - 3
dulwich/tests/test_pack.py

@@ -185,7 +185,7 @@ class TestHexToSha(unittest.TestCase):
         self.assertEquals("abcdef", sha_to_hex('\xab\xcd\xef'))
 
 
-class TestPackIndexWriting(object):
+class BaseTestPackIndexWriting(object):
 
     def test_empty(self):
         pack_checksum = 'r\x19\x80\xe8f\xaf\x9a_\x93\xadgAD\xe1E\x9b\x8b\xa3\xe7\xb7'
@@ -216,7 +216,7 @@ class TestPackIndexWriting(object):
                 self.assertTrue(b[2] is None)
 
 
-class TestPackIndexWritingv1(unittest.TestCase, TestPackIndexWriting):
+class TestPackIndexWritingv1(unittest.TestCase, BaseTestPackIndexWriting):
 
     def setUp(self):
         unittest.TestCase.setUp(self)
@@ -225,7 +225,7 @@ class TestPackIndexWritingv1(unittest.TestCase, TestPackIndexWriting):
         self._write_fn = write_pack_index_v1
 
 
-class TestPackIndexWritingv2(unittest.TestCase, TestPackIndexWriting):
+class TestPackIndexWritingv2(unittest.TestCase, BaseTestPackIndexWriting):
 
     def setUp(self):
         unittest.TestCase.setUp(self)