commit 013c16720913591801f3d39843d1d94900de854a from: Jelmer Vernooij date: Fri May 27 19:42:04 2022 UTC Some refactoring. commit - 4c51d513b0fc38a9918844f3875a0c01be2a6574 commit + 013c16720913591801f3d39843d1d94900de854a blob - 9120e51f673806fb2e2463068b7762ae3c89840e blob + 33742b0dcc180037ff9545e2be5a2515192e1546 --- dulwich/client.py +++ dulwich/client.py @@ -501,8 +501,131 @@ def _read_side_band64k_data(pkt_seq, channel_callbacks else: if cb is not None: cb(pkt) + + +def _handle_upload_pack_head( + proto, capabilities, graph_walker, wants, can_read, depth +): + """Handle the head of a 'git-upload-pack' request. + + Args: + proto: Protocol object to read from + capabilities: List of negotiated capabilities + graph_walker: GraphWalker instance to call .ack() on + wants: List of commits to fetch + can_read: function that returns a boolean that indicates + whether there is extra graph data to read on proto + depth: Depth for request + + Returns: + + """ + assert isinstance(wants, list) and isinstance(wants[0], bytes) + proto.write_pkt_line( + COMMAND_WANT + + b" " + + wants[0] + + b" " + + b" ".join(sorted(capabilities)) + + b"\n" + ) + for want in wants[1:]: + proto.write_pkt_line(COMMAND_WANT + b" " + want + b"\n") + if depth not in (0, None) or getattr(graph_walker, "shallow", None): + if CAPABILITY_SHALLOW not in capabilities: + raise GitProtocolError( + "server does not support shallow capability required for " "depth" + ) + for sha in graph_walker.shallow: + proto.write_pkt_line(COMMAND_SHALLOW + b" " + sha + b"\n") + if depth is not None: + proto.write_pkt_line( + COMMAND_DEEPEN + b" " + str(depth).encode("ascii") + b"\n" + ) + proto.write_pkt_line(None) + if can_read is not None: + (new_shallow, new_unshallow) = _read_shallow_updates(proto.read_pkt_seq()) + else: + new_shallow = new_unshallow = None + else: + new_shallow = new_unshallow = set() + proto.write_pkt_line(None) + have = next(graph_walker) + while have: + proto.write_pkt_line(COMMAND_HAVE + b" " + have + b"\n") + if can_read is not None and can_read(): + pkt = proto.read_pkt_line() + parts = pkt.rstrip(b"\n").split(b" ") + if parts[0] == b"ACK": + graph_walker.ack(parts[1]) + if parts[2] in (b"continue", b"common"): + pass + elif parts[2] == b"ready": + break + else: + raise AssertionError( + "%s not in ('continue', 'ready', 'common)" % parts[2] + ) + have = next(graph_walker) + proto.write_pkt_line(COMMAND_DONE + b"\n") + return (new_shallow, new_unshallow) +def _handle_upload_pack_tail( + proto, + capabilities, + graph_walker, + pack_data, + progress=None, + rbufsize=_RBUFSIZE, +): + """Handle the tail of a 'git-upload-pack' request. + + Args: + proto: Protocol object to read from + capabilities: List of negotiated capabilities + graph_walker: GraphWalker instance to call .ack() on + pack_data: Function to call with pack data + progress: Optional progress reporting function + rbufsize: Read buffer size + + Returns: + + """ + pkt = proto.read_pkt_line() + while pkt: + parts = pkt.rstrip(b"\n").split(b" ") + if parts[0] == b"ACK": + graph_walker.ack(parts[1]) + if len(parts) < 3 or parts[2] not in ( + b"ready", + b"continue", + b"common", + ): + break + pkt = proto.read_pkt_line() + if CAPABILITY_SIDE_BAND_64K in capabilities: + if progress is None: + # Just ignore progress data + + def progress(x): + pass + + _read_side_band64k_data( + proto.read_pkt_seq(), + { + SIDE_BAND_CHANNEL_DATA: pack_data, + SIDE_BAND_CHANNEL_PROGRESS: progress, + }, + ) + else: + while True: + data = proto.read(rbufsize) + if data == b"": + break + pack_data(data) + + # TODO(durin42): this doesn't correctly degrade if the server doesn't # support some capabilities. This should work properly with servers # that don't support multi_ack. @@ -824,130 +947,8 @@ class GitClient(object): negotiated_capabilities = self._fetch_capabilities & server_capabilities return (negotiated_capabilities, symrefs, agent) - - def _handle_upload_pack_head( - self, proto, capabilities, graph_walker, wants, can_read, depth - ): - """Handle the head of a 'git-upload-pack' request. - - Args: - proto: Protocol object to read from - capabilities: List of negotiated capabilities - graph_walker: GraphWalker instance to call .ack() on - wants: List of commits to fetch - can_read: function that returns a boolean that indicates - whether there is extra graph data to read on proto - depth: Depth for request - Returns: - """ - assert isinstance(wants, list) and isinstance(wants[0], bytes) - proto.write_pkt_line( - COMMAND_WANT - + b" " - + wants[0] - + b" " - + b" ".join(sorted(capabilities)) - + b"\n" - ) - for want in wants[1:]: - proto.write_pkt_line(COMMAND_WANT + b" " + want + b"\n") - if depth not in (0, None) or getattr(graph_walker, "shallow", None): - if CAPABILITY_SHALLOW not in capabilities: - raise GitProtocolError( - "server does not support shallow capability required for " "depth" - ) - for sha in graph_walker.shallow: - proto.write_pkt_line(COMMAND_SHALLOW + b" " + sha + b"\n") - if depth is not None: - proto.write_pkt_line( - COMMAND_DEEPEN + b" " + str(depth).encode("ascii") + b"\n" - ) - proto.write_pkt_line(None) - if can_read is not None: - (new_shallow, new_unshallow) = _read_shallow_updates(proto.read_pkt_seq()) - else: - new_shallow = new_unshallow = None - else: - new_shallow = new_unshallow = set() - proto.write_pkt_line(None) - have = next(graph_walker) - while have: - proto.write_pkt_line(COMMAND_HAVE + b" " + have + b"\n") - if can_read is not None and can_read(): - pkt = proto.read_pkt_line() - parts = pkt.rstrip(b"\n").split(b" ") - if parts[0] == b"ACK": - graph_walker.ack(parts[1]) - if parts[2] in (b"continue", b"common"): - pass - elif parts[2] == b"ready": - break - else: - raise AssertionError( - "%s not in ('continue', 'ready', 'common)" % parts[2] - ) - have = next(graph_walker) - proto.write_pkt_line(COMMAND_DONE + b"\n") - return (new_shallow, new_unshallow) - - def _handle_upload_pack_tail( - self, - proto, - capabilities, - graph_walker, - pack_data, - progress=None, - rbufsize=_RBUFSIZE, - ): - """Handle the tail of a 'git-upload-pack' request. - - Args: - proto: Protocol object to read from - capabilities: List of negotiated capabilities - graph_walker: GraphWalker instance to call .ack() on - pack_data: Function to call with pack data - progress: Optional progress reporting function - rbufsize: Read buffer size - - Returns: - - """ - pkt = proto.read_pkt_line() - while pkt: - parts = pkt.rstrip(b"\n").split(b" ") - if parts[0] == b"ACK": - graph_walker.ack(parts[1]) - if len(parts) < 3 or parts[2] not in ( - b"ready", - b"continue", - b"common", - ): - break - pkt = proto.read_pkt_line() - if CAPABILITY_SIDE_BAND_64K in capabilities: - if progress is None: - # Just ignore progress data - - def progress(x): - pass - - _read_side_band64k_data( - proto.read_pkt_seq(), - { - SIDE_BAND_CHANNEL_DATA: pack_data, - SIDE_BAND_CHANNEL_PROGRESS: progress, - }, - ) - else: - while True: - data = proto.read(rbufsize) - if data == b"": - break - pack_data(data) - - def check_wants(wants, refs): """Check that a set of wants is valid. @@ -1141,7 +1142,7 @@ class TraditionalGitClient(GitClient): if not wants: proto.write_pkt_line(None) return FetchPackResult(refs, symrefs, agent) - (new_shallow, new_unshallow) = self._handle_upload_pack_head( + (new_shallow, new_unshallow) = _handle_upload_pack_head( proto, negotiated_capabilities, graph_walker, @@ -1149,7 +1150,7 @@ class TraditionalGitClient(GitClient): can_read, depth=depth, ) - self._handle_upload_pack_tail( + _handle_upload_pack_tail( proto, negotiated_capabilities, graph_walker, @@ -2092,7 +2093,7 @@ class AbstractHttpGitClient(GitClient): raise NotImplementedError(self.fetch_pack) req_data = BytesIO() req_proto = Protocol(None, req_data.write) - (new_shallow, new_unshallow) = self._handle_upload_pack_head( + (new_shallow, new_unshallow) = _handle_upload_pack_head( req_proto, negotiated_capabilities, graph_walker, @@ -2106,8 +2107,9 @@ class AbstractHttpGitClient(GitClient): try: resp_proto = Protocol(read, None) if new_shallow is None and new_unshallow is None: - (new_shallow, new_unshallow) = _read_shallow_updates(resp_proto.read_pkt_seq()) - self._handle_upload_pack_tail( + (new_shallow, new_unshallow) = _read_shallow_updates( + resp_proto.read_pkt_seq()) + _handle_upload_pack_tail( resp_proto, negotiated_capabilities, graph_walker,