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