auto_update: Add better error context (#51850)

Lukas Wirth created

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/auto_update/src/auto_update.rs | 73 ++++++++++++++++------------
1 file changed, 41 insertions(+), 32 deletions(-)

Detailed changes

crates/auto_update/src/auto_update.rs 🔗

@@ -629,9 +629,13 @@ impl AutoUpdater {
             cx.notify();
         });
 
-        let installer_dir = InstallerDir::new().await?;
+        let installer_dir = InstallerDir::new()
+            .await
+            .context("Failed to create installer dir")?;
         let target_path = Self::target_path(&installer_dir).await?;
-        download_release(&target_path, fetched_release_data, client).await?;
+        download_release(&target_path, fetched_release_data, client)
+            .await
+            .with_context(|| format!("Failed to download update to {}", target_path.display()))?;
 
         this.update(cx, |this, cx| {
             this.status = AutoUpdateStatus::Installing {
@@ -640,7 +644,9 @@ impl AutoUpdater {
             cx.notify();
         });
 
-        let new_binary_path = Self::install_release(installer_dir, target_path, cx).await?;
+        let new_binary_path = Self::install_release(installer_dir, &target_path, cx)
+            .await
+            .with_context(|| format!("Failed to install update at: {}", target_path.display()))?;
         if let Some(new_binary_path) = new_binary_path {
             cx.update(|cx| cx.set_restart_path(new_binary_path));
         }
@@ -730,7 +736,7 @@ impl AutoUpdater {
 
     async fn install_release(
         installer_dir: InstallerDir,
-        target_path: PathBuf,
+        target_path: &Path,
         cx: &AsyncApp,
     ) -> Result<Option<PathBuf>> {
         #[cfg(test)]
@@ -888,7 +894,7 @@ async fn download_release(
 
 async fn install_release_linux(
     temp_dir: &InstallerDir,
-    downloaded_tar_gz: PathBuf,
+    downloaded_tar_gz: &Path,
     cx: &AsyncApp,
 ) -> Result<Option<PathBuf>> {
     let channel = cx.update(|cx| ReleaseChannel::global(cx).dev_name());
@@ -900,13 +906,15 @@ async fn install_release_linux(
         .await
         .context("failed to create directory into which to extract update")?;
 
-    let output = new_command("tar")
-        .arg("-xzf")
+    let mut cmd = new_command("tar");
+    cmd.arg("-xzf")
         .arg(&downloaded_tar_gz)
         .arg("-C")
-        .arg(&extracted)
+        .arg(&extracted);
+    let output = cmd
         .output()
-        .await?;
+        .await
+        .with_context(|| "failed to extract: {cmd}")?;
 
     anyhow::ensure!(
         output.status.success(),
@@ -935,12 +943,12 @@ async fn install_release_linux(
         to = PathBuf::from(prefix);
     }
 
-    let output = new_command("rsync")
-        .args(["-av", "--delete"])
-        .arg(&from)
-        .arg(&to)
+    let mut cmd = new_command("rsync");
+    cmd.args(["-av", "--delete"]).arg(&from).arg(&to);
+    let output = cmd
         .output()
-        .await?;
+        .await
+        .with_context(|| "failed to rsync: {cmd}")?;
 
     anyhow::ensure!(
         output.status.success(),
@@ -955,7 +963,7 @@ async fn install_release_linux(
 
 async fn install_release_macos(
     temp_dir: &InstallerDir,
-    downloaded_dmg: PathBuf,
+    downloaded_dmg: &Path,
     cx: &AsyncApp,
 ) -> Result<Option<PathBuf>> {
     let running_app_path = cx.update(|cx| cx.app_path())?;
@@ -967,13 +975,15 @@ async fn install_release_macos(
     let mut mounted_app_path: OsString = mount_path.join(running_app_filename).into();
 
     mounted_app_path.push("/");
-    let output = new_command("hdiutil")
-        .args(["attach", "-nobrowse"])
+    let mut cmd = new_command("hdiutil");
+    cmd.args(["attach", "-nobrowse"])
         .arg(&downloaded_dmg)
         .arg("-mountroot")
-        .arg(temp_dir.path())
+        .arg(temp_dir.path());
+    let output = cmd
         .output()
-        .await?;
+        .await
+        .with_context(|| "failed to mount: {cmd}")?;
 
     anyhow::ensure!(
         output.status.success(),
@@ -987,12 +997,14 @@ async fn install_release_macos(
         background_executor: cx.background_executor(),
     };
 
-    let output = new_command("rsync")
-        .args(["-av", "--delete", "--exclude", "Icon?"])
+    let mut cmd = new_command("rsync");
+    cmd.args(["-av", "--delete", "--exclude", "Icon?"])
         .arg(&mounted_app_path)
-        .arg(&running_app_path)
+        .arg(&running_app_path);
+    let output = cmd
         .output()
-        .await?;
+        .await
+        .with_context(|| "failed to rsync: {cmd}")?;
 
     anyhow::ensure!(
         output.status.success(),
@@ -1017,14 +1029,13 @@ async fn cleanup_windows() -> Result<()> {
     Ok(())
 }
 
-async fn install_release_windows(downloaded_installer: PathBuf) -> Result<Option<PathBuf>> {
-    let output = new_command(downloaded_installer)
-        .arg("/verysilent")
+async fn install_release_windows(downloaded_installer: &Path) -> Result<Option<PathBuf>> {
+    let mut cmd = new_command(downloaded_installer);
+    cmd.arg("/verysilent")
         .arg("/update=true")
         .arg("!desktopicon")
-        .arg("!quicklaunchicon")
-        .output()
-        .await?;
+        .arg("!quicklaunchicon");
+    let output = cmd.output().await?;
     anyhow::ensure!(
         output.status.success(),
         "failed to start installer: {:?}",
@@ -1089,9 +1100,7 @@ mod tests {
 
     use super::*;
 
-    pub(super) struct InstallOverride(
-        pub Rc<dyn Fn(PathBuf, &AsyncApp) -> Result<Option<PathBuf>>>,
-    );
+    pub(super) struct InstallOverride(pub Rc<dyn Fn(&Path, &AsyncApp) -> Result<Option<PathBuf>>>);
     impl Global for InstallOverride {}
 
     #[gpui::test]