From aa3d986251f75dd6544598beaa506f0d434b164a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 20 Jul 2023 14:35:18 +0530 Subject: [PATCH] Basic rsync transmission works --- kittens/transfer/algorithm.c | 4 +++- kitty/file_transmission.py | 28 +++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/kittens/transfer/algorithm.c b/kittens/transfer/algorithm.c index a8558cb1f..e0ef72a72 100644 --- a/kittens/transfer/algorithm.c +++ b/kittens/transfer/algorithm.c @@ -260,7 +260,7 @@ sign_block(Patcher *self, PyObject *args) { return PyLong_FromSize_t(signature_block_size); } -typedef enum { OpBlock, OpBlockRange, OpHash, OpData } OpType; +typedef enum { OpBlock, OpData, OpHash, OpBlockRange } OpType; typedef struct Operation { OpType type; @@ -268,6 +268,8 @@ typedef struct Operation { struct { uint8_t *buf; size_t len; } data; } Operation; +#define bytes_as_hex_for_debug(data, len) PyUnicode_AsUTF8(PyObject_CallMethod(PyBytes_FromStringAndSize((char*)data, len), "hex", NULL)) + static size_t unserialize_op(uint8_t *data, size_t len, Operation *op) { size_t consumed = 0; diff --git a/kitty/file_transmission.py b/kitty/file_transmission.py index c754b0f60..fbb6dd8fa 100644 --- a/kitty/file_transmission.py +++ b/kitty/file_transmission.py @@ -379,8 +379,10 @@ class PatchFile: self.patcher = Patcher(expected_size) self.block_buffer = memoryview(bytearray(self.patcher.block_size)) self.path = path + self.signature_done = False self.src_file: Optional[io.BufferedReader] = None self._dest_file: Optional[IO[bytes]] = None + self.closed = False @property def dest_file(self) -> IO[bytes]: @@ -389,14 +391,18 @@ class PatchFile: return self._dest_file def close(self) -> None: + if self.closed: + return + self.closed = True + p = self.patcher + del self.block_buffer, self.patcher if self.src_file is not None and not self.src_file.closed: self.src_file.close() if self._dest_file is not None and not self._dest_file.closed: self._dest_file.close() - self.patcher.finish_delta_data() - assert self.src_file is not None - os.replace(self.dest_file.name, self.src_file.name) - del self.patcher, self.block_buffer + p.finish_delta_data() + if self.src_file is not None: + os.replace(self.dest_file.name, self.src_file.name) def tell(self) -> int: df = self.dest_file @@ -417,18 +423,19 @@ class PatchFile: def next_signature_block(self) -> memoryview: buf = memoryview(bytearray(32)) + if self.signature_done: + return buf[:0] if self.src_file is None: self.src_file = open(self.path, 'rb') n = self.patcher.signature_header(buf) return buf[:n] - if self.src_file.closed: - return buf[:0] n = self.src_file.readinto(self.block_buffer) if n > 0: n = self.patcher.sign_block(self.block_buffer[:n], buf) buf = buf[:n] else: - self.src_file.close() + self.src_file.seek(0, os.SEEK_SET) + self.signature_done = True buf = buf[:0] return buf @@ -624,7 +631,8 @@ class ActiveReceive: df.write_data(self.files, ftc.data, ftc.action is Action.end_data) except Exception: df.failed = True - df.close() + with suppress(Exception): + df.close() raise return df @@ -1046,7 +1054,9 @@ class FileTransmission: if ar.send_errors: self.send_transmission_error(ar.id, err) except Exception as err: - log_error(f'Transmission protocol failed to write data to file with error: {err}') + import traceback + st = traceback.format_exc() + log_error(f'Transmission protocol failed to write data to file with error: {st}') if ar.send_errors: te = TransmissionError(file_id=cmd.file_id, msg=str(err)) self.send_transmission_error(ar.id, te)