def handle_action(action: str, cli_opts: RemoteFileCLIOptions) -> Result: cli_data = json.loads(cli_opts.ssh_connection_data or '') if cli_data and cli_data[0] == is_ssh_kitten_sentinel: conn_data = SSHConnectionData(is_ssh_kitten_sentinel, cli_data[-1], -1, identity_file=json.dumps(cli_data[1:])) else: conn_data = SSHConnectionData(*cli_data) remote_path = cli_opts.path or '' if action == 'open': print('Opening', cli_opts.path, 'from', cli_opts.hostname) dest = os.path.join(tempfile.mkdtemp(), os.path.basename(remote_path)) with ControlMaster(conn_data, remote_path, cli_opts, dest=dest) as master: if master.check_hostname_matches(): if master.download(): return dest master.show_error('Failed to copy file from remote machine') elif action == 'edit': print('Editing', cli_opts.path, 'from', cli_opts.hostname) editor = get_editor() with ControlMaster(conn_data, remote_path, cli_opts) as master: if not master.check_hostname_matches(): return None if not master.download(): master.show_error(f'Failed to download {remote_path}') return None mtime = os.path.getmtime(master.dest) print(reset_terminal(), end='', flush=True) editor_process = subprocess.Popen(editor + [master.dest]) while editor_process.poll() is None: time.sleep(0.1) newmtime = os.path.getmtime(master.dest) if newmtime > mtime: mtime = newmtime if master.is_alive: master.upload() print(reset_terminal(), end='', flush=True) if master.is_alive: if not master.upload(suppress_output=False): master.show_error(f'Failed to upload {remote_path}') else: master.show_error( f'Failed to upload {remote_path}, SSH master process died') elif action == 'save': print('Saving', cli_opts.path, 'from', cli_opts.hostname) save_as(conn_data, remote_path, cli_opts) return None
def get_connection_data(args: List[str]) -> Optional[SSHConnectionData]: boolean_ssh_args, other_ssh_args = get_ssh_cli() found_ssh = '' port: Optional[int] = None expecting_port = False expecting_option_val = False for i, arg in enumerate(args): if not found_ssh: if os.path.basename(arg).lower() in ('ssh', 'ssh.exe'): found_ssh = arg continue if arg.startswith('-') and not expecting_option_val: if arg in boolean_ssh_args: continue if arg.startswith('-p'): if arg[2:].isdigit(): with suppress(Exception): port = int(arg[2:]) elif arg == '-p': expecting_port = True expecting_option_val = True continue if expecting_option_val: if expecting_port: with suppress(Exception): port = int(arg) expecting_port = False expecting_option_val = False continue return SSHConnectionData(found_ssh, arg, port)
def get_connection_data(args: List[str], cwd: str = '') -> Optional[SSHConnectionData]: boolean_ssh_args, other_ssh_args = get_ssh_cli() port: Optional[int] = None expecting_port = expecting_identity = False expecting_option_val = False expecting_hostname = False host_name = identity_file = found_ssh = '' for i, arg in enumerate(args): if not found_ssh: if os.path.basename(arg).lower() in ('ssh', 'ssh.exe'): found_ssh = arg continue if expecting_hostname: host_name = arg continue if arg.startswith('-') and not expecting_option_val: if arg in boolean_ssh_args: continue if arg == '--': expecting_hostname = True if arg.startswith('-p'): if arg[2:].isdigit(): with suppress(Exception): port = int(arg[2:]) continue elif arg == '-p': expecting_port = True elif arg.startswith('-i'): if arg == '-i': expecting_identity = True else: identity_file = arg[2:] continue expecting_option_val = True continue if expecting_option_val: if expecting_port: with suppress(Exception): port = int(arg) expecting_port = False elif expecting_identity: identity_file = arg expecting_option_val = False continue if not host_name: host_name = arg if not host_name: return None if identity_file: if not os.path.isabs(identity_file): identity_file = os.path.expanduser(identity_file) if not os.path.isabs(identity_file): identity_file = os.path.normpath( os.path.join(cwd or os.getcwd(), identity_file)) return SSHConnectionData(found_ssh, host_name, port, identity_file)
def t(cmdline, binary='ssh', host='main', port=None, identity_file='', extra_args=()): if identity_file: identity_file = os.path.abspath(identity_file) en = set(f'{x[0]}' for x in extra_args) q = get_connection_data(cmdline.split(), extra_args=en) self.ae( q, SSHConnectionData(binary, host, port, identity_file, extra_args))
def get_connection_data( args: List[str], cwd: str = '', extra_args: Tuple[str, ...] = () ) -> Optional[SSHConnectionData]: boolean_ssh_args, other_ssh_args = get_ssh_cli() port: Optional[int] = None expecting_port = expecting_identity = False expecting_option_val = False expecting_hostname = False expecting_extra_val = '' host_name = identity_file = found_ssh = '' found_extra_args: List[Tuple[str, str]] = [] for i, arg in enumerate(args): if not found_ssh: if os.path.basename(arg).lower() in ('ssh', 'ssh.exe'): found_ssh = arg continue if expecting_hostname: host_name = arg continue if arg.startswith('-') and not expecting_option_val: if arg in boolean_ssh_args: continue if arg == '--': expecting_hostname = True if arg.startswith('-p'): if arg[2:].isdigit(): with suppress(Exception): port = int(arg[2:]) continue elif arg == '-p': expecting_port = True elif arg.startswith('-i'): if arg == '-i': expecting_identity = True else: identity_file = arg[2:] continue if arg.startswith('--') and extra_args: matching_ex = is_extra_arg(arg, extra_args) if matching_ex: if '=' in arg: exval = arg.partition('=')[-1] found_extra_args.append((matching_ex, exval)) continue expecting_extra_val = matching_ex expecting_option_val = True continue if expecting_option_val: if expecting_port: with suppress(Exception): port = int(arg) expecting_port = False elif expecting_identity: identity_file = arg elif expecting_extra_val: found_extra_args.append((expecting_extra_val, arg)) expecting_extra_val = '' expecting_option_val = False continue if not host_name: host_name = arg if not host_name: return None if host_name.startswith('ssh://'): from urllib.parse import urlparse purl = urlparse(host_name) if purl.hostname: host_name = purl.hostname if purl.username: host_name = f'{purl.username}@{host_name}' if port is None and purl.port: port = purl.port if identity_file: if not os.path.isabs(identity_file): identity_file = os.path.expanduser(identity_file) if not os.path.isabs(identity_file): identity_file = os.path.normpath( os.path.join(cwd or os.getcwd(), identity_file)) return SSHConnectionData(found_ssh, host_name, port, identity_file, tuple(found_extra_args))
def t(cmdline, binary='ssh', host='main', port=None, identity_file=''): if identity_file: identity_file = os.path.abspath(identity_file) q = get_connection_data(cmdline.split()) self.ae(q, SSHConnectionData(binary, host, port, identity_file))