Skip to repository content326 lines · 10.1 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:03:19.828Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
lib.rs
1//! Provides constructs for the Zed app version and release channel.
2
3#![deny(missing_docs)]
4
5use std::{env, str::FromStr, sync::LazyLock};
6
7use gpui::{App, Global};
8use semver::Version;
9
10const ZED_DOCS_URL: &str = "https://zed.dev/docs";
11
12/// stable | dev | nightly | preview
13pub static RELEASE_CHANNEL_NAME: LazyLock<String> = LazyLock::new(|| {
14 if cfg!(debug_assertions) {
15 env::var("ZED_RELEASE_CHANNEL")
16 .unwrap_or_else(|_| include_str!("../../zed/RELEASE_CHANNEL").trim().to_string())
17 } else {
18 include_str!("../../zed/RELEASE_CHANNEL").trim().to_string()
19 }
20});
21
22#[doc(hidden)]
23pub static RELEASE_CHANNEL: LazyLock<ReleaseChannel> =
24 LazyLock::new(|| match ReleaseChannel::from_str(&RELEASE_CHANNEL_NAME) {
25 Ok(channel) => channel,
26 _ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
27 });
28
29/// The app identifier for the current release channel, Windows only.
30#[cfg(target_os = "windows")]
31pub fn app_identifier() -> &'static str {
32 match *RELEASE_CHANNEL {
33 ReleaseChannel::Dev => "OpenAgents-Omega-Dev",
34 ReleaseChannel::Nightly => "OpenAgents-Omega-Nightly",
35 ReleaseChannel::Preview => "OpenAgents-Omega-RC",
36 ReleaseChannel::Stable => "OpenAgents-Omega",
37 }
38}
39
40/// The Git commit SHA that Zed was built at.
41#[derive(Clone, Eq, Debug, PartialEq)]
42pub struct AppCommitSha(String);
43
44struct GlobalAppCommitSha(AppCommitSha);
45
46impl Global for GlobalAppCommitSha {}
47
48impl AppCommitSha {
49 /// Creates a new [`AppCommitSha`].
50 pub fn new(sha: String) -> Self {
51 AppCommitSha(sha)
52 }
53
54 /// Returns the global [`AppCommitSha`], if one is set.
55 pub fn try_global(cx: &App) -> Option<AppCommitSha> {
56 cx.try_global::<GlobalAppCommitSha>()
57 .map(|sha| sha.0.clone())
58 }
59
60 /// Sets the global [`AppCommitSha`].
61 pub fn set_global(sha: AppCommitSha, cx: &mut App) {
62 cx.set_global(GlobalAppCommitSha(sha))
63 }
64
65 /// Returns the full commit SHA.
66 pub fn full(&self) -> String {
67 self.0.to_string()
68 }
69
70 /// Returns the short (7 character) commit SHA.
71 pub fn short(&self) -> String {
72 self.0.chars().take(7).collect()
73 }
74}
75
76struct GlobalAppVersion(Version);
77
78impl Global for GlobalAppVersion {}
79
80/// The version of Zed.
81pub struct AppVersion;
82
83impl AppVersion {
84 /// Load the app version from env.
85 pub fn load(
86 pkg_version: &str,
87 build_id: Option<&str>,
88 commit_sha: Option<AppCommitSha>,
89 ) -> Version {
90 let mut version: Version = if let Ok(from_env) = env::var("ZED_APP_VERSION") {
91 from_env.parse().expect("invalid ZED_APP_VERSION")
92 } else {
93 pkg_version.parse().expect("invalid version in Cargo.toml")
94 };
95 let mut pre = String::from(RELEASE_CHANNEL.dev_name());
96
97 if let Some(build_id) = build_id {
98 pre.push('.');
99 pre.push_str(&build_id);
100 }
101
102 if let Some(sha) = commit_sha {
103 pre.push('.');
104 pre.push_str(&sha.0);
105 }
106 if let Ok(build) = semver::BuildMetadata::new(&pre) {
107 version.build = build;
108 }
109
110 version
111 }
112
113 /// Returns the global version number.
114 pub fn global(cx: &App) -> Version {
115 if cx.has_global::<GlobalAppVersion>() {
116 cx.global::<GlobalAppVersion>().0.clone()
117 } else {
118 Version::new(0, 0, 0)
119 }
120 }
121}
122
123/// A Zed release channel.
124#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
125pub enum ReleaseChannel {
126 /// The development release channel.
127 ///
128 /// Used for local debug builds of Zed.
129 #[default]
130 Dev,
131
132 /// The Nightly release channel.
133 Nightly,
134
135 /// The Preview release channel.
136 Preview,
137
138 /// The Stable release channel.
139 Stable,
140}
141
142struct GlobalReleaseChannel(ReleaseChannel);
143
144impl Global for GlobalReleaseChannel {}
145
146/// Initializes the release channel.
147pub fn init(app_version: Version, cx: &mut App) {
148 cx.set_global(GlobalAppVersion(app_version));
149 cx.set_global(GlobalReleaseChannel(*RELEASE_CHANNEL))
150}
151
152/// Initializes the release channel for tests that rely on fake release channel.
153pub fn init_test(app_version: Version, release_channel: ReleaseChannel, cx: &mut App) {
154 cx.set_global(GlobalAppVersion(app_version));
155 cx.set_global(GlobalReleaseChannel(release_channel))
156}
157
158/// Returns the Zed docs URL for the current release channel for the given
159/// `slug`.
160pub fn docs_url(slug: &str, cx: &App) -> String {
161 ReleaseChannel::try_global(cx)
162 .unwrap_or(*RELEASE_CHANNEL)
163 .docs_url(slug)
164}
165
166impl ReleaseChannel {
167 /// All release channels.
168 pub const ALL: [ReleaseChannel; 4] = [
169 ReleaseChannel::Dev,
170 ReleaseChannel::Nightly,
171 ReleaseChannel::Preview,
172 ReleaseChannel::Stable,
173 ];
174
175 /// Returns the global [`ReleaseChannel`].
176 pub fn global(cx: &App) -> Self {
177 cx.global::<GlobalReleaseChannel>().0
178 }
179
180 /// Returns the global [`ReleaseChannel`], if one is set.
181 pub fn try_global(cx: &App) -> Option<Self> {
182 cx.try_global::<GlobalReleaseChannel>()
183 .map(|channel| channel.0)
184 }
185
186 /// Returns whether we want to poll for updates for this [`ReleaseChannel`]
187 pub fn poll_for_updates(&self) -> bool {
188 !matches!(self, ReleaseChannel::Dev)
189 }
190
191 /// Returns the display name for this [`ReleaseChannel`].
192 pub fn display_name(&self) -> &'static str {
193 self.app_channel().display_name()
194 }
195
196 /// Returns the programmatic name for this [`ReleaseChannel`].
197 pub fn dev_name(&self) -> &'static str {
198 match self {
199 ReleaseChannel::Dev => "dev",
200 ReleaseChannel::Nightly => "nightly",
201 ReleaseChannel::Preview => "preview",
202 ReleaseChannel::Stable => "stable",
203 }
204 }
205
206 /// Returns the application ID that's used by Wayland as application ID
207 /// and WM_CLASS on X11.
208 /// This also has to match the bundle identifier on macOS.
209 pub fn app_id(&self) -> &'static str {
210 self.app_channel().app_id()
211 }
212
213 /// Returns the namespace prepended to credentials for this release channel.
214 pub fn credential_namespace(&self) -> &'static str {
215 self.app_channel().credential_namespace()
216 }
217
218 /// Returns the URL scheme registered by this release channel.
219 pub fn protocol_scheme(&self) -> &'static str {
220 self.app_channel().protocol_scheme()
221 }
222
223 /// Returns the query parameter for this [`ReleaseChannel`].
224 pub fn release_query_param(&self) -> Option<&'static str> {
225 match self {
226 Self::Dev => None,
227 Self::Nightly => Some("nightly=1"),
228 Self::Preview => Some("preview=1"),
229 Self::Stable => None,
230 }
231 }
232
233 /// Returns the Zed docs URL for this [`ReleaseChannel`] for the given
234 /// `slug`.
235 pub fn docs_url(&self, slug: &str) -> String {
236 let channel_path_segment = match self {
237 Self::Dev | Self::Nightly => Some("nightly"),
238 Self::Preview => Some("preview"),
239 Self::Stable => None,
240 };
241
242 match channel_path_segment {
243 Some(channel) if slug.is_empty() => format!("{ZED_DOCS_URL}/{channel}"),
244 Some(channel) => format!("{ZED_DOCS_URL}/{channel}/{slug}"),
245 None if slug.is_empty() => ZED_DOCS_URL.to_string(),
246 None => format!("{ZED_DOCS_URL}/{slug}"),
247 }
248 }
249
250 fn app_channel(&self) -> app_identity::AppChannel {
251 match self {
252 Self::Dev => app_identity::AppChannel::Dev,
253 Self::Nightly => app_identity::AppChannel::Nightly,
254 Self::Preview => app_identity::AppChannel::Rc,
255 Self::Stable => app_identity::AppChannel::Stable,
256 }
257 }
258}
259
260/// Error indicating that release channel string does not match any known release channel names.
261#[derive(Copy, Clone, Debug, Hash, PartialEq)]
262pub struct InvalidReleaseChannel;
263
264impl FromStr for ReleaseChannel {
265 type Err = InvalidReleaseChannel;
266
267 fn from_str(channel: &str) -> Result<Self, Self::Err> {
268 Ok(match channel {
269 "dev" => ReleaseChannel::Dev,
270 "nightly" => ReleaseChannel::Nightly,
271 "preview" => ReleaseChannel::Preview,
272 "stable" => ReleaseChannel::Stable,
273 _ => return Err(InvalidReleaseChannel),
274 })
275 }
276}
277
278#[cfg(test)]
279mod tests {
280 use std::collections::HashSet;
281
282 use super::ReleaseChannel;
283
284 #[test]
285 fn omega_channel_identities_are_unique() {
286 let display_names = ReleaseChannel::ALL.map(|channel| channel.display_name());
287 let app_ids = ReleaseChannel::ALL.map(|channel| channel.app_id());
288 let credential_namespaces =
289 ReleaseChannel::ALL.map(|channel| channel.credential_namespace());
290 let protocol_schemes = ReleaseChannel::ALL.map(|channel| channel.protocol_scheme());
291
292 for values in [
293 display_names.as_slice(),
294 app_ids.as_slice(),
295 credential_namespaces.as_slice(),
296 protocol_schemes.as_slice(),
297 ] {
298 assert_eq!(values.iter().copied().collect::<HashSet<_>>().len(), 4);
299 }
300
301 assert_eq!(ReleaseChannel::Preview.display_name(), "Omega RC");
302 assert_eq!(ReleaseChannel::Preview.app_id(), "com.openagents.omega.rc");
303 assert_eq!(ReleaseChannel::Preview.protocol_scheme(), "omega-rc");
304 }
305
306 #[test]
307 fn test_docs_url_for_release_channel() {
308 assert_eq!(
309 ReleaseChannel::Dev.docs_url("settings"),
310 "https://zed.dev/docs/nightly/settings"
311 );
312 assert_eq!(
313 ReleaseChannel::Nightly.docs_url("settings"),
314 "https://zed.dev/docs/nightly/settings"
315 );
316 assert_eq!(
317 ReleaseChannel::Preview.docs_url("settings"),
318 "https://zed.dev/docs/preview/settings"
319 );
320 assert_eq!(
321 ReleaseChannel::Stable.docs_url("settings"),
322 "https://zed.dev/docs/settings"
323 );
324 }
325}
326