Use shortened SHA when displaying version to install (#31281)

Joseph T. Lyons created

This PR uses a shortened SHA when displaying the nightly version to
install in the update status, for nicer tooltip formatting.

Release Notes:

- N/A

Change summary

Cargo.lock                                          |  1 
crates/activity_indicator/Cargo.toml                |  3 
crates/activity_indicator/src/activity_indicator.rs | 45 ++++++++++++---
crates/auto_update/src/auto_update.rs               | 29 +++++----
crates/feedback/src/system_specs.rs                 |  6 -
crates/release_channel/src/lib.rs                   | 19 +++++
crates/remote/src/ssh_session.rs                    |  2 
crates/zed/src/main.rs                              |  2 
crates/zed/src/reliability.rs                       |  4 
crates/zed/src/zed.rs                               |  2 
10 files changed, 78 insertions(+), 35 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -14,6 +14,7 @@ dependencies = [
  "gpui",
  "language",
  "project",
+ "release_channel",
  "smallvec",
  "ui",
  "util",

crates/activity_indicator/Cargo.toml 🔗

@@ -24,8 +24,9 @@ project.workspace = true
 smallvec.workspace = true
 ui.workspace = true
 util.workspace = true
-workspace.workspace = true
 workspace-hack.workspace = true
+workspace.workspace = true
 
 [dev-dependencies]
 editor = { workspace = true, features = ["test-support"] }
+release_channel.workspace = true

crates/activity_indicator/src/activity_indicator.rs 🔗

@@ -1,4 +1,4 @@
-use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage};
+use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage, VersionCheckType};
 use editor::Editor;
 use extension_host::ExtensionStore;
 use futures::StreamExt;
@@ -508,14 +508,7 @@ impl ActivityIndicator {
                         };
                         move |_, _, cx| workspace::reload(&reload, cx)
                     })),
-                    tooltip_message: Some(format!("Install version: {}", {
-                        match version {
-                            auto_update::VersionCheckType::Sha(sha) => sha.to_string(),
-                            auto_update::VersionCheckType::Semantic(semantic_version) => {
-                                semantic_version.to_string()
-                            }
-                        }
-                    })),
+                    tooltip_message: Some(Self::install_version_tooltip_message(&version)),
                 }),
                 AutoUpdateStatus::Errored => Some(Content {
                     icon: Some(
@@ -555,6 +548,17 @@ impl ActivityIndicator {
         None
     }
 
+    fn install_version_tooltip_message(version: &VersionCheckType) -> String {
+        format!("Install version: {}", {
+            match version {
+                auto_update::VersionCheckType::Sha(sha) => format!("{}…", sha.short()),
+                auto_update::VersionCheckType::Semantic(semantic_version) => {
+                    semantic_version.to_string()
+                }
+            }
+        })
+    }
+
     fn toggle_language_server_work_context_menu(
         &mut self,
         window: &mut Window,
@@ -686,3 +690,26 @@ impl StatusItemView for ActivityIndicator {
     ) {
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use gpui::SemanticVersion;
+    use release_channel::AppCommitSha;
+
+    use super::*;
+
+    #[test]
+    fn test_install_version_tooltip_message() {
+        let message = ActivityIndicator::install_version_tooltip_message(
+            &VersionCheckType::Semantic(SemanticVersion::new(1, 0, 0)),
+        );
+
+        assert_eq!(message, "Install version: 1.0.0");
+
+        let message = ActivityIndicator::install_version_tooltip_message(&VersionCheckType::Sha(
+            AppCommitSha::new("14d9a4189f058d8736339b06ff2340101eaea5af".to_string()),
+        ));
+
+        assert_eq!(message, "Install version: 14d9a41…");
+    }
+}

crates/auto_update/src/auto_update.rs 🔗

@@ -41,7 +41,7 @@ struct UpdateRequestBody {
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum VersionCheckType {
-    Sha(String),
+    Sha(AppCommitSha),
     Semantic(SemanticVersion),
 }
 
@@ -510,7 +510,7 @@ impl AutoUpdater {
         let fetched_release_data =
             Self::get_latest_release(&this, "zed", OS, ARCH, release_channel, &mut cx).await?;
         let fetched_version = fetched_release_data.clone().version;
-        let app_commit_sha = cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.0));
+        let app_commit_sha = cx.update(|cx| AppCommitSha::try_global(cx).map(|sha| sha.full()));
         let newer_version = Self::check_for_newer_version(
             *RELEASE_CHANNEL,
             app_commit_sha,
@@ -569,9 +569,9 @@ impl AutoUpdater {
         if let AutoUpdateStatus::Updated { version, .. } = status {
             match version {
                 VersionCheckType::Sha(cached_version) => {
-                    let should_download = fetched_version != cached_version;
-                    let newer_version =
-                        should_download.then(|| VersionCheckType::Sha(fetched_version));
+                    let should_download = fetched_version != cached_version.full();
+                    let newer_version = should_download
+                        .then(|| VersionCheckType::Sha(AppCommitSha::new(fetched_version)));
                     return Ok(newer_version);
                 }
                 VersionCheckType::Semantic(cached_version) => {
@@ -590,7 +590,8 @@ impl AutoUpdater {
                     .flatten()
                     .map(|sha| fetched_version != sha)
                     .unwrap_or(true);
-                let newer_version = should_download.then(|| VersionCheckType::Sha(fetched_version));
+                let newer_version = should_download
+                    .then(|| VersionCheckType::Sha(AppCommitSha::new(fetched_version)));
                 Ok(newer_version)
             }
             _ => Self::check_for_newer_version_non_nightly(
@@ -1041,7 +1042,7 @@ mod tests {
 
         assert_eq!(
             newer_version.unwrap(),
-            Some(VersionCheckType::Sha(fetched_sha))
+            Some(VersionCheckType::Sha(AppCommitSha::new(fetched_sha)))
         );
     }
 
@@ -1052,7 +1053,7 @@ mod tests {
         let installed_version = SemanticVersion::new(1, 0, 0);
         let status = AutoUpdateStatus::Updated {
             binary_path: PathBuf::new(),
-            version: VersionCheckType::Sha("b".to_string()),
+            version: VersionCheckType::Sha(AppCommitSha::new("b".to_string())),
         };
         let fetched_sha = "b".to_string();
 
@@ -1074,7 +1075,7 @@ mod tests {
         let installed_version = SemanticVersion::new(1, 0, 0);
         let status = AutoUpdateStatus::Updated {
             binary_path: PathBuf::new(),
-            version: VersionCheckType::Sha("b".to_string()),
+            version: VersionCheckType::Sha(AppCommitSha::new("b".to_string())),
         };
         let fetched_sha = "c".to_string();
 
@@ -1088,7 +1089,7 @@ mod tests {
 
         assert_eq!(
             newer_version.unwrap(),
-            Some(VersionCheckType::Sha(fetched_sha))
+            Some(VersionCheckType::Sha(AppCommitSha::new(fetched_sha)))
         );
     }
 
@@ -1110,7 +1111,7 @@ mod tests {
 
         assert_eq!(
             newer_version.unwrap(),
-            Some(VersionCheckType::Sha(fetched_sha))
+            Some(VersionCheckType::Sha(AppCommitSha::new(fetched_sha)))
         );
     }
 
@@ -1122,7 +1123,7 @@ mod tests {
         let installed_version = SemanticVersion::new(1, 0, 0);
         let status = AutoUpdateStatus::Updated {
             binary_path: PathBuf::new(),
-            version: VersionCheckType::Sha("b".to_string()),
+            version: VersionCheckType::Sha(AppCommitSha::new("b".to_string())),
         };
         let fetched_sha = "b".to_string();
 
@@ -1145,7 +1146,7 @@ mod tests {
         let installed_version = SemanticVersion::new(1, 0, 0);
         let status = AutoUpdateStatus::Updated {
             binary_path: PathBuf::new(),
-            version: VersionCheckType::Sha("b".to_string()),
+            version: VersionCheckType::Sha(AppCommitSha::new("b".to_string())),
         };
         let fetched_sha = "c".to_string();
 
@@ -1159,7 +1160,7 @@ mod tests {
 
         assert_eq!(
             newer_version.unwrap(),
-            Some(VersionCheckType::Sha(fetched_sha))
+            Some(VersionCheckType::Sha(AppCommitSha::new(fetched_sha)))
         );
     }
 }

crates/feedback/src/system_specs.rs 🔗

@@ -30,7 +30,7 @@ impl SystemSpecs {
         let architecture = env::consts::ARCH;
         let commit_sha = match release_channel {
             ReleaseChannel::Dev | ReleaseChannel::Nightly => {
-                AppCommitSha::try_global(cx).map(|sha| sha.0.clone())
+                AppCommitSha::try_global(cx).map(|sha| sha.full().clone())
             }
             _ => None,
         };
@@ -70,9 +70,7 @@ impl SystemSpecs {
         let memory = system.total_memory();
         let architecture = env::consts::ARCH;
         let commit_sha = match release_channel {
-            ReleaseChannel::Dev | ReleaseChannel::Nightly => {
-                app_commit_sha.map(|sha| sha.0.clone())
-            }
+            ReleaseChannel::Dev | ReleaseChannel::Nightly => app_commit_sha.map(|sha| sha.full()),
             _ => None,
         };
 

crates/release_channel/src/lib.rs 🔗

@@ -35,14 +35,19 @@ pub fn app_identifier() -> &'static str {
 }
 
 /// The Git commit SHA that Zed was built at.
-#[derive(Clone)]
-pub struct AppCommitSha(pub String);
+#[derive(Clone, Eq, Debug, PartialEq)]
+pub struct AppCommitSha(String);
 
 struct GlobalAppCommitSha(AppCommitSha);
 
 impl Global for GlobalAppCommitSha {}
 
 impl AppCommitSha {
+    /// Creates a new [`AppCommitSha`].
+    pub fn new(sha: String) -> Self {
+        AppCommitSha(sha)
+    }
+
     /// Returns the global [`AppCommitSha`], if one is set.
     pub fn try_global(cx: &App) -> Option<AppCommitSha> {
         cx.try_global::<GlobalAppCommitSha>()
@@ -53,6 +58,16 @@ impl AppCommitSha {
     pub fn set_global(sha: AppCommitSha, cx: &mut App) {
         cx.set_global(GlobalAppCommitSha(sha))
     }
+
+    /// Returns the full commit SHA.
+    pub fn full(&self) -> String {
+        self.0.to_string()
+    }
+
+    /// Returns the short (7 character) commit SHA.
+    pub fn short(&self) -> String {
+        self.0.chars().take(7).collect()
+    }
 }
 
 struct GlobalAppVersion(SemanticVersion);

crates/remote/src/ssh_session.rs 🔗

@@ -1702,7 +1702,7 @@ impl SshRemoteConnection {
     ) -> Result<PathBuf> {
         let version_str = match release_channel {
             ReleaseChannel::Nightly => {
-                let commit = commit.map(|s| s.0.to_string()).unwrap_or_default();
+                let commit = commit.map(|s| s.full()).unwrap_or_default();
 
                 format!("{}-{}", version, commit)
             }

crates/zed/src/main.rs 🔗

@@ -217,7 +217,7 @@ fn main() {
 
     let app_version = AppVersion::load(env!("CARGO_PKG_VERSION"));
     let app_commit_sha =
-        option_env!("ZED_COMMIT_SHA").map(|commit_sha| AppCommitSha(commit_sha.to_string()));
+        option_env!("ZED_COMMIT_SHA").map(|commit_sha| AppCommitSha::new(commit_sha.to_string()));
 
     if args.system_specs {
         let system_specs = feedback::system_specs::SystemSpecs::new_stateless(

crates/zed/src/reliability.rs 🔗

@@ -65,7 +65,7 @@ pub fn init_panic_hook(
                     Some(commit_sha) => format!(
                         "https://github.com/zed-industries/zed/blob/{}/src/{}#L{} \
                         (may not be uploaded, line may be incorrect if files modified)\n",
-                        commit_sha.0,
+                        commit_sha.full(),
                         location.file(),
                         location.line()
                     ),
@@ -114,7 +114,7 @@ pub fn init_panic_hook(
                 line: location.line(),
             }),
             app_version: app_version.to_string(),
-            app_commit_sha: app_commit_sha.as_ref().map(|sha| sha.0.clone()),
+            app_commit_sha: app_commit_sha.as_ref().map(|sha| sha.full()),
             release_channel: RELEASE_CHANNEL.dev_name().into(),
             target: env!("TARGET").to_owned().into(),
             os_name: telemetry::os_name(),

crates/zed/src/zed.rs 🔗

@@ -940,7 +940,7 @@ fn about(
         ""
     };
     let message = format!("{release_channel} {version} {debug}");
-    let detail = AppCommitSha::try_global(cx).map(|sha| sha.0.clone());
+    let detail = AppCommitSha::try_global(cx).map(|sha| sha.full());
 
     let prompt = window.prompt(PromptLevel::Info, &message, detail.as_deref(), &["OK"], cx);
     cx.foreground_executor()