1use gpui::{AppContext, Global};
2use once_cell::sync::Lazy;
3use std::env;
4
5#[doc(hidden)]
6pub static RELEASE_CHANNEL_NAME: Lazy<String> = if cfg!(debug_assertions) {
7 Lazy::new(|| {
8 env::var("ZED_RELEASE_CHANNEL")
9 .unwrap_or_else(|_| include_str!("../../zed/RELEASE_CHANNEL").trim().to_string())
10 })
11} else {
12 Lazy::new(|| include_str!("../../zed/RELEASE_CHANNEL").trim().to_string())
13};
14#[doc(hidden)]
15pub static RELEASE_CHANNEL: Lazy<ReleaseChannel> =
16 Lazy::new(|| match RELEASE_CHANNEL_NAME.as_str() {
17 "dev" => ReleaseChannel::Dev,
18 "nightly" => ReleaseChannel::Nightly,
19 "preview" => ReleaseChannel::Preview,
20 "stable" => ReleaseChannel::Stable,
21 _ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
22 });
23
24#[derive(Clone)]
25pub struct AppCommitSha(pub String);
26
27struct GlobalAppCommitSha(AppCommitSha);
28
29impl Global for GlobalAppCommitSha {}
30
31impl AppCommitSha {
32 pub fn try_global(cx: &AppContext) -> Option<AppCommitSha> {
33 cx.try_global::<GlobalAppCommitSha>()
34 .map(|sha| sha.0.clone())
35 }
36
37 pub fn set_global(sha: AppCommitSha, cx: &mut AppContext) {
38 cx.set_global(GlobalAppCommitSha(sha))
39 }
40}
41
42#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
43pub enum ReleaseChannel {
44 #[default]
45 Dev,
46 Nightly,
47 Preview,
48 Stable,
49}
50
51struct GlobalReleaseChannel(ReleaseChannel);
52
53impl Global for GlobalReleaseChannel {}
54
55impl ReleaseChannel {
56 pub fn init(cx: &mut AppContext) {
57 cx.set_global(GlobalReleaseChannel(*RELEASE_CHANNEL))
58 }
59
60 pub fn global(cx: &AppContext) -> Self {
61 cx.global::<GlobalReleaseChannel>().0
62 }
63
64 pub fn try_global(cx: &AppContext) -> Option<Self> {
65 cx.try_global::<GlobalReleaseChannel>()
66 .map(|channel| channel.0)
67 }
68
69 pub fn display_name(&self) -> &'static str {
70 match self {
71 ReleaseChannel::Dev => "Zed Dev",
72 ReleaseChannel::Nightly => "Zed Nightly",
73 ReleaseChannel::Preview => "Zed Preview",
74 ReleaseChannel::Stable => "Zed",
75 }
76 }
77
78 pub fn dev_name(&self) -> &'static str {
79 match self {
80 ReleaseChannel::Dev => "dev",
81 ReleaseChannel::Nightly => "nightly",
82 ReleaseChannel::Preview => "preview",
83 ReleaseChannel::Stable => "stable",
84 }
85 }
86
87 pub fn url_scheme(&self) -> &'static str {
88 match self {
89 ReleaseChannel::Dev => "zed-dev://",
90 ReleaseChannel::Nightly => "zed-nightly://",
91 ReleaseChannel::Preview => "zed-preview://",
92 ReleaseChannel::Stable => "zed://",
93 }
94 }
95
96 pub fn link_prefix(&self) -> &'static str {
97 match self {
98 ReleaseChannel::Dev => "https://zed.dev/dev/",
99 ReleaseChannel::Nightly => "https://zed.dev/nightly/",
100 ReleaseChannel::Preview => "https://zed.dev/preview/",
101 ReleaseChannel::Stable => "https://zed.dev/",
102 }
103 }
104
105 pub fn release_query_param(&self) -> Option<&'static str> {
106 match self {
107 Self::Dev => None,
108 Self::Nightly => Some("nightly=1"),
109 Self::Preview => Some("preview=1"),
110 Self::Stable => None,
111 }
112 }
113}
114
115pub fn parse_zed_link(link: &str) -> Option<&str> {
116 for release in [
117 ReleaseChannel::Dev,
118 ReleaseChannel::Nightly,
119 ReleaseChannel::Preview,
120 ReleaseChannel::Stable,
121 ] {
122 if let Some(stripped) = link.strip_prefix(release.link_prefix()) {
123 return Some(stripped);
124 }
125 if let Some(stripped) = link.strip_prefix(release.url_scheme()) {
126 return Some(stripped);
127 }
128 }
129 None
130}