From: Jelmer Vernooij Date: Thu, 25 Dec 2008 13:50:59 +0000 (+0000) Subject: Merge John. X-Git-Tag: dulwich-0.1.0~53 X-Git-Url: http://git.samba.org/samba.git/?p=jelmer%2Fdulwich-libgit2.git;a=commitdiff_plain;h=7568783174b7495a7c57591dd0625a97bb0f2e4c;hp=512275cdf57bda06f729ce6eeef66108e5bd4f06 Merge John. --- diff --git a/bin/dul-daemon b/bin/dul-daemon index 3eea950..a9943b1 100755 --- a/bin/dul-daemon +++ b/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__": diff --git a/dulwich/client.py b/dulwich/client.py index 606db05..3ada929 100644 --- a/dulwich/client.py +++ b/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) diff --git a/dulwich/protocol.py b/dulwich/protocol.py index 715e66a..f37b56c 100644 --- a/dulwich/protocol.py +++ b/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:]) diff --git a/dulwich/server.py b/dulwich/server.py index e3fcd6d..c90f6fa 100644 --- a/dulwich/server.py +++ b/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) diff --git a/dulwich/tests/test_pack.py b/dulwich/tests/test_pack.py index 29f770b..c995422 100644 --- a/dulwich/tests/test_pack.py +++ b/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)