From d0f921ed636cda6a5e9bc9b705716253b14e81dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jelmer=20Vernoo=C4=B3?= Date: Wed, 14 Nov 2018 02:35:25 +0000 Subject: [PATCH] Add basic server side implementation of 'git-upload-archive'. --- NEWS | 3 +++ dulwich/server.py | 39 +++++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index b4faf679c..2a316f654 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ * Preserve port and username in parsed HTTP URLs. (Jelmer Vernooij) + * Add basic server side implementation of ``git-upload-archivw``. + (Jelmer Vernooij) + 0.19.7 2018-11-05 CHANGES diff --git a/dulwich/server.py b/dulwich/server.py index 6b77575e9..9d3b3b3f4 100644 --- a/dulwich/server.py +++ b/dulwich/server.py @@ -46,6 +46,7 @@ import os import socket import sys +import time import zlib try: @@ -53,6 +54,7 @@ except ImportError: import socketserver as SocketServer +from dulwich.archive import tar_stream from dulwich.errors import ( ApplyDeltaError, ChecksumMismatch, @@ -1003,19 +1005,48 @@ def handle(self): class UploadArchiveHandler(Handler): - def __init__(self, backend, proto, http_req=None): + def __init__(self, backend, args, proto, http_req=None): super(UploadArchiveHandler, self).__init__(backend, proto, http_req) + self.repo = backend.open_repository(args[0]) def handle(self): - # TODO(jelmer) - raise NotImplementedError(self.handle) + def write(x): + return self.proto.write_sideband(SIDE_BAND_CHANNEL_DATA, x) + arguments = [] + for pkt in self.proto.read_pkt_seq(): + (key, value) = pkt.split(b' ', 1) + if key != b'argument': + raise GitProtocolError('unknown command %s' % key) + arguments.append(value.rstrip(b'\n')) + prefix = b'' + format = 'tar' + i = 0 + store = self.repo.object_store + while i < len(arguments): + argument = arguments[i] + if argument == b'--prefix': + i += 1 + prefix = arguments[i] + elif argument == b'--format': + i += 1 + format = arguments[i].decode('ascii') + else: + commit_sha = self.repo.refs[argument] + tree = store[store[commit_sha].tree] + i += 1 + self.proto.write_pkt_line(b'ACK\n') + self.proto.write_pkt_line(None) + for chunk in tar_stream( + store, tree, mtime=time.time(), prefix=prefix, format=format): + write(chunk) + self.proto.write_pkt_line(None) # Default handler classes for git services. DEFAULT_HANDLERS = { b'git-upload-pack': UploadPackHandler, b'git-receive-pack': ReceivePackHandler, - # b'git-upload-archive': UploadArchiveHandler, + b'git-upload-archive': UploadArchiveHandler, }