1use std::ops::Range;
2
3use anyhow::{anyhow, Result};
4use language::Point;
5use url::Url;
6
7enum GitHostingProvider {
8 Github,
9 Gitlab,
10 Gitee,
11 Bitbucket,
12 Sourcehut,
13 Codeberg,
14}
15
16impl GitHostingProvider {
17 fn base_url(&self) -> Url {
18 let base_url = match self {
19 Self::Github => "https://github.com",
20 Self::Gitlab => "https://gitlab.com",
21 Self::Gitee => "https://gitee.com",
22 Self::Bitbucket => "https://bitbucket.org",
23 Self::Sourcehut => "https://git.sr.ht",
24 Self::Codeberg => "https://codeberg.org",
25 };
26
27 Url::parse(&base_url).unwrap()
28 }
29
30 /// Returns the fragment portion of the URL for the selected lines in
31 /// the representation the [`GitHostingProvider`] expects.
32 fn line_fragment(&self, selection: &Range<Point>) -> String {
33 if selection.start.row == selection.end.row {
34 let line = selection.start.row + 1;
35
36 match self {
37 Self::Github | Self::Gitlab | Self::Gitee | Self::Sourcehut | Self::Codeberg => {
38 format!("L{}", line)
39 }
40 Self::Bitbucket => format!("lines-{}", line),
41 }
42 } else {
43 let start_line = selection.start.row + 1;
44 let end_line = selection.end.row + 1;
45
46 match self {
47 Self::Github | Self::Codeberg => format!("L{}-L{}", start_line, end_line),
48 Self::Gitlab | Self::Gitee | Self::Sourcehut => {
49 format!("L{}-{}", start_line, end_line)
50 }
51 Self::Bitbucket => format!("lines-{}:{}", start_line, end_line),
52 }
53 }
54 }
55}
56
57pub struct BuildPermalinkParams<'a> {
58 pub remote_url: &'a str,
59 pub sha: &'a str,
60 pub path: &'a str,
61 pub selection: Option<Range<Point>>,
62}
63
64pub fn build_permalink(params: BuildPermalinkParams) -> Result<Url> {
65 let BuildPermalinkParams {
66 remote_url,
67 sha,
68 path,
69 selection,
70 } = params;
71
72 let ParsedGitRemote {
73 provider,
74 owner,
75 repo,
76 } = parse_git_remote_url(remote_url)
77 .ok_or_else(|| anyhow!("failed to parse Git remote URL"))?;
78
79 let path = match provider {
80 GitHostingProvider::Github => format!("{owner}/{repo}/blob/{sha}/{path}"),
81 GitHostingProvider::Gitlab => format!("{owner}/{repo}/-/blob/{sha}/{path}"),
82 GitHostingProvider::Gitee => format!("{owner}/{repo}/blob/{sha}/{path}"),
83 GitHostingProvider::Bitbucket => format!("{owner}/{repo}/src/{sha}/{path}"),
84 GitHostingProvider::Sourcehut => format!("~{owner}/{repo}/tree/{sha}/item/{path}"),
85 GitHostingProvider::Codeberg => format!("{owner}/{repo}/src/commit/{sha}/{path}"),
86 };
87 let line_fragment = selection.map(|selection| provider.line_fragment(&selection));
88
89 let mut permalink = provider.base_url().join(&path).unwrap();
90 permalink.set_fragment(line_fragment.as_deref());
91
92 Ok(permalink)
93}
94
95struct ParsedGitRemote<'a> {
96 pub provider: GitHostingProvider,
97 pub owner: &'a str,
98 pub repo: &'a str,
99}
100
101fn parse_git_remote_url(url: &str) -> Option<ParsedGitRemote> {
102 if url.starts_with("git@github.com:") || url.starts_with("https://github.com/") {
103 let repo_with_owner = url
104 .trim_start_matches("git@github.com:")
105 .trim_start_matches("https://github.com/")
106 .trim_end_matches(".git");
107
108 let (owner, repo) = repo_with_owner.split_once("/")?;
109
110 return Some(ParsedGitRemote {
111 provider: GitHostingProvider::Github,
112 owner,
113 repo,
114 });
115 }
116
117 if url.starts_with("git@gitlab.com:") || url.starts_with("https://gitlab.com/") {
118 let repo_with_owner = url
119 .trim_start_matches("git@gitlab.com:")
120 .trim_start_matches("https://gitlab.com/")
121 .trim_end_matches(".git");
122
123 let (owner, repo) = repo_with_owner.split_once("/")?;
124
125 return Some(ParsedGitRemote {
126 provider: GitHostingProvider::Gitlab,
127 owner,
128 repo,
129 });
130 }
131
132 if url.starts_with("git@gitee.com:") || url.starts_with("https://gitee.com/") {
133 let repo_with_owner = url
134 .trim_start_matches("git@gitee.com:")
135 .trim_start_matches("https://gitee.com/")
136 .trim_end_matches(".git");
137
138 let (owner, repo) = repo_with_owner.split_once("/")?;
139
140 return Some(ParsedGitRemote {
141 provider: GitHostingProvider::Gitee,
142 owner,
143 repo,
144 });
145 }
146
147 if url.contains("bitbucket.org") {
148 let (_, repo_with_owner) = url.trim_end_matches(".git").split_once("bitbucket.org")?;
149 let (owner, repo) = repo_with_owner
150 .trim_start_matches("/")
151 .trim_start_matches(":")
152 .split_once("/")?;
153
154 return Some(ParsedGitRemote {
155 provider: GitHostingProvider::Bitbucket,
156 owner,
157 repo,
158 });
159 }
160
161 if url.starts_with("git@git.sr.ht:") || url.starts_with("https://git.sr.ht/") {
162 // sourcehut indicates a repo with '.git' suffix as a separate repo.
163 // For example, "git@git.sr.ht:~username/repo" and "git@git.sr.ht:~username/repo.git"
164 // are two distinct repositories.
165 let repo_with_owner = url
166 .trim_start_matches("git@git.sr.ht:~")
167 .trim_start_matches("https://git.sr.ht/~");
168
169 let (owner, repo) = repo_with_owner.split_once("/")?;
170
171 return Some(ParsedGitRemote {
172 provider: GitHostingProvider::Sourcehut,
173 owner,
174 repo,
175 });
176 }
177
178 if url.starts_with("git@codeberg.org:") || url.starts_with("https://codeberg.org/") {
179 let repo_with_owner = url
180 .trim_start_matches("git@codeberg.org:")
181 .trim_start_matches("https://codeberg.org/")
182 .trim_end_matches(".git");
183
184 let (owner, repo) = repo_with_owner.split_once("/")?;
185
186 return Some(ParsedGitRemote {
187 provider: GitHostingProvider::Codeberg,
188 owner,
189 repo,
190 });
191 }
192
193 None
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199
200 #[test]
201 fn test_build_github_permalink_from_ssh_url() {
202 let permalink = build_permalink(BuildPermalinkParams {
203 remote_url: "git@github.com:zed-industries/zed.git",
204 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
205 path: "crates/editor/src/git/permalink.rs",
206 selection: None,
207 })
208 .unwrap();
209
210 let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
211 assert_eq!(permalink.to_string(), expected_url.to_string())
212 }
213
214 #[test]
215 fn test_build_github_permalink_from_ssh_url_single_line_selection() {
216 let permalink = build_permalink(BuildPermalinkParams {
217 remote_url: "git@github.com:zed-industries/zed.git",
218 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
219 path: "crates/editor/src/git/permalink.rs",
220 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
221 })
222 .unwrap();
223
224 let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
225 assert_eq!(permalink.to_string(), expected_url.to_string())
226 }
227
228 #[test]
229 fn test_build_github_permalink_from_ssh_url_multi_line_selection() {
230 let permalink = build_permalink(BuildPermalinkParams {
231 remote_url: "git@github.com:zed-industries/zed.git",
232 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
233 path: "crates/editor/src/git/permalink.rs",
234 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
235 })
236 .unwrap();
237
238 let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-L48";
239 assert_eq!(permalink.to_string(), expected_url.to_string())
240 }
241
242 #[test]
243 fn test_build_github_permalink_from_https_url() {
244 let permalink = build_permalink(BuildPermalinkParams {
245 remote_url: "https://github.com/zed-industries/zed.git",
246 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
247 path: "crates/zed/src/main.rs",
248 selection: None,
249 })
250 .unwrap();
251
252 let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
253 assert_eq!(permalink.to_string(), expected_url.to_string())
254 }
255
256 #[test]
257 fn test_build_github_permalink_from_https_url_single_line_selection() {
258 let permalink = build_permalink(BuildPermalinkParams {
259 remote_url: "https://github.com/zed-industries/zed.git",
260 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
261 path: "crates/zed/src/main.rs",
262 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
263 })
264 .unwrap();
265
266 let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
267 assert_eq!(permalink.to_string(), expected_url.to_string())
268 }
269
270 #[test]
271 fn test_build_github_permalink_from_https_url_multi_line_selection() {
272 let permalink = build_permalink(BuildPermalinkParams {
273 remote_url: "https://github.com/zed-industries/zed.git",
274 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
275 path: "crates/zed/src/main.rs",
276 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
277 })
278 .unwrap();
279
280 let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-L48";
281 assert_eq!(permalink.to_string(), expected_url.to_string())
282 }
283
284 #[test]
285 fn test_build_gitlab_permalink_from_ssh_url() {
286 let permalink = build_permalink(BuildPermalinkParams {
287 remote_url: "git@gitlab.com:zed-industries/zed.git",
288 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
289 path: "crates/editor/src/git/permalink.rs",
290 selection: None,
291 })
292 .unwrap();
293
294 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
295 assert_eq!(permalink.to_string(), expected_url.to_string())
296 }
297
298 #[test]
299 fn test_build_gitlab_permalink_from_ssh_url_single_line_selection() {
300 let permalink = build_permalink(BuildPermalinkParams {
301 remote_url: "git@gitlab.com:zed-industries/zed.git",
302 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
303 path: "crates/editor/src/git/permalink.rs",
304 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
305 })
306 .unwrap();
307
308 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
309 assert_eq!(permalink.to_string(), expected_url.to_string())
310 }
311
312 #[test]
313 fn test_build_gitlab_permalink_from_ssh_url_multi_line_selection() {
314 let permalink = build_permalink(BuildPermalinkParams {
315 remote_url: "git@gitlab.com:zed-industries/zed.git",
316 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
317 path: "crates/editor/src/git/permalink.rs",
318 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
319 })
320 .unwrap();
321
322 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-48";
323 assert_eq!(permalink.to_string(), expected_url.to_string())
324 }
325
326 #[test]
327 fn test_build_gitlab_permalink_from_https_url() {
328 let permalink = build_permalink(BuildPermalinkParams {
329 remote_url: "https://gitlab.com/zed-industries/zed.git",
330 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
331 path: "crates/zed/src/main.rs",
332 selection: None,
333 })
334 .unwrap();
335
336 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
337 assert_eq!(permalink.to_string(), expected_url.to_string())
338 }
339
340 #[test]
341 fn test_build_gitlab_permalink_from_https_url_single_line_selection() {
342 let permalink = build_permalink(BuildPermalinkParams {
343 remote_url: "https://gitlab.com/zed-industries/zed.git",
344 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
345 path: "crates/zed/src/main.rs",
346 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
347 })
348 .unwrap();
349
350 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
351 assert_eq!(permalink.to_string(), expected_url.to_string())
352 }
353
354 #[test]
355 fn test_build_gitlab_permalink_from_https_url_multi_line_selection() {
356 let permalink = build_permalink(BuildPermalinkParams {
357 remote_url: "https://gitlab.com/zed-industries/zed.git",
358 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
359 path: "crates/zed/src/main.rs",
360 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
361 })
362 .unwrap();
363
364 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-48";
365 assert_eq!(permalink.to_string(), expected_url.to_string())
366 }
367
368 #[test]
369 fn test_build_gitee_permalink_from_ssh_url() {
370 let permalink = build_permalink(BuildPermalinkParams {
371 remote_url: "git@gitee.com:libkitten/zed.git",
372 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
373 path: "crates/editor/src/git/permalink.rs",
374 selection: None,
375 })
376 .unwrap();
377
378 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs";
379 assert_eq!(permalink.to_string(), expected_url.to_string())
380 }
381
382 #[test]
383 fn test_build_gitee_permalink_from_ssh_url_single_line_selection() {
384 let permalink = build_permalink(BuildPermalinkParams {
385 remote_url: "git@gitee.com:libkitten/zed.git",
386 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
387 path: "crates/editor/src/git/permalink.rs",
388 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
389 })
390 .unwrap();
391
392 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L7";
393 assert_eq!(permalink.to_string(), expected_url.to_string())
394 }
395
396 #[test]
397 fn test_build_gitee_permalink_from_ssh_url_multi_line_selection() {
398 let permalink = build_permalink(BuildPermalinkParams {
399 remote_url: "git@gitee.com:libkitten/zed.git",
400 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
401 path: "crates/editor/src/git/permalink.rs",
402 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
403 })
404 .unwrap();
405
406 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L24-48";
407 assert_eq!(permalink.to_string(), expected_url.to_string())
408 }
409
410 #[test]
411 fn test_build_gitee_permalink_from_https_url() {
412 let permalink = build_permalink(BuildPermalinkParams {
413 remote_url: "https://gitee.com/libkitten/zed.git",
414 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
415 path: "crates/zed/src/main.rs",
416 selection: None,
417 })
418 .unwrap();
419
420 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs";
421 assert_eq!(permalink.to_string(), expected_url.to_string())
422 }
423
424 #[test]
425 fn test_build_gitee_permalink_from_https_url_single_line_selection() {
426 let permalink = build_permalink(BuildPermalinkParams {
427 remote_url: "https://gitee.com/libkitten/zed.git",
428 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
429 path: "crates/zed/src/main.rs",
430 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
431 })
432 .unwrap();
433
434 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs#L7";
435 assert_eq!(permalink.to_string(), expected_url.to_string())
436 }
437
438 #[test]
439 fn test_build_gitee_permalink_from_https_url_multi_line_selection() {
440 let permalink = build_permalink(BuildPermalinkParams {
441 remote_url: "https://gitee.com/libkitten/zed.git",
442 sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
443 path: "crates/zed/src/main.rs",
444 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
445 })
446 .unwrap();
447 let expected_url = "https://gitee.com/libkitten/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/zed/src/main.rs#L24-48";
448 assert_eq!(permalink.to_string(), expected_url.to_string())
449 }
450
451 #[test]
452 fn test_parse_git_remote_url_bitbucket_https_with_username() {
453 let url = "https://thorstenballzed@bitbucket.org/thorstenzed/testingrepo.git";
454 let parsed = parse_git_remote_url(url).unwrap();
455 assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
456 assert_eq!(parsed.owner, "thorstenzed");
457 assert_eq!(parsed.repo, "testingrepo");
458 }
459
460 #[test]
461 fn test_parse_git_remote_url_bitbucket_https_without_username() {
462 let url = "https://bitbucket.org/thorstenzed/testingrepo.git";
463 let parsed = parse_git_remote_url(url).unwrap();
464 assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
465 assert_eq!(parsed.owner, "thorstenzed");
466 assert_eq!(parsed.repo, "testingrepo");
467 }
468
469 #[test]
470 fn test_parse_git_remote_url_bitbucket_git() {
471 let url = "git@bitbucket.org:thorstenzed/testingrepo.git";
472 let parsed = parse_git_remote_url(url).unwrap();
473 assert!(matches!(parsed.provider, GitHostingProvider::Bitbucket));
474 assert_eq!(parsed.owner, "thorstenzed");
475 assert_eq!(parsed.repo, "testingrepo");
476 }
477
478 #[test]
479 fn test_build_bitbucket_permalink_from_ssh_url() {
480 let permalink = build_permalink(BuildPermalinkParams {
481 remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
482 sha: "f00b4r",
483 path: "main.rs",
484 selection: None,
485 })
486 .unwrap();
487
488 let expected_url = "https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs";
489 assert_eq!(permalink.to_string(), expected_url.to_string())
490 }
491
492 #[test]
493 fn test_build_bitbucket_permalink_from_ssh_url_single_line_selection() {
494 let permalink = build_permalink(BuildPermalinkParams {
495 remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
496 sha: "f00b4r",
497 path: "main.rs",
498 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
499 })
500 .unwrap();
501
502 let expected_url =
503 "https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs#lines-7";
504 assert_eq!(permalink.to_string(), expected_url.to_string())
505 }
506
507 #[test]
508 fn test_build_bitbucket_permalink_from_ssh_url_multi_line_selection() {
509 let permalink = build_permalink(BuildPermalinkParams {
510 remote_url: "git@bitbucket.org:thorstenzed/testingrepo.git",
511 sha: "f00b4r",
512 path: "main.rs",
513 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
514 })
515 .unwrap();
516
517 let expected_url =
518 "https://bitbucket.org/thorstenzed/testingrepo/src/f00b4r/main.rs#lines-24:48";
519 assert_eq!(permalink.to_string(), expected_url.to_string())
520 }
521
522 #[test]
523 fn test_build_sourcehut_permalink_from_ssh_url() {
524 let permalink = build_permalink(BuildPermalinkParams {
525 remote_url: "git@git.sr.ht:~rajveermalviya/zed",
526 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
527 path: "crates/editor/src/git/permalink.rs",
528 selection: None,
529 })
530 .unwrap();
531
532 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
533 assert_eq!(permalink.to_string(), expected_url.to_string())
534 }
535
536 #[test]
537 fn test_build_sourcehut_permalink_from_ssh_url_with_git_prefix() {
538 let permalink = build_permalink(BuildPermalinkParams {
539 remote_url: "git@git.sr.ht:~rajveermalviya/zed.git",
540 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
541 path: "crates/editor/src/git/permalink.rs",
542 selection: None,
543 })
544 .unwrap();
545
546 let expected_url = "https://git.sr.ht/~rajveermalviya/zed.git/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
547 assert_eq!(permalink.to_string(), expected_url.to_string())
548 }
549
550 #[test]
551 fn test_build_sourcehut_permalink_from_ssh_url_single_line_selection() {
552 let permalink = build_permalink(BuildPermalinkParams {
553 remote_url: "git@git.sr.ht:~rajveermalviya/zed",
554 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
555 path: "crates/editor/src/git/permalink.rs",
556 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
557 })
558 .unwrap();
559
560 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L7";
561 assert_eq!(permalink.to_string(), expected_url.to_string())
562 }
563
564 #[test]
565 fn test_build_sourcehut_permalink_from_ssh_url_multi_line_selection() {
566 let permalink = build_permalink(BuildPermalinkParams {
567 remote_url: "git@git.sr.ht:~rajveermalviya/zed",
568 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
569 path: "crates/editor/src/git/permalink.rs",
570 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
571 })
572 .unwrap();
573
574 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L24-48";
575 assert_eq!(permalink.to_string(), expected_url.to_string())
576 }
577
578 #[test]
579 fn test_build_sourcehut_permalink_from_https_url() {
580 let permalink = build_permalink(BuildPermalinkParams {
581 remote_url: "https://git.sr.ht/~rajveermalviya/zed",
582 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
583 path: "crates/zed/src/main.rs",
584 selection: None,
585 })
586 .unwrap();
587
588 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs";
589 assert_eq!(permalink.to_string(), expected_url.to_string())
590 }
591
592 #[test]
593 fn test_build_sourcehut_permalink_from_https_url_single_line_selection() {
594 let permalink = build_permalink(BuildPermalinkParams {
595 remote_url: "https://git.sr.ht/~rajveermalviya/zed",
596 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
597 path: "crates/zed/src/main.rs",
598 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
599 })
600 .unwrap();
601
602 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L7";
603 assert_eq!(permalink.to_string(), expected_url.to_string())
604 }
605
606 #[test]
607 fn test_build_sourcehut_permalink_from_https_url_multi_line_selection() {
608 let permalink = build_permalink(BuildPermalinkParams {
609 remote_url: "https://git.sr.ht/~rajveermalviya/zed",
610 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
611 path: "crates/zed/src/main.rs",
612 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
613 })
614 .unwrap();
615
616 let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L24-48";
617 assert_eq!(permalink.to_string(), expected_url.to_string())
618 }
619
620 #[test]
621 fn test_build_codeberg_permalink_from_ssh_url() {
622 let permalink = build_permalink(BuildPermalinkParams {
623 remote_url: "git@codeberg.org:rajveermalviya/zed.git",
624 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
625 path: "crates/editor/src/git/permalink.rs",
626 selection: None,
627 })
628 .unwrap();
629
630 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs";
631 assert_eq!(permalink.to_string(), expected_url.to_string())
632 }
633
634 #[test]
635 fn test_build_codeberg_permalink_from_ssh_url_single_line_selection() {
636 let permalink = build_permalink(BuildPermalinkParams {
637 remote_url: "git@codeberg.org:rajveermalviya/zed.git",
638 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
639 path: "crates/editor/src/git/permalink.rs",
640 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
641 })
642 .unwrap();
643
644 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L7";
645 assert_eq!(permalink.to_string(), expected_url.to_string())
646 }
647
648 #[test]
649 fn test_build_codeberg_permalink_from_ssh_url_multi_line_selection() {
650 let permalink = build_permalink(BuildPermalinkParams {
651 remote_url: "git@codeberg.org:rajveermalviya/zed.git",
652 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
653 path: "crates/editor/src/git/permalink.rs",
654 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
655 })
656 .unwrap();
657
658 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L24-L48";
659 assert_eq!(permalink.to_string(), expected_url.to_string())
660 }
661
662 #[test]
663 fn test_build_codeberg_permalink_from_https_url() {
664 let permalink = build_permalink(BuildPermalinkParams {
665 remote_url: "https://codeberg.org/rajveermalviya/zed.git",
666 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
667 path: "crates/zed/src/main.rs",
668 selection: None,
669 })
670 .unwrap();
671
672 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs";
673 assert_eq!(permalink.to_string(), expected_url.to_string())
674 }
675
676 #[test]
677 fn test_build_codeberg_permalink_from_https_url_single_line_selection() {
678 let permalink = build_permalink(BuildPermalinkParams {
679 remote_url: "https://codeberg.org/rajveermalviya/zed.git",
680 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
681 path: "crates/zed/src/main.rs",
682 selection: Some(Point::new(6, 1)..Point::new(6, 10)),
683 })
684 .unwrap();
685
686 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs#L7";
687 assert_eq!(permalink.to_string(), expected_url.to_string())
688 }
689
690 #[test]
691 fn test_build_codeberg_permalink_from_https_url_multi_line_selection() {
692 let permalink = build_permalink(BuildPermalinkParams {
693 remote_url: "https://codeberg.org/rajveermalviya/zed.git",
694 sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
695 path: "crates/zed/src/main.rs",
696 selection: Some(Point::new(23, 1)..Point::new(47, 10)),
697 })
698 .unwrap();
699
700 let expected_url = "https://codeberg.org/rajveermalviya/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/zed/src/main.rs#L24-L48";
701 assert_eq!(permalink.to_string(), expected_url.to_string())
702 }
703}