79 lines
2.7 KiB
Rust
79 lines
2.7 KiB
Rust
use std::process::Command;
|
|
use std::time::Duration;
|
|
|
|
use tauri::Manager;
|
|
use tokio::time::sleep;
|
|
|
|
use crate::app::APP;
|
|
use crate::errors::*;
|
|
use crate::state::AppState;
|
|
|
|
|
|
pub async fn launch(use_base: bool) -> Result<(), LaunchTerminalError> {
|
|
let app = APP.get().unwrap();
|
|
let state = app.state::<AppState>();
|
|
|
|
// register_terminal_request() returns Err if there is another request pending
|
|
if state.register_terminal_request().await.is_err() {
|
|
return Ok(());
|
|
}
|
|
|
|
let mut cmd = {
|
|
let config = state.config.read().await;
|
|
let mut cmd = Command::new(&config.terminal.exec);
|
|
cmd.args(&config.terminal.args);
|
|
cmd
|
|
};
|
|
|
|
// if session is locked, wait for credentials from frontend
|
|
if state.is_locked().await {
|
|
let lease = state.acquire_visibility_lease(0).await
|
|
.map_err(|_e| LaunchTerminalError::NoMainWindow)?; // automate conversion eventually?
|
|
|
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
|
app.once("unlocked", move |_| {
|
|
let _ = tx.send(());
|
|
});
|
|
|
|
let timeout = Duration::from_secs(60);
|
|
tokio::select! {
|
|
// if the frontend is unlocked within 60 seconds, release visibility lock and proceed
|
|
_ = rx => lease.release(),
|
|
// otherwise, dump this request, but return Ok so we don't get an error popup
|
|
_ = sleep(timeout) => {
|
|
state.unregister_terminal_request().await;
|
|
eprintln!("WARNING: Request to launch terminal timed out after 60 seconds.");
|
|
return Ok(());
|
|
},
|
|
}
|
|
}
|
|
|
|
// session should really be unlocked at this point, but if the frontend misbehaves
|
|
// (i.e. lies about unlocking) we could end up here with a locked session
|
|
// this will result in an error popup to the user (see main hotkey handler)
|
|
if use_base {
|
|
let base_creds = state.get_aws_base("default").await?;
|
|
cmd.env("AWS_ACCESS_KEY_ID", &base_creds.access_key_id);
|
|
cmd.env("AWS_SECRET_ACCESS_KEY", &base_creds.secret_access_key);
|
|
}
|
|
else {
|
|
let session_creds = state.get_aws_session("default").await?;
|
|
cmd.env("AWS_ACCESS_KEY_ID", &session_creds.access_key_id);
|
|
cmd.env("AWS_SECRET_ACCESS_KEY", &session_creds.secret_access_key);
|
|
cmd.env("AWS_SESSION_TOKEN", &session_creds.session_token);
|
|
}
|
|
|
|
let res = match cmd.spawn() {
|
|
Ok(_) => Ok(()),
|
|
Err(e) if std::io::ErrorKind::NotFound == e.kind() => {
|
|
Err(ExecError::NotFound(cmd.get_program().to_owned()))
|
|
},
|
|
Err(e) => Err(ExecError::ExecutionFailed(e)),
|
|
};
|
|
|
|
state.unregister_terminal_request().await;
|
|
|
|
res?; // ? auto-conversion is more liberal than .into()
|
|
Ok(())
|
|
}
|