Skip to content

Commit f66e0b0

Browse files
Bskiser/fix linux update (#540)
* fix: Linux updating from the CLI * fix: Notify user on sigint during Linux update
1 parent 34a6c9a commit f66e0b0

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

crates/fig_install/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ pub enum Error {
9191
SystemNotOnChannel,
9292
#[error("manifest not found")]
9393
ManifestNotFound,
94-
#[error("update in progress")]
94+
#[error("Update in progress")]
9595
UpdateInProgress,
9696
#[error("could not convert path to cstring")]
9797
Nul(#[from] std::ffi::NulError),

crates/fig_ipc/src/local.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub async fn prompt_accessibility_command() -> Result<()> {
123123

124124
pub async fn update_command(force: bool) -> Result<Option<CommandResponse>> {
125125
let command = command::Command::Update(UpdateCommand { force });
126-
send_recv_command_to_socket(command).await
126+
send_recv_command_to_socket_with_timeout(command, std::time::Duration::from_secs(120)).await
127127
}
128128

129129
pub async fn restart_command() -> Result<()> {
@@ -155,7 +155,11 @@ pub async fn devtools_command(window: devtools_command::Window) -> Result<()> {
155155
pub trait LocalIpc: SendRecvMessage {
156156
async fn send_hook(&mut self, hook: local::Hook) -> Result<()>;
157157
async fn send_command(&mut self, command: local::command::Command, response: bool) -> Result<()>;
158-
async fn send_recv_command(&mut self, command: local::command::Command) -> Result<Option<local::CommandResponse>>;
158+
async fn send_recv_command(
159+
&mut self,
160+
command: local::command::Command,
161+
timeout: Duration,
162+
) -> Result<Option<local::CommandResponse>>;
159163
}
160164

161165
#[async_trait]
@@ -183,10 +187,15 @@ where
183187
Ok(self.send_message(message).await?)
184188
}
185189

186-
/// Send a command to and recv a response from the desktop app
187-
async fn send_recv_command(&mut self, command: local::command::Command) -> Result<Option<local::CommandResponse>> {
190+
/// Send a command to and recv a response from the desktop app, with a configurable timeout on
191+
/// the response
192+
async fn send_recv_command(
193+
&mut self,
194+
command: local::command::Command,
195+
timeout: Duration,
196+
) -> Result<Option<local::CommandResponse>> {
188197
self.send_command(command, true).await?;
189-
Ok(tokio::time::timeout(Duration::from_secs(2), self.recv_message())
198+
Ok(tokio::time::timeout(timeout, self.recv_message())
190199
.await
191200
.or(Err(Error::Timeout))??)
192201
}
@@ -206,7 +215,14 @@ pub async fn send_command_to_socket(command: local::command::Command) -> Result<
206215
}
207216

208217
pub async fn send_recv_command_to_socket(command: local::command::Command) -> Result<Option<local::CommandResponse>> {
218+
send_recv_command_to_socket_with_timeout(command, Duration::from_secs(2)).await
219+
}
220+
221+
pub async fn send_recv_command_to_socket_with_timeout(
222+
command: local::command::Command,
223+
timeout: Duration,
224+
) -> Result<Option<local::CommandResponse>> {
209225
let path = directories::desktop_socket_path()?;
210226
let mut conn = BufferedUnixStream::connect_timeout(&path, Duration::from_secs(3)).await?;
211-
conn.send_recv_command(command).await
227+
conn.send_recv_command(command, timeout).await
212228
}

crates/q_cli/src/cli/update.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::io::stdout;
12
use std::process::ExitCode;
23

34
use anstream::println;
@@ -38,6 +39,10 @@ use tracing::{
3839
};
3940

4041
use crate::util::dialoguer_theme;
42+
use crate::util::spinner::{
43+
Spinner,
44+
SpinnerComponent,
45+
};
4146

4247
#[derive(Debug, PartialEq, Args)]
4348
pub struct UpdateArgs {
@@ -130,19 +135,36 @@ async fn try_linux_update() -> Result<ExitCode> {
130135
.interact_opt()?;
131136

132137
if should_continue == Some(0) {
133-
println!("Updating {PRODUCT_NAME}...");
134-
match update_command(true).await {
138+
let mut spinner = Spinner::new(vec![
139+
SpinnerComponent::Spinner,
140+
SpinnerComponent::Text(format!(" Updating {PRODUCT_NAME}, please wait...")),
141+
]);
142+
tokio::spawn(async {
143+
tokio::signal::ctrl_c().await.unwrap();
144+
println!(
145+
"\nThe app is still updating. You can view the progress by running {}",
146+
format!("{CLI_BINARY_NAME} debug logs").bold()
147+
);
148+
crossterm::execute!(stdout(), crossterm::cursor::Show).unwrap();
149+
#[allow(clippy::exit)]
150+
std::process::exit(0);
151+
});
152+
153+
let update_cmd_result = update_command(true).await;
154+
println!("");
155+
match update_cmd_result {
135156
Ok(Some(CommandResponse {
136157
response: Some(Response::Success(_)),
137158
..
138159
})) => {
139-
println!("Update complete");
160+
spinner.stop_with_message("Update complete".into());
140161
Ok(ExitCode::SUCCESS)
141162
},
142163
Ok(Some(CommandResponse {
143164
response: Some(Response::Error(ErrorResponse { message, .. })),
144165
..
145166
})) => {
167+
spinner.stop();
146168
let message = message.unwrap_or("An unknown error occurred attempting to update".into());
147169
eyre::bail!(
148170
"{message}\n\nFailed to update. If this is unexpected, try running {} and then try again.\n",
@@ -152,14 +174,25 @@ async fn try_linux_update() -> Result<ExitCode> {
152174
Ok(_) => {
153175
// This case shouldn't happen, we expect a response from the desktop
154176
// app.
155-
println!("Update complete");
177+
spinner.stop_with_message("Update complete".into());
156178
Ok(ExitCode::SUCCESS)
157179
},
158180
Err(err) => {
159-
eyre::bail!(
160-
"{err}\n\nFailed to update. If this is unexpected, try running {} and then try again.\n",
161-
format!("{CLI_BINARY_NAME} doctor").bold()
162-
)
181+
spinner.stop();
182+
match err {
183+
fig_ipc::Error::Timeout => {
184+
eyre::bail!(
185+
"Timed out while waiting for the app to update. Updating may still be in progress - you can view app logs by running {}",
186+
format!("{CLI_BINARY_NAME} debug logs").bold()
187+
)
188+
},
189+
err => {
190+
eyre::bail!(
191+
"{err}\n\nFailed to update. If this is unexpected, try running {} and then try again.\n",
192+
format!("{CLI_BINARY_NAME} doctor").bold()
193+
)
194+
},
195+
}
163196
},
164197
}
165198
} else {

0 commit comments

Comments
 (0)