diff --git a/crates/activity_indicator/src/activity_indicator.rs b/crates/activity_indicator/src/activity_indicator.rs index 5ce8f06448..4b25ce93b0 100644 --- a/crates/activity_indicator/src/activity_indicator.rs +++ b/crates/activity_indicator/src/activity_indicator.rs @@ -485,7 +485,7 @@ impl ActivityIndicator { this.dismiss_error_message(&DismissErrorMessage, window, cx) })), }), - AutoUpdateStatus::Updated { binary_path } => Some(Content { + AutoUpdateStatus::Updated { binary_path, .. } => Some(Content { icon: None, message: "Click to restart and update Zed".to_string(), on_click: Some(Arc::new({ diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index 6ff878f10d..d0e1f95a99 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -39,13 +39,22 @@ struct UpdateRequestBody { destination: &'static str, } +#[derive(Clone, PartialEq, Eq)] +pub enum VersionCheckType { + Sha(String), + Semantic(SemanticVersion), +} + #[derive(Clone, PartialEq, Eq)] pub enum AutoUpdateStatus { Idle, Checking, Downloading, Installing, - Updated { binary_path: PathBuf }, + Updated { + binary_path: PathBuf, + version: VersionCheckType, + }, Errored, } @@ -62,7 +71,7 @@ pub struct AutoUpdater { pending_poll: Option>>, } -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Clone, Debug)] pub struct JsonRelease { pub version: String, pub url: String, @@ -307,7 +316,7 @@ impl AutoUpdater { } pub fn poll(&mut self, cx: &mut Context) { - if self.pending_poll.is_some() || self.status.is_updated() { + if self.pending_poll.is_some() { return; } @@ -483,36 +492,63 @@ impl AutoUpdater { Self::get_release(this, asset, os, arch, None, release_channel, cx).await } + fn installed_update_version(&self) -> Option { + match &self.status { + AutoUpdateStatus::Updated { version, .. } => Some(version.clone()), + _ => None, + } + } + async fn update(this: Entity, mut cx: AsyncApp) -> Result<()> { - let (client, current_version, release_channel) = this.update(&mut cx, |this, cx| { - this.status = AutoUpdateStatus::Checking; - cx.notify(); - ( - this.http_client.clone(), - this.current_version, - ReleaseChannel::try_global(cx), - ) - })?; + let (client, current_version, installed_update_version, release_channel) = + this.update(&mut cx, |this, cx| { + this.status = AutoUpdateStatus::Checking; + cx.notify(); + ( + this.http_client.clone(), + this.current_version, + this.installed_update_version(), + ReleaseChannel::try_global(cx), + ) + })?; let release = Self::get_latest_release(&this, "zed", OS, ARCH, release_channel, &mut cx).await?; - let should_download = match *RELEASE_CHANNEL { - ReleaseChannel::Nightly => cx - .update(|cx| AppCommitSha::try_global(cx).map(|sha| release.version != sha.0)) - .ok() - .flatten() - .unwrap_or(true), - _ => release.version.parse::()? > current_version, + let update_version_to_install = match *RELEASE_CHANNEL { + ReleaseChannel::Nightly => { + let should_download = cx + .update(|cx| AppCommitSha::try_global(cx).map(|sha| release.version != sha.0)) + .ok() + .flatten() + .unwrap_or(true); + + should_download.then(|| VersionCheckType::Sha(release.version.clone())) + } + _ => { + let installed_version = + installed_update_version.unwrap_or(VersionCheckType::Semantic(current_version)); + match installed_version { + VersionCheckType::Sha(_) => { + log::warn!("Unexpected SHA-based version in non-nightly build"); + Some(installed_version) + } + VersionCheckType::Semantic(semantic_comparison_version) => { + let latest_release_version = release.version.parse::()?; + let should_download = latest_release_version > semantic_comparison_version; + should_download.then(|| VersionCheckType::Semantic(latest_release_version)) + } + } + } }; - if !should_download { + let Some(update_version) = update_version_to_install else { this.update(&mut cx, |this, cx| { this.status = AutoUpdateStatus::Idle; cx.notify(); })?; return Ok(()); - } + }; this.update(&mut cx, |this, cx| { this.status = AutoUpdateStatus::Downloading; @@ -534,7 +570,7 @@ impl AutoUpdater { ); let downloaded_asset = installer_dir.path().join(filename); - download_release(&downloaded_asset, release, client, &cx).await?; + download_release(&downloaded_asset, release.clone(), client, &cx).await?; this.update(&mut cx, |this, cx| { this.status = AutoUpdateStatus::Installing; @@ -551,7 +587,10 @@ impl AutoUpdater { this.update(&mut cx, |this, cx| { this.set_should_show_update_notification(true, cx) .detach_and_log_err(cx); - this.status = AutoUpdateStatus::Updated { binary_path }; + this.status = AutoUpdateStatus::Updated { + binary_path, + version: update_version, + }; cx.notify(); })?;