瀏覽代碼

Merge John.

Jelmer Vernooij 16 年之前
父節點
當前提交
7483f5db10
共有 7 個文件被更改,包括 313 次插入227 次删除
  1. 1 108
      bin/dul-daemon
  2. 34 0
      bin/dul-receive-pack
  3. 34 0
      bin/dul-upload-pack
  4. 34 0
      docs/protocol.txt
  5. 18 50
      dulwich/client.py
  6. 71 0
      dulwich/protocol.py
  7. 121 69
      dulwich/server.py

+ 1 - 108
bin/dul-daemon

@@ -17,114 +17,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 # MA  02110-1301, USA.
 
-import os, sys, tempfile, struct
-from dulwich.server import Backend, TCPGitServer
-from dulwich.repo import Repo
-from dulwich.pack import PackData, Pack, write_pack_data
-
-import sha
-
-class PackWriteWrapper(object):
-
-    def __init__(self, write):
-        self.writefn = write
-        self.sha = sha.sha()
-
-    def write(self, blob):
-        self.sha.update(blob)
-        self.writefn(blob)
-
-    def tell(self):
-        pass
-
-    @property
-    def digest(self):
-        return self.sha.digest()
-
-class GitBackend(Backend):
-
-    def __init__(self, gitdir=None):
-        self.gitdir = gitdir
-
-        if not self.gitdir:
-            self.gitdir = tempfile.mkdtemp()
-            Repo.create(self.gitdir)
-
-        self.repo = Repo(self.gitdir)
-
-    def get_refs(self):
-        refs = []
-        if self.repo.head():
-            refs.append(('HEAD', self.repo.head()))
-        for ref, sha in self.repo.heads().items():
-            refs.append(('refs/heads/'+ref,sha))
-        return refs
-
-    def has_revision(self, sha):
-        return self.repo.get_object(sha) != None
-
-    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())
-        os.write(fd, read())
-        os.close(fd)
-
-        # strip '.pack' off our filename
-        basename = name[:-5]
-
-        # generate an index for it
-        pd = PackData(name)
-        pd.create_index_v2(basename+".idx")
-
-        for oldsha, sha, ref in refs:
-            if ref == "0" * 40:
-                self.repo.remove_ref(ref)
-            else:
-                self.repo.set_ref(ref, sha)
-
-        print "pack applied"
-
-    def generate_pack(self, want, have, write, progress):
-        progress("dul-daemon says what\n")
-
-        sha_queue = []
-
-        commits_to_send = want[:]
-        for sha in commits_to_send:
-            if sha in sha_queue:
-                continue
-
-            sha_queue.append((1,sha))
-
-            c = self.repo.commit(sha)
-            for p in c.parents():
-                if not p in commits_to_send:
-                    commits_to_send.append(p)
-
-            def parse_tree(tree, sha_queue):
-                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))
-                            parse_tree(t, sha_queue)
-                        except:
-                            sha_queue.append((3, x))
-
-            treesha = c.tree()
-            if treesha not in sha_queue:
-                sha_queue.append((2, treesha))
-                t = self.repo.get_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))
-
-        progress("how was that, then?\n")
-
+from dulwich.server import GitBackend, TCPGitServer
 
 if __name__ == "__main__":
     gitdir = None

+ 34 - 0
bin/dul-receive-pack

@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# dul-receive-pack - git-receive-pack in python
+# Copyright (C) 2008 John Carr <john.carr@unrouted.co.uk>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+import sys
+from dulwich.server import GitBackend, ReceivePackHandler
+
+def send_fn(data):
+    sys.stdout.write(data)
+    sys.stdout.flush()
+
+if __name__ == "__main__":
+    gitdir = None
+    if len(sys.argv) > 1:
+        gitdir = sys.argv[1]
+
+    backend = GitBackend(gitdir)
+    handler = ReceivePackHandler(backend, sys.stdin.read, send_fn)
+    handler.handle()

+ 34 - 0
bin/dul-upload-pack

@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# dul-upload-pack - git-upload-pack in python
+# Copyright (C) 2008 John Carr <john.carr@unrouted.co.uk>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+import sys
+from dulwich.server import GitBackend, UploadPackHandler
+
+def send_fn(data):
+    sys.stdout.write(data)
+    sys.stdout.flush()
+
+if __name__ == "__main__":
+    gitdir = None
+    if len(sys.argv) > 1:
+        gitdir = sys.argv[1]
+
+    backend = GitBackend(gitdir)
+    handler = UploadPackHandler(backend, sys.stdin.read, send_fn)
+    handler.handle()

+ 34 - 0
docs/protocol.txt

@@ -0,0 +1,34 @@
+= Git Server Protocol =
+
+== Transport ==
+The Git protocol operates over pipes or TCP/IP. When a client connects over TCP/IP, it sends a header that tells the server which program to run and what parameters to use. When invoked over SSH, git will run a program with the parameters as command line arguments.
+
+== Protocols ==
+
+=== Basics ====
+
+Git communicates with a server by piping data between a local program and a remote program.
+
+A common way of sending a unit of information is a pkt_line. This is a 4 byte size as human encoded hex (i.e. totally underusing the 4 bytes...) that tells you the size of the payload, followed by the payload. The size includes the 4 byes used by the size itself.
+
+{{{
+0009ABCD\n
+}}}
+
+Git can also multiplex data using the sideband. As well as 4 bytes size, there would be a 1 byte channel number. This is in binary, so 1 will be \x01.
+
+Typically Git will piggyback a list of capabilities on the first pkt_line it sends. It will also look for capabilities in the first pkt_like it receives. Git will degrade as much as possible when encountering a server or client with differing capabilities.
+
+==== git-upload-pack ===
+
+git-upload pack is used by git-ls-remote, git-clone, git-fetch and git-pull. And i'm sure others. Typically a client will connect a local git-fetch-pack to a remote git-upload-pack.
+
+Capabilities for this protocol include multi_ack, thin-pack, ofs-delta, sideband and sideband-64k A thin pack can reference objects not in the current pack.
+
+The server tells the client what refs it has. The client states which of those SHA1's it would like. It then starts to report which SHA1's it has. The server ACKs these allowing the client to work out when to stop sending SHA1's. This saves a lot of transfer because the client can make decisions like "well if it has this SHA, then it has all its parents so i dont need to care about those". When the client stops sending shas, the server can work out an optimal pack and then send it to the client.
+
+==== git-receive-pack ===
+
+git-receive-pack is used by git push. Typically a client connects a local git-send-pack to a remote git-receive-pack.
+
+Capabilities include report-status and delete-ref.

+ 18 - 50
dulwich/client.py

@@ -18,7 +18,7 @@
 
 import select
 import socket
-
+from dulwich.protocol import Protocol
 
 def extract_capabilities(text):
     if not "\0" in text:
@@ -57,44 +57,12 @@ class GitClient(object):
     """
 
     def __init__(self, fileno, read, write, host):
-        self.read = read
-        self.write = write
+        self.proto = Protocol(read, write)
         self.fileno = fileno
         self.host = host
 
-    def read_pkt_line(self):
-        """
-        Reads a 'pkt line' from the remote git process
-
-        :return: The next string from the stream
-        """
-        sizestr = self.read(4)
-        if sizestr == "":
-            raise RuntimeError("Socket broken")
-        size = int(sizestr, 16)
-        if size == 0:
-            return None
-        return self.read(size-4)
-
-    def read_pkt_seq(self):
-        pkt = self.read_pkt_line()
-        while pkt:
-            yield pkt
-            pkt = self.read_pkt_line()
-
-    def write_pkt_line(self, line):
-        """
-        Sends a 'pkt line' to the remote git process
-
-        :param line: A string containing the data to send
-        """
-        if line is None:
-            self.write("0000")
-        else:
-            self.write("%04x%s" % (len(line)+4, line))
-
     def send_cmd(self, name, *args):
-        self.write_pkt_line("%s %s" % (name, "".join(["%s\0" % a for a in 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"
@@ -103,7 +71,7 @@ class GitClient(object):
         server_capabilities = None
         refs = {}
         # Receive refs from server
-        for pkt in self.read_pkt_seq():
+        for pkt in self.proto.read_pkt_seq():
             (sha, ref) = pkt.rstrip("\n").split(" ", 1)
             if server_capabilities is None:
                 (ref, server_capabilities) = extract_capabilities(ref)
@@ -116,12 +84,12 @@ class GitClient(object):
         refs, server_capabilities = self.read_refs()
         changed_refs = [] # FIXME
         if not changed_refs:
-            self.write_pkt_line(None)
+            self.proto.write_pkt_line(None)
             return
-        self.write_pkt_line("%s %s %s\0%s" % (changed_refs[0][0], changed_refs[0][1], changed_refs[0][2], self.capabilities()))
+        self.proto.write_pkt_line("%s %s %s\0%s" % (changed_refs[0][0], changed_refs[0][1], changed_refs[0][2], self.capabilities()))
         for changed_ref in changed_refs[:]:
-            self.write_pkt_line("%s %s %s" % changed_refs)
-        self.write_pkt_line(None)
+            self.proto.write_pkt_line("%s %s %s" % changed_refs)
+        self.proto.write_pkt_line(None)
         # FIXME: Send pack
 
     def fetch_pack(self, path, determine_wants, graph_walker, pack_data, progress):
@@ -138,32 +106,32 @@ class GitClient(object):
        
         wants = determine_wants(refs)
         if not wants:
-            self.write_pkt_line(None)
+            self.proto.write_pkt_line(None)
             return
-        self.write_pkt_line("want %s %s\n" % (wants[0], self.capabilities()))
+        self.proto.write_pkt_line("want %s %s\n" % (wants[0], self.capabilities()))
         for want in wants[1:]:
-            self.write_pkt_line("want %s\n" % want)
-        self.write_pkt_line(None)
+            self.proto.write_pkt_line("want %s\n" % want)
+        self.proto.write_pkt_line(None)
         have = graph_walker.next()
         while have:
-            self.write_pkt_line("have %s\n" % have)
+            self.proto.write_pkt_line("have %s\n" % have)
             if len(select.select([self.fileno], [], [], 0)[0]) > 0:
-                pkt = self.read_pkt_line()
+                pkt = self.proto.read_pkt_line()
                 parts = pkt.rstrip("\n").split(" ")
                 if parts[0] == "ACK":
                     graph_walker.ack(parts[1])
                     assert parts[2] == "continue"
             have = graph_walker.next()
-        self.write_pkt_line("done\n")
-        pkt = self.read_pkt_line()
+        self.proto.write_pkt_line("done\n")
+        pkt = self.proto.read_pkt_line()
         while pkt:
             parts = pkt.rstrip("\n").split(" ")
             if parts[0] == "ACK":
                 graph_walker.ack(pkt.split(" ")[1])
             if len(parts) < 3 or parts[2] != "continue":
                 break
-            pkt = self.read_pkt_line()
-        for pkt in self.read_pkt_seq():
+            pkt = self.proto.read_pkt_line()
+        for pkt in self.proto.read_pkt_seq():
             channel = ord(pkt[0])
             pkt = pkt[1:]
             if channel == 1:

+ 71 - 0
dulwich/protocol.py

@@ -0,0 +1,71 @@
+# protocol.py -- Shared parts of the git protocols
+# Copryight (C) 2008 John Carr <john.carr@unrouted.co.uk>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.
+
+
+class Protocol(object):
+
+    def __init__(self, read, write):
+        self.read = read
+        self.write = write
+
+    def read_pkt_line(self):
+        """
+        Reads a 'pkt line' from the remote git process
+
+        :return: The next string from the stream
+        """
+        sizestr = self.read(4)
+        if not sizestr:
+            return None
+        size = int(sizestr, 16)
+        if size == 0:
+            return None
+        return self.read(size-4)
+
+    def read_pkt_seq(self):
+        pkt = self.read_pkt_line()
+        while pkt:
+            yield pkt
+            pkt = self.read_pkt_line()
+
+    def write_pkt_line(self, line):
+        """
+        Sends a 'pkt line' to the remote git process
+
+        :param line: A string containing the data to send
+        """
+        if line is None:
+            self.write("0000")
+        else:
+            self.write("%04x%s" % (len(line)+4, line))
+
+    def write_sideband(self, channel, blob):
+        """
+        Write data to the sideband (a git multiplexing method)
+
+        :param channel: int specifying which channel to write to
+        :param blob: a blob of data (as a string) to send on this channel
+        """
+        # a pktline can be a max of 65535. a sideband line can therefore be
+        # 65535-5 = 65530
+        # WTF: Why have the len in ASCII, but the channel in binary.
+        while blob:
+            self.write_pkt_line("%s%s" % (chr(channel), blob[:65530]))
+            blob = blob[65530:]
+
+

+ 121 - 69
dulwich/server.py

@@ -17,6 +17,7 @@
 # MA  02110-1301, USA.
 
 import SocketServer
+from dulwich.protocol import Protocol
 
 class Backend(object):
 
@@ -55,53 +56,104 @@ 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 Handler(object):
+class GitBackend(Backend):
 
-    def __init__(self, backend, read, write):
-        self.backend = backend
-        self.read = read
-        self.write = write
+    def __init__(self, gitdir=None):
+        self.gitdir = gitdir
 
-    def read_pkt_line(self):
-        """
-        Reads a 'pkt line' from the remote git process
+        if not self.gitdir:
+            self.gitdir = tempfile.mkdtemp()
+            Repo.create(self.gitdir)
 
-        :return: The next string from the stream
-        """
-        sizestr = self.read(4)
-        if not sizestr:
-            return None
-        size = int(sizestr, 16)
-        if size == 0:
-            return None
-        return self.read(size-4)
-
-    def write_pkt_line(self, line):
-        """
-        Sends a 'pkt line' to the remote git process
+        self.repo = Repo(self.gitdir)
 
-        :param line: A string containing the data to send
-        """
-        self.write("%04x%s" % (len(line)+4, line))
+    def get_refs(self):
+        refs = []
+        if self.repo.head():
+            refs.append(('HEAD', self.repo.head()))
+        for ref, sha in self.repo.heads().items():
+            refs.append(('refs/heads/'+ref,sha))
+        return refs
 
-    def write_sideband(self, channel, blob):
-        """
-        Write data to the sideband (a git multiplexing method)
+    def has_revision(self, sha):
+        return self.repo.get_object(sha) != None
 
-        :param channel: int specifying which channel to write to
-        :param blob: a blob of data (as a string) to send on this channel
-        """
-        # a pktline can be a max of 65535. a sideband line can therefore be
-        # 65535-5 = 65530
-        # WTF: Why have the len in ASCII, but the channel in binary.
-        while blob:
-            self.write_pkt_line("%s%s" % (chr(channel), blob[:65530]))
-            blob = blob[65530:]
+    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())
+        os.write(fd, read())
+        os.close(fd)
+
+        # strip '.pack' off our filename
+        basename = name[:-5]
+
+        # generate an index for it
+        pd = PackData(name)
+        pd.create_index_v2(basename+".idx")
+
+        for oldsha, sha, ref in refs:
+            if ref == "0" * 40:
+                self.repo.remove_ref(ref)
+            else:
+                self.repo.set_ref(ref, sha)
+
+        print "pack applied"
+
+    def generate_pack(self, want, have, write, progress):
+        progress("dul-daemon says what\n")
+
+        sha_queue = []
+
+        commits_to_send = want[:]
+        for sha in commits_to_send:
+            if sha in sha_queue:
+                continue
+
+            sha_queue.append((1,sha))
+
+            c = self.repo.commit(sha)
+            for p in c.parents():
+                if not p in commits_to_send:
+                    commits_to_send.append(p)
+
+            def parse_tree(tree, sha_queue):
+                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))
+                            parse_tree(t, sha_queue)
+                        except:
+                            sha_queue.append((3, x))
+
+            treesha = c.tree()
+            if treesha not in sha_queue:
+                sha_queue.append((2, treesha))
+                t = self.repo.get_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))
+
+        progress("how was that, then?\n")
+
+
+class Handler(object):
+
+    def __init__(self, backend, read, write):
+        self.backend = backend
+        self.proto = Protocol(read, write)
 
     def capabilities(self):
-        # FIXME: Capabilities are different for pushing...
-        return "multi_ack side-band-64k thin-pack ofs-delta"
+        return " ".join(self.default_capabilities())
 
     def handshake(self, blob):
         """
@@ -118,30 +170,27 @@ class Handler(object):
 
         return blob
 
-    def handle(self):
-        """
-        Deal with the request
-        """
-        raise NotImplementedError
-
 
 class UploadPackHandler(Handler):
 
+    def default_capabilities(self):
+        return ("multi_ack", "side-band-64k", "thin-pack", "ofs-delta")
+
     def handle(self):
         refs = self.backend.get_refs()
 
         if refs:
-            self.write_pkt_line("%s %s\x00%s\n" % (refs[0][1], refs[0][0], self.capabilities()))
+            self.proto.write_pkt_line("%s %s\x00%s\n" % (refs[0][1], refs[0][0], self.capabilities()))
             for i in range(1, len(refs)):
                 ref = refs[i]
-                self.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
+                self.proto.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
 
-        # i'm done...
-        self.write("0000")
+        # i'm done..
+        self.proto.write("0000")
 
         # Now client will either send "0000", meaning that it doesnt want to pull.
         # or it will start sending want want want commands
-        want = self.read_pkt_line()
+        want = self.proto.read_pkt_line()
         if want == None:
             return
 
@@ -154,54 +203,57 @@ class UploadPackHandler(Handler):
             # FIXME: This check probably isnt needed?
             if self.backend.has_revision(want_rev):
                want_revs.append(want_rev)
-            want = self.read_pkt_line()
+            want = self.proto.read_pkt_line()
         
         # Client will now tell us which commits it already has - if we have them we ACK them
         # this allows client to stop looking at that commits parents (main reason why git pull is fast)
         last_sha = None
         have_revs = []
-        have = self.read_pkt_line()
+        have = self.proto.read_pkt_line()
         while have and have[:4] == 'have':
             have_ref = have[6:46]
-            if self.backend.has_revision(hav_rev):
-                self.write_pkt_line("ACK %s continue\n" % sha)
-                last_sha = sha
-                have_revs.append(rev_id)
-            have = self.read_pkt_line()
+            if self.backend.has_revision(have_ref):
+                self.proto.write_pkt_line("ACK %s continue\n" % have_ref)
+                last_sha = have_ref
+                have_revs.append(have_ref)
+            have = self.proto.read_pkt_line()
 
         # At some point client will stop sending commits and will tell us it is done
         assert(have[:4] == "done")
 
         # Oddness: Git seems to resend the last ACK, without the "continue" statement
         if last_sha:
-            self.write_pkt_line("ACK %s\n" % last_sha)
+            self.proto.write_pkt_line("ACK %s\n" % last_sha)
 
         # The exchange finishes with a NAK
-        self.write_pkt_line("NAK\n")
+        self.proto.write_pkt_line("NAK\n")
       
-        self.backend.generate_pack(want_revs, have_revs, lambda x: self.write_sideband(1, x), lambda x: self.write_sideband(2, x))
+        self.backend.generate_pack(want_revs, have_revs, lambda x: self.proto.write_sideband(1, x), lambda x: self.proto.write_sideband(2, x))
 
         # we are done
-        self.write("0000")
+        self.proto.write("0000")
 
 
 class ReceivePackHandler(Handler):
 
+    def default_capabilities(self):
+        return ("report-status", "delete-refs")
+
     def handle(self):
         refs = self.backend.get_refs()
 
         if refs:
-            self.write_pkt_line("%s %s\x00%s\n" % (refs[0][1], refs[0][0], self.capabilities()))
+            self.proto.write_pkt_line("%s %s\x00%s\n" % (refs[0][1], refs[0][0], self.capabilities()))
             for i in range(1, len(refs)):
                 ref = refs[i]
-                self.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
+                self.proto.write_pkt_line("%s %s\n" % (ref[1], ref[0]))
         else:
-            self.write_pkt_line("0000000000000000000000000000000000000000 capabilities^{} %s" % self.capabilities())
+            self.proto.write_pkt_line("0000000000000000000000000000000000000000 capabilities^{} %s" % self.capabilities())
 
-        self.write("0000")
+        self.proto.write("0000")
 
         client_refs = []
-        ref = self.read_pkt_line()
+        ref = self.proto.read_pkt_line()
 
         # if ref is none then client doesnt want to send us anything..
         if ref is None:
@@ -212,10 +264,10 @@ class ReceivePackHandler(Handler):
         # client will now send us a list of (oldsha, newsha, ref)
         while ref:
             client_refs.append(ref.split())
-            ref = self.read_pkt_line()
+            ref = self.proto.read_pkt_line()
 
         # backend can now deal with this refs and read a pack using self.read
-        self.backend.apply_pack(client_refs, self.read)
+        self.backend.apply_pack(client_refs, self.proto.read)
 
         # when we have read all the pack from the client, it assumes everything worked OK
         # there is NO ack from the server before it reports victory.
@@ -231,7 +283,7 @@ class TCPGitRequestHandler(SocketServer.StreamRequestHandler, Handler):
         #so we can't call this in a sane place??
         Handler.__init__(self, self.server.backend, self.rfile.read, self.wfile.write)
 
-        request = self.read_pkt_line()
+        request = self.proto.read_pkt_line()
 
         # up until the space is the command to run, everything after is parameters
         splice_point = request.find(' ')
@@ -248,7 +300,7 @@ class TCPGitRequestHandler(SocketServer.StreamRequestHandler, Handler):
         else:
             return
 
-        h = cls(self.backend, self.read, self.write)
+        h = cls(self.backend, self.proto.read, self.proto.write)
         h.handle()