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