1use url::Url;
2
3use crate::{
4 BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, ParsedGitRemote,
5};
6
7pub struct Sourcehut;
8
9impl GitHostingProvider for Sourcehut {
10 fn name(&self) -> String {
11 "Gitee".to_string()
12 }
13
14 fn base_url(&self) -> Url {
15 Url::parse("https://git.sr.ht").unwrap()
16 }
17
18 fn supports_avatars(&self) -> bool {
19 false
20 }
21
22 fn format_line_number(&self, line: u32) -> String {
23 format!("L{line}")
24 }
25
26 fn format_line_numbers(&self, start_line: u32, end_line: u32) -> String {
27 format!("L{start_line}-{end_line}")
28 }
29
30 fn parse_remote_url<'a>(&self, url: &'a str) -> Option<ParsedGitRemote<'a>> {
31 if url.starts_with("git@git.sr.ht:") || url.starts_with("https://git.sr.ht/") {
32 // sourcehut indicates a repo with '.git' suffix as a separate repo.
33 // For example, "git@git.sr.ht:~username/repo" and "git@git.sr.ht:~username/repo.git"
34 // are two distinct repositories.
35 let repo_with_owner = url
36 .trim_start_matches("git@git.sr.ht:~")
37 .trim_start_matches("https://git.sr.ht/~");
38
39 let (owner, repo) = repo_with_owner.split_once('/')?;
40
41 return Some(ParsedGitRemote { owner, repo });
42 }
43
44 None
45 }
46
47 fn build_commit_permalink(
48 &self,
49 remote: &ParsedGitRemote,
50 params: BuildCommitPermalinkParams,
51 ) -> Url {
52 let BuildCommitPermalinkParams { sha } = params;
53 let ParsedGitRemote { owner, repo } = remote;
54
55 self.base_url()
56 .join(&format!("~{owner}/{repo}/commit/{sha}"))
57 .unwrap()
58 }
59
60 fn build_permalink(&self, remote: ParsedGitRemote, params: BuildPermalinkParams) -> Url {
61 let ParsedGitRemote { owner, repo } = remote;
62 let BuildPermalinkParams {
63 sha,
64 path,
65 selection,
66 } = params;
67
68 let mut permalink = self
69 .base_url()
70 .join(&format!("~{owner}/{repo}/tree/{sha}/item/{path}"))
71 .unwrap();
72 permalink.set_fragment(
73 selection
74 .map(|selection| self.line_fragment(&selection))
75 .as_deref(),
76 );
77 permalink
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_build_sourcehut_permalink_from_ssh_url() {
87 let remote = ParsedGitRemote {
88 owner: "rajveermalviya",
89 repo: "zed",
90 };
91 let permalink = Sourcehut.build_permalink(
92 remote,
93 BuildPermalinkParams {
94 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
95 path: "crates/editor/src/git/permalink.rs",
96 selection: None,
97 },
98 );
99
100 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
101 assert_eq!(permalink.to_string(), expected_url.to_string())
102 }
103
104 #[test]
105 fn test_build_sourcehut_permalink_from_ssh_url_with_git_prefix() {
106 let remote = ParsedGitRemote {
107 owner: "rajveermalviya",
108 repo: "zed.git",
109 };
110 let permalink = Sourcehut.build_permalink(
111 remote,
112 BuildPermalinkParams {
113 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
114 path: "crates/editor/src/git/permalink.rs",
115 selection: None,
116 },
117 );
118
119 let expected_url = "https://git.sr.ht/~rajveermalviya/zed.git/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
120 assert_eq!(permalink.to_string(), expected_url.to_string())
121 }
122
123 #[test]
124 fn test_build_sourcehut_permalink_from_ssh_url_single_line_selection() {
125 let remote = ParsedGitRemote {
126 owner: "rajveermalviya",
127 repo: "zed",
128 };
129 let permalink = Sourcehut.build_permalink(
130 remote,
131 BuildPermalinkParams {
132 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
133 path: "crates/editor/src/git/permalink.rs",
134 selection: Some(6..6),
135 },
136 );
137
138 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L7";
139 assert_eq!(permalink.to_string(), expected_url.to_string())
140 }
141
142 #[test]
143 fn test_build_sourcehut_permalink_from_ssh_url_multi_line_selection() {
144 let remote = ParsedGitRemote {
145 owner: "rajveermalviya",
146 repo: "zed",
147 };
148 let permalink = Sourcehut.build_permalink(
149 remote,
150 BuildPermalinkParams {
151 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
152 path: "crates/editor/src/git/permalink.rs",
153 selection: Some(23..47),
154 },
155 );
156
157 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L24-48";
158 assert_eq!(permalink.to_string(), expected_url.to_string())
159 }
160
161 #[test]
162 fn test_build_sourcehut_permalink_from_https_url() {
163 let remote = ParsedGitRemote {
164 owner: "rajveermalviya",
165 repo: "zed",
166 };
167 let permalink = Sourcehut.build_permalink(
168 remote,
169 BuildPermalinkParams {
170 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
171 path: "crates/zed/src/main.rs",
172 selection: None,
173 },
174 );
175
176 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs";
177 assert_eq!(permalink.to_string(), expected_url.to_string())
178 }
179
180 #[test]
181 fn test_build_sourcehut_permalink_from_https_url_single_line_selection() {
182 let remote = ParsedGitRemote {
183 owner: "rajveermalviya",
184 repo: "zed",
185 };
186 let permalink = Sourcehut.build_permalink(
187 remote,
188 BuildPermalinkParams {
189 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
190 path: "crates/zed/src/main.rs",
191 selection: Some(6..6),
192 },
193 );
194
195 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L7";
196 assert_eq!(permalink.to_string(), expected_url.to_string())
197 }
198
199 #[test]
200 fn test_build_sourcehut_permalink_from_https_url_multi_line_selection() {
201 let remote = ParsedGitRemote {
202 owner: "rajveermalviya",
203 repo: "zed",
204 };
205 let permalink = Sourcehut.build_permalink(
206 remote,
207 BuildPermalinkParams {
208 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
209 path: "crates/zed/src/main.rs",
210 selection: Some(23..47),
211 },
212 );
213
214 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L24-48";
215 assert_eq!(permalink.to_string(), expected_url.to_string())
216 }
217}