105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
#!/usr/bin/env python
|
|
# License: GPLv3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
|
|
|
|
|
|
import os
|
|
import sys
|
|
from typing import List, Tuple
|
|
|
|
from kitty.cli import parse_args
|
|
from kitty.cli_stub import TransferCLIOptions
|
|
|
|
from .receive import receive_main
|
|
from .send import send_main
|
|
|
|
usage = 'source_files_or_directories destination_path'
|
|
help_text = 'Transfer files over the TTY device'
|
|
|
|
|
|
def option_text() -> str:
|
|
return '''\
|
|
--direction -d
|
|
default=send
|
|
choices=send,receive
|
|
Whether to send or receive files.
|
|
|
|
|
|
--mode -m
|
|
default=normal
|
|
choices=normal,mirror
|
|
How to interpret command line arguments. In :code:`mirror` mode all arguments
|
|
are assumed to be files on the sending computer and they are mirrored onto the
|
|
receiving computer. In :code:`normal` mode the last argument is assumed to be a
|
|
destination path on the receiving computer.
|
|
|
|
|
|
--permissions-bypass -p
|
|
The password to use to skip the transfer confirmation popup in kitty. Must match
|
|
the password set for the :opt:`file_transfer_confirmation_bypass` option in
|
|
:file:`kitty.conf`. Note that leading and trailing whitespace is removed from
|
|
the password. A password starting with :code:`.`, :code:`/` or :code:`~`
|
|
characters is assumed to be a file name to read the password from. A value of
|
|
:code:`-` means read the password from STDIN. A password that is purely a number
|
|
less than 256 is assumed to be the number of a file descriptor from which to
|
|
read the actual password.
|
|
|
|
|
|
--confirm-paths -c
|
|
type=bool-set
|
|
Before actually transferring files, show a mapping of local file names to remote
|
|
file names and ask for confirmation.
|
|
|
|
|
|
--transmit-deltas -x
|
|
type=bool-set
|
|
If a file on the receiving side already exists, use the rsync algorithm to
|
|
update it to match the file on the sending side, potentially saving lots of
|
|
bandwidth and also automatically resuming partial transfers. Note that this will
|
|
actually degrade performance on fast links with small files, so use with care.
|
|
'''
|
|
|
|
|
|
def parse_transfer_args(args: List[str]) -> Tuple[TransferCLIOptions, List[str]]:
|
|
return parse_args(
|
|
args[1:], option_text, usage, help_text,
|
|
'kitty +kitten transfer', result_class=TransferCLIOptions
|
|
)
|
|
|
|
|
|
def read_bypass(loc: str) -> str:
|
|
if not loc:
|
|
return ''
|
|
if loc.isdigit() and int(loc) >= 0 and int(loc) < 256:
|
|
with open(int(loc), 'rb') as f:
|
|
return f.read().decode('utf-8')
|
|
if loc[0] in ('.', '~', '/'):
|
|
if loc[0] == '~':
|
|
loc = os.path.expanduser(loc)
|
|
with open(loc, 'rb') as f:
|
|
return f.read().decode('utf-8')
|
|
if loc == '-':
|
|
return sys.stdin.read()
|
|
return loc
|
|
|
|
|
|
def main(args: List[str]) -> None:
|
|
cli_opts, items = parse_transfer_args(args)
|
|
if cli_opts.permissions_bypass:
|
|
cli_opts.permissions_bypass = read_bypass(cli_opts.permissions_bypass).strip()
|
|
|
|
if not items:
|
|
raise SystemExit('Usage: kitty +kitten transfer file_or_directory ...')
|
|
if cli_opts.direction == 'send':
|
|
send_main(cli_opts, items)
|
|
else:
|
|
receive_main(cli_opts, items)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv)
|
|
elif __name__ == '__doc__':
|
|
cd = sys.cli_docs # type: ignore
|
|
cd['usage'] = usage
|
|
cd['options'] = option_text
|
|
cd['help_text'] = help_text
|