fix: fixed a crash when the local directory specified in the auth form does not exist

fix #319
This commit is contained in:
veeso
2025-03-15 16:46:57 +01:00
parent dd35fe825c
commit cdf303a847
6 changed files with 46 additions and 24 deletions

View File

@@ -44,6 +44,8 @@
Released on ?? Released on ??
- [issue 319](https://github.com/veeso/termscp/issues/319): fixed a crash when the local directory specified in the auth form does not exist
- [issue 327](https://github.com/veeso/termscp/issues/327): fixed a panic when trying to go up from local directory on localhost in the auth form
- Dependencies: - Dependencies:
- `argh` to `0.1.13` - `argh` to `0.1.13`
- `bytesize` to `2` - `bytesize` to `2`

View File

@@ -342,7 +342,7 @@ impl ActivityManager {
fn run_filetransfer(&mut self) -> Option<NextActivity> { fn run_filetransfer(&mut self) -> Option<NextActivity> {
info!("Starting FileTransferActivity"); info!("Starting FileTransferActivity");
// Get context // Get context
let ctx: Context = match self.context.take() { let mut ctx: Context = match self.context.take() {
Some(ctx) => ctx, Some(ctx) => ctx,
None => { None => {
error!("Failed to start FileTransferActivity: context is None"); error!("Failed to start FileTransferActivity: context is None");
@@ -367,8 +367,18 @@ impl ActivityManager {
} }
}; };
let mut activity: FileTransferActivity = // try to setup activity
FileTransferActivity::new(host_bridge_params, remote_params, self.ticks); let mut activity =
match FileTransferActivity::new(host_bridge_params, remote_params, self.ticks) {
Ok(activity) => activity,
Err(err) => {
error!("Failed to start FileTransferActivity: {}", err);
ctx.set_error(err);
self.context = Some(ctx);
// Return to authentication
return Some(NextActivity::Authentication);
}
};
// Prepare result // Prepare result
let result: Option<NextActivity>; let result: Option<NextActivity>;
// Create activity // Create activity

View File

@@ -7,15 +7,19 @@ pub struct HostBridgeBuilder;
impl HostBridgeBuilder { impl HostBridgeBuilder {
/// Build Host Bridge from parms /// Build Host Bridge from parms
/// ///
/// if protocol and parameters are inconsistent, the function will panic. /// if protocol and parameters are inconsistent, the function will return an error.
pub fn build(params: HostBridgeParams, config_client: &ConfigClient) -> Box<dyn HostBridge> { pub fn build(
params: HostBridgeParams,
config_client: &ConfigClient,
) -> Result<Box<dyn HostBridge>, String> {
match params { match params {
HostBridgeParams::Localhost(path) => { HostBridgeParams::Localhost(path) => Localhost::new(path)
Box::new(Localhost::new(path).expect("Failed to create Localhost")) .map(|host| Box::new(host) as Box<dyn HostBridge>)
.map_err(|e| e.to_string()),
HostBridgeParams::Remote(protocol, params) => {
RemoteFsBuilder::build(protocol, params, config_client)
.map(|host| Box::new(RemoteBridged::from(host)) as Box<dyn HostBridge>)
} }
HostBridgeParams::Remote(protocol, params) => Box::new(RemoteBridged::from(
RemoteFsBuilder::build(protocol, params, config_client),
)),
} }
} }
} }

View File

@@ -37,33 +37,35 @@ impl RemoteFsBuilder {
protocol: FileTransferProtocol, protocol: FileTransferProtocol,
params: ProtocolParams, params: ProtocolParams,
config_client: &ConfigClient, config_client: &ConfigClient,
) -> Box<dyn RemoteFs> { ) -> Result<Box<dyn RemoteFs>, String> {
match (protocol, params) { match (protocol, params) {
(FileTransferProtocol::AwsS3, ProtocolParams::AwsS3(params)) => { (FileTransferProtocol::AwsS3, ProtocolParams::AwsS3(params)) => {
Box::new(Self::aws_s3_client(params)) Ok(Box::new(Self::aws_s3_client(params)))
} }
(FileTransferProtocol::Ftp(secure), ProtocolParams::Generic(params)) => { (FileTransferProtocol::Ftp(secure), ProtocolParams::Generic(params)) => {
Box::new(Self::ftp_client(params, secure)) Ok(Box::new(Self::ftp_client(params, secure)))
} }
(FileTransferProtocol::Kube, ProtocolParams::Kube(params)) => { (FileTransferProtocol::Kube, ProtocolParams::Kube(params)) => {
Box::new(Self::kube_client(params)) Ok(Box::new(Self::kube_client(params)))
} }
(FileTransferProtocol::Scp, ProtocolParams::Generic(params)) => { (FileTransferProtocol::Scp, ProtocolParams::Generic(params)) => {
Box::new(Self::scp_client(params, config_client)) Ok(Box::new(Self::scp_client(params, config_client)))
} }
(FileTransferProtocol::Sftp, ProtocolParams::Generic(params)) => { (FileTransferProtocol::Sftp, ProtocolParams::Generic(params)) => {
Box::new(Self::sftp_client(params, config_client)) Ok(Box::new(Self::sftp_client(params, config_client)))
} }
#[cfg(smb)] #[cfg(smb)]
(FileTransferProtocol::Smb, ProtocolParams::Smb(params)) => { (FileTransferProtocol::Smb, ProtocolParams::Smb(params)) => {
Box::new(Self::smb_client(params)) Ok(Box::new(Self::smb_client(params)))
} }
(FileTransferProtocol::WebDAV, ProtocolParams::WebDAV(params)) => { (FileTransferProtocol::WebDAV, ProtocolParams::WebDAV(params)) => {
Box::new(Self::webdav_client(params)) Ok(Box::new(Self::webdav_client(params)))
} }
(protocol, params) => { (protocol, params) => {
error!("Invalid params for protocol '{:?}'", protocol); error!("Invalid params for protocol '{:?}'", protocol);
panic!("Invalid protocol '{protocol:?}' with parameters of type {params:?}") Err(format!(
"Invalid protocol '{protocol:?}' with parameters of type {params:?}",
))
} }
} }
} }

View File

@@ -243,14 +243,14 @@ impl FileTransferActivity {
host_bridge_params: HostBridgeParams, host_bridge_params: HostBridgeParams,
remote_params: &FileTransferParams, remote_params: &FileTransferParams,
ticks: Duration, ticks: Duration,
) -> Self { ) -> Result<Self, String> {
// Get config client // Get config client
let config_client: ConfigClient = Self::init_config_client(); let config_client: ConfigClient = Self::init_config_client();
// init host bridge // init host bridge
let host_bridge = HostBridgeBuilder::build(host_bridge_params, &config_client); let host_bridge = HostBridgeBuilder::build(host_bridge_params, &config_client)?;
let host_bridge_connected = host_bridge.is_localhost(); let host_bridge_connected = host_bridge.is_localhost();
let enable_fs_watcher = host_bridge.is_localhost(); let enable_fs_watcher = host_bridge.is_localhost();
Self { Ok(Self {
exit_reason: None, exit_reason: None,
context: None, context: None,
app: Application::init( app: Application::init(
@@ -264,7 +264,7 @@ impl FileTransferActivity {
remote_params.protocol, remote_params.protocol,
remote_params.params.clone(), remote_params.params.clone(),
&config_client, &config_client,
), )?,
browser: Browser::new(&config_client), browser: Browser::new(&config_client),
log_records: VecDeque::with_capacity(256), // 256 events is enough I guess log_records: VecDeque::with_capacity(256), // 256 events is enough I guess
walkdir: WalkdirStates::default(), walkdir: WalkdirStates::default(),
@@ -280,7 +280,7 @@ impl FileTransferActivity {
}, },
host_bridge_connected, host_bridge_connected,
remote_connected: false, remote_connected: false,
} })
} }
fn host_bridge(&self) -> &FileExplorer { fn host_bridge(&self) -> &FileExplorer {

View File

@@ -108,6 +108,10 @@ impl Context {
pub fn error(&mut self) -> Option<String> { pub fn error(&mut self) -> Option<String> {
self.error.take() self.error.take()
} }
pub fn set_error(&mut self, error: String) {
self.error = Some(error);
}
} }
impl Drop for Context { impl Drop for Context {