فهرست منبع

Merge upstream

John Carr 16 سال پیش
والد
کامیت
7498e05d8d
5فایلهای تغییر یافته به همراه44 افزوده شده و 47 حذف شده
  1. 1 1
      bin/dul-daemon
  2. 5 13
      dulwich/client.py
  3. 22 9
      dulwich/pack.py
  4. 8 0
      dulwich/protocol.py
  5. 8 24
      dulwich/server.py

+ 1 - 1
bin/dul-daemon

@@ -25,5 +25,5 @@ if __name__ == "__main__":
         gitdir = sys.argv[1]
 
     backend = GitBackend(gitdir)
-    server = TCPGitServer(backend, ('localhost', 9418))
+    server = TCPGitServer(backend, 'localhost')
     server.serve_forever()

+ 5 - 13
dulwich/client.py

@@ -18,14 +18,7 @@
 
 import select
 import socket
-from dulwich.protocol import Protocol
-
-def extract_capabilities(text):
-    if not "\0" in text:
-        return text
-    capabilities = text.split("\0")
-    return (capabilities[0], capabilities[1:])
-
+from dulwich.protocol import Protocol, TCP_GIT_PORT, extract_capabilities
 
 class SimpleFetchGraphWalker(object):
 
@@ -37,10 +30,9 @@ class SimpleFetchGraphWalker(object):
     def ack(self, ref):
         if ref in self.heads:
             self.heads.remove(ref)
-        if not ref in self.parents:
-            return
-        for p in self.parents[ref]:
-            self.ack(p)
+        if ref in self.parents:
+            for p in self.parents[ref]:
+                self.ack(p)
 
     def next(self):
         if self.heads:
@@ -145,7 +137,7 @@ class GitClient(object):
 
 class TCPGitClient(GitClient):
 
-    def __init__(self, host, port=9418):
+    def __init__(self, host, port=TCP_GIT_PORT):
         self._socket = socket.socket()
         self._socket.connect((host, port))
         self.rfile = self._socket.makefile('rb', -1)

+ 22 - 9
dulwich/pack.py

@@ -152,7 +152,7 @@ def resolve_object(offset, type, obj, get_ref, get_offset):
      (basename, delta) = obj
      assert isinstance(basename, str) and len(basename) == 20
      assert isinstance(delta, str)
-     type, base_obj= get_ref(basename)
+     type, base_obj = get_ref(basename)
      assert isinstance(type, int)
   type, base_text = resolve_object(offset, type, base_obj, get_ref, get_offset)
   return type, apply_delta(base_text, delta)
@@ -403,22 +403,35 @@ class PackData(object):
 
   def iterentries(self):
     found = {}
-    postponed = list(self.iterobjects())
-    while postponed:
-      (offset, type, obj) = postponed.pop(0)
+    at = {}
+    postponed = defaultdict(list)
+    class Postpone(Exception):
+        """Raised to postpone delta resolving."""
+        
+    def get_ref_text(sha):
+        if sha in found:
+            return found[sha]
+        raise Postpone, (sha, )
+    todo = list(self.iterobjects())
+    while todo:
+      (offset, type, obj) = todo.pop(0)
+      at[offset] = (type, obj)
       assert isinstance(offset, int)
       assert isinstance(type, int)
       assert isinstance(obj, tuple) or isinstance(obj, str)
       try:
-        type, obj = resolve_object(offset, type, obj, found.__getitem__, 
-            self.get_object_at)
-      except KeyError:
-        postponed.append((offset, type, obj))
+        type, obj = resolve_object(offset, type, obj, get_ref_text,
+            at.__getitem__)
+      except Postpone, (sha, ):
+        postponed[sha].append((offset, type, obj))
       else:
         shafile = ShaFile.from_raw_string(type, obj)
         sha = shafile.sha().digest()
         found[sha] = (type, obj)
         yield sha, offset, shafile.crc32()
+        todo += postponed.get(sha, [])
+    if postponed:
+        raise KeyError([sha_to_hex(h) for h in postponed.keys()])
 
   def sorted_entries(self):
     ret = list(self.iterentries())
@@ -683,7 +696,7 @@ def write_pack_index_v2(filename, entries, pack_checksum):
     for (name, offset, entry_checksum) in entries:
         f.write(name)
     for (name, offset, entry_checksum) in entries:
-        f.write(struct.pack(">L", entry_checksum))
+        f.write(struct.pack(">l", entry_checksum))
     for (name, offset, entry_checksum) in entries:
         # FIXME: handle if MSBit is set in offset
         f.write(struct.pack(">L", offset))

+ 8 - 0
dulwich/protocol.py

@@ -1,5 +1,6 @@
 # protocol.py -- Shared parts of the git protocols
 # Copryight (C) 2008 John Carr <john.carr@unrouted.co.uk>
+# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
@@ -16,6 +17,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
+TCP_GIT_PORT = 9418
 
 class Protocol(object):
 
@@ -69,3 +71,9 @@ class Protocol(object):
             blob = blob[65530:]
 
 
+def extract_capabilities(text):
+    if not "\0" in text:
+        return text
+    capabilities = text.split("\0")
+    return (capabilities[0], capabilities[1:])
+

+ 8 - 24
dulwich/server.py

@@ -17,7 +17,10 @@
 # MA  02110-1301, USA.
 
 import SocketServer
-from dulwich.protocol import Protocol
+from dulwich.protocol import Protocol, TCP_GIT_PORT
+from dulwich.repo import Repo
+from dulwich.pack import PackData, Pack, write_pack_data, extract_capabilities
+import os, sha, tempfile
 
 class Backend(object):
 
@@ -56,10 +59,6 @@ class Backend(object):
         """
         raise NotImplementedError
 
-from dulwich.repo import Repo
-from dulwich.pack import PackData, Pack
-import sha, tempfile, os
-from dulwich.pack import write_pack_data
 
 class GitBackend(Backend):
 
@@ -155,21 +154,6 @@ class Handler(object):
     def capabilities(self):
         return " ".join(self.default_capabilities())
 
-    def handshake(self, blob):
-        """
-        Compare remote capabilites with our own and alter protocol accordingly
-
-        :param blob: space seperated list of capabilities (i.e. wire format)
-        """
-        if not "\x00" in blob:
-            return blob
-        blob, caps = blob.split("\x00")
-
-        # FIXME: Do something with this..
-        caps = caps.split()
-
-        return blob
-
 
 class UploadPackHandler(Handler):
 
@@ -194,7 +178,7 @@ class UploadPackHandler(Handler):
         if want == None:
             return
 
-        want = self.handshake(want)
+        want, client_capabilities = extract_capabilities(want)
 
         # Keep reading the list of demands until we hit another "0000" 
         want_revs = []
@@ -211,7 +195,7 @@ class UploadPackHandler(Handler):
         have_revs = []
         have = self.proto.read_pkt_line()
         while have and have[:4] == 'have':
-            have_ref = have[6:46]
+            have_ref = have[5:45]
             if self.backend.has_revision(have_ref):
                 self.proto.write_pkt_line("ACK %s continue\n" % have_ref)
                 last_sha = have_ref
@@ -259,7 +243,7 @@ class ReceivePackHandler(Handler):
         if ref is None:
             return
 
-        ref = self.handshake(ref)
+        ref, client_capabilities = extract_capabilities(ref)
 
         # client will now send us a list of (oldsha, newsha, ref)
         while ref:
@@ -309,7 +293,7 @@ class TCPGitServer(SocketServer.TCPServer):
     allow_reuse_address = True
     serve = SocketServer.TCPServer.serve_forever
 
-    def __init__(self, backend, addr):
+    def __init__(self, backend, listen_addr, port=TCP_GIT_PORT):
         self.backend = backend
         SocketServer.TCPServer.__init__(self, addr, TCPGitRequestHandler)