More work on file transfer
This commit is contained in:
parent
8dfb0c6675
commit
32805ca968
@ -8,12 +8,15 @@ from typing import Dict, Iterator, List, Optional
|
||||
|
||||
from kitty.cli_stub import TransferCLIOptions
|
||||
from kitty.fast_data_types import FILE_TRANSFER_CODE
|
||||
from kitty.utils import sanitize_control_codes
|
||||
from kitty.file_transmission import (
|
||||
Action, FileTransmissionCommand, NameReprEnum, encode_bypass
|
||||
)
|
||||
|
||||
from ..tui.handler import Handler
|
||||
from ..tui.loop import Loop, debug
|
||||
from ..tui.utils import human_size
|
||||
from ..tui.operations import styled, without_line_wrap
|
||||
from .utils import expand_home, random_id
|
||||
|
||||
debug
|
||||
@ -35,6 +38,7 @@ class File:
|
||||
self.spec_id = int(ftc.file_id)
|
||||
self.permissions = ftc.permissions
|
||||
self.remote_path = ftc.name
|
||||
self.display_name = sanitize_control_codes(self.remote_path)
|
||||
self.remote_id = ftc.status
|
||||
self.remote_target = ftc.data.decode('utf-8')
|
||||
self.parent = ftc.parent
|
||||
@ -128,17 +132,23 @@ class Manager:
|
||||
self.failed_specs: Dict[int, str] = {}
|
||||
self.spec_counts = dict.fromkeys(range(len(self.spec)), 0)
|
||||
self.dest = dest
|
||||
self.remote_home = ''
|
||||
self.bypass = encode_bypass(request_id, bypass) if bypass else ''
|
||||
self.prefix = f'\x1b]{FILE_TRANSFER_CODE};id={self.request_id};'
|
||||
self.suffix = '\x1b\\'
|
||||
self.state = State.waiting_for_permission
|
||||
self.files: List[File] = []
|
||||
self.total_transfer_size = 0
|
||||
|
||||
def start_transfer(self) -> Iterator[str]:
|
||||
yield FileTransmissionCommand(action=Action.send, bypass=self.bypass, size=len(self.spec)).serialize()
|
||||
for i, x in enumerate(self.spec):
|
||||
yield FileTransmissionCommand(action=Action.file, file_id=str(i), name=x).serialize()
|
||||
|
||||
def collect_files(self, cli_opts: TransferCLIOptions) -> None:
|
||||
self.files = list(files_for_receive(cli_opts, self.dest, self.files, self.remote_home, self.spec))
|
||||
self.total_transfer_size = sum(max(0, f.expected_size) for f in self.files)
|
||||
|
||||
def on_file_transfer_response(self, ftc: FileTransmissionCommand) -> str:
|
||||
if self.state is State.waiting_for_permission:
|
||||
if ftc.action is Action.status:
|
||||
@ -161,6 +171,7 @@ class Manager:
|
||||
else:
|
||||
if ftc.status == 'OK':
|
||||
self.state = State.transferring
|
||||
self.remote_home = ftc.name
|
||||
return ''
|
||||
else:
|
||||
return ftc.status
|
||||
@ -185,6 +196,7 @@ class Receive(Handler):
|
||||
self.cli_opts = cli_opts
|
||||
self.manager = Manager(random_id(), spec, dest, bypass=cli_opts.permissions_bypass)
|
||||
self.quit_after_write_code: Optional[int] = None
|
||||
self.check_paths_printed = False
|
||||
|
||||
def send_payload(self, payload: str) -> None:
|
||||
self.write(self.manager.prefix)
|
||||
@ -226,7 +238,37 @@ class Receive(Handler):
|
||||
self.print_err('No matches found for: ' + ', '.join(self.manager.spec[k] for k, v in self.manager.spec_counts.items() if v == 0))
|
||||
self.quit_loop(1)
|
||||
return
|
||||
self.print(f'Queueing transfer of {len(self.manager.files)} files(s)')
|
||||
self.manager.collect_files(self.cli_opts)
|
||||
if self.cli_opts.confirm_paths:
|
||||
self.confirm_paths()
|
||||
else:
|
||||
self.queue_transfer()
|
||||
|
||||
def confirm_paths(self) -> None:
|
||||
self.print_check_paths()
|
||||
|
||||
def print_check_paths(self) -> None:
|
||||
if self.check_paths_printed:
|
||||
return
|
||||
self.check_paths_printed = True
|
||||
self.print('The following file transfers will be performed. A red destination means an existing file will be overwritten.')
|
||||
for df in self.manager.files:
|
||||
self.cmd.styled(df.ftype.short_text, fg=df.ftype.color)
|
||||
self.print(end=' ')
|
||||
self.print(df.display_name, '→', end=' ')
|
||||
self.cmd.styled(df.expanded_local_path, fg='red' if os.path.lexists(df.expanded_local_path) else None)
|
||||
self.print()
|
||||
self.print(f'Transferring {len(self.manager.files)} files of total size: {human_size(self.manager.total_transfer_size)}')
|
||||
self.print()
|
||||
self.print_continue_msg()
|
||||
|
||||
def print_continue_msg(self) -> None:
|
||||
self.print(
|
||||
'Press', styled('y', fg='green', bold=True, fg_intense=True), 'to continue or',
|
||||
styled('n', fg='red', bold=True, fg_intense=True), 'to abort')
|
||||
|
||||
def queue_transfer(self) -> None:
|
||||
self.print(f'Queueing transfer of {len(self.manager.files)} files(s)')
|
||||
|
||||
def print_err(self, msg: str) -> None:
|
||||
self.cmd.styled(msg, fg='red')
|
||||
@ -252,6 +294,11 @@ class Receive(Handler):
|
||||
self.manager.state = State.canceled
|
||||
self.asyncio_loop.call_later(delay, self.quit_loop, 1)
|
||||
|
||||
@Handler.atomic_update
|
||||
def draw_progress(self) -> None:
|
||||
with without_line_wrap(self.write):
|
||||
pass
|
||||
|
||||
|
||||
def receive_main(cli_opts: TransferCLIOptions, args: List[str]) -> None:
|
||||
dest = ''
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user