From 110b9ab307cca1aae6eeca045865cef4f6d1a144 Mon Sep 17 00:00:00 2001
From: lucascouts <lucascs@protonmail.com>
Date: Thu, 8 Oct 2026 11:50:25 -0300
Subject: [PATCH] zed: the About window names Zeo's version

The About window read "Zeo 1.25.0" and "Version 1.25.0+zeo": the product name
came from display_name(), which 0021 makes return "Zeo", but both versions were
Zed's -- CARGO_PKG_VERSION in the heading, AppVersion in the row. Zeo has a
version of its own since 2026-10-05 (zeo/docs/RELEASING.md), and the package
already hands it to the build: src_compile exports RELEASE_VERSION=${PV}, which
until now only `zeo --version` read.

Under the Zeo channel, with RELEASE_VERSION set, the window now reads:

    Zeo 0.2.1                  the heading: Zeo's X.Y.Z, the part before `_p`
    Version  0.2.1_p20261008   the package version, snapshot date included
    Zed      1.25.0+zeo        AppVersion, unchanged

AppVersion is shown, not replaced, because it is what extensions check their
compatibility against; RELEASING.md said so as the reason the About kept Zed's
version, and moving Zed's version to a row of its own keeps that reason intact.
"Copy" carries the same three lines. Without RELEASE_VERSION -- a development
build, or any channel but Zeo -- the window is exactly upstream's.

A separate patch rather than part of 0021 or 0025: neither is about versions,
and this one reads an environment variable only the ebuild sets, which is worth
being able to find by its own name.

(0.2.3_p20261009): the version choice is `package_version_for` and `short_version`, out of
the About window's body so they can be tested.
---

diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs
index ad16b4c..081d193 100644
--- a/crates/zed/src/zed.rs
+++ b/crates/zed/src/zed.rs
@@ -1539,7 +1539,27 @@ fn initialize_pane(
     });
 }
 
+/// Zeo's own version, as the package passes it in RELEASE_VERSION (`0.2.1_p20261008`);
+/// `None` when it is unset or empty -- a development build -- or on another channel.
+fn package_version_for(
+    release_version: Option<&'static str>,
+    release_channel: ReleaseChannel,
+) -> Option<&'static str> {
+    release_version.filter(|version| !version.is_empty() && release_channel == ReleaseChannel::Zeo)
+}
+
+/// The `X.Y.Z` the About window's title line shows for a package version: the part
+/// before the snapshot suffix (`0.2.1_p20261008` -> `0.2.1`).
+fn short_version(package_version: &str) -> &str {
+    package_version.split('_').next().unwrap_or(package_version)
+}
+
 fn open_about_window(cx: &mut App) {
+    /// Zeo's own version, which the package passes in as RELEASE_VERSION.
+    fn zeo_package_version(release_channel: ReleaseChannel) -> Option<&'static str> {
+        package_version_for(option_env!("RELEASE_VERSION"), release_channel)
+    }
+
     fn about_window_icon(release_channel: ReleaseChannel) -> Arc<Image> {
         let bytes = match release_channel {
             ReleaseChannel::Dev => include_bytes!("../resources/app-icon-dev.png").as_slice(),
@@ -1564,14 +1584,26 @@ fn open_about_window(cx: &mut App) {
         message: SharedString,
         commit: Option<SharedString>,
         full_version: SharedString,
+        upstream_version: Option<SharedString>,
     }
 
     impl AboutWindow {
         fn new(cx: &mut Context<Self>) -> Self {
             let release_channel = ReleaseChannel::global(cx);
             let release_channel_name = release_channel.display_name();
-            let full_version: SharedString = AppVersion::global(cx).to_string().into();
-            let version = env!("CARGO_PKG_VERSION");
+            let app_version: SharedString = AppVersion::global(cx).to_string().into();
+            // Zeo's version names this build. Zed's keeps a row of its own rather
+            // than being replaced, because AppVersion is what extensions check
+            // compatibility against.
+            let package_version = zeo_package_version(release_channel);
+            let version = match package_version {
+                Some(package_version) => short_version(package_version),
+                None => env!("CARGO_PKG_VERSION"),
+            };
+            let (full_version, upstream_version) = match package_version {
+                Some(package_version) => (package_version.into(), Some(app_version)),
+                None => (app_version, None),
+            };
 
             let debug = if cfg!(debug_assertions) {
                 "(debug)"
@@ -1592,11 +1624,12 @@ fn open_about_window(cx: &mut App) {
                 message,
                 commit,
                 full_version,
+                upstream_version,
             }
         }
 
         fn copy_details(&self, window: &mut Window, cx: &mut Context<Self>) {
-            let content = match self.commit.as_ref() {
+            let mut content = match self.commit.as_ref() {
                 Some(commit) => {
                     format!(
                         "{}\nCommit: {}\nVersion: {}",
@@ -1605,6 +1638,9 @@ fn open_about_window(cx: &mut App) {
                 }
                 None => format!("{}\nVersion: {}", self.message, self.full_version),
             };
+            if let Some(upstream_version) = &self.upstream_version {
+                content.push_str(&format!("\nZed: {upstream_version}"));
+            }
             cx.write_to_clipboard(ClipboardItem::new_string(content));
             window.remove_window();
         }
@@ -1651,7 +1687,15 @@ fn open_about_window(cx: &mut App) {
                                     .color(Color::Muted)
                                     .size(LabelSize::XSmall),
                             )
-                            .child(Label::new(self.full_version.clone()).size(LabelSize::Small)),
+                            .child(Label::new(self.full_version.clone()).size(LabelSize::Small))
+                            .when_some(self.upstream_version.clone(), |this, upstream_version| {
+                                this.child(
+                                    Label::new("Zed")
+                                        .color(Color::Muted)
+                                        .size(LabelSize::XSmall),
+                                )
+                                .child(Label::new(upstream_version).size(LabelSize::Small))
+                            }),
                     )
                     .child(
                         h_flex()
@@ -1724,9 +1768,16 @@ fn open_about_window(cx: &mut App) {
         return;
     }
 
+    // The window does not resize, so the row naming Zed's version makes room
+    // for itself; without it the OK and Copy buttons fall below the edge.
+    let zed_row_height = if zeo_package_version(ReleaseChannel::global(cx)).is_some() {
+        52.
+    } else {
+        0.
+    };
     let window_size = Size {
         width: px(440.),
-        height: px(300.),
+        height: px(300. + zed_row_height),
     };
 
     cx.open_window(
@@ -6216,6 +6267,27 @@ mod tests {
 
     /// Checks that action namespaces are the expected set. The purpose of this is to prevent typos
     /// and let you know when introducing a new namespace.
+    /// 0047: the About window shows Zeo's package version only on the Zeo channel and
+    /// only when the package set one, and titles it by the part before the snapshot.
+    #[test]
+    fn test_about_window_package_version() {
+        use super::{package_version_for, short_version};
+        assert_eq!(
+            package_version_for(Some("0.2.1_p20261008"), ReleaseChannel::Zeo),
+            Some("0.2.1_p20261008")
+        );
+        assert_eq!(package_version_for(Some(""), ReleaseChannel::Zeo), None);
+        assert_eq!(package_version_for(None, ReleaseChannel::Zeo), None);
+        assert_eq!(
+            package_version_for(Some("0.2.1_p20261008"), ReleaseChannel::Stable),
+            None,
+            "another channel keeps Zed's version"
+        );
+        assert_eq!(short_version("0.2.1_p20261008"), "0.2.1");
+        assert_eq!(short_version("0.2.1_p20261008-r1"), "0.2.1");
+        assert_eq!(short_version("0.2.1"), "0.2.1");
+    }
+
     #[gpui::test]
     async fn test_action_namespaces(cx: &mut gpui::TestAppContext) {
         use itertools::Itertools;
