1use url::Url;
2
3use crate::{
4 BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, ParsedGitRemote,
5};
6
7pub struct Gitlab;
8
9impl GitHostingProvider for Gitlab {
10 fn name(&self) -> String {
11 "GitLab".to_string()
12 }
13
14 fn base_url(&self) -> Url {
15 Url::parse("https://gitlab.com").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@gitlab.com:") || url.starts_with("https://gitlab.com/") {
32 let repo_with_owner = url
33 .trim_start_matches("git@gitlab.com:")
34 .trim_start_matches("https://gitlab.com/")
35 .trim_end_matches(".git");
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}/-/blob/{sha}/{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_gitlab_permalink_from_ssh_url() {
85 let remote = ParsedGitRemote {
86 owner: "zed-industries",
87 repo: "zed",
88 };
89 let permalink = Gitlab.build_permalink(
90 remote,
91 BuildPermalinkParams {
92 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
93 path: "crates/editor/src/git/permalink.rs",
94 selection: None,
95 },
96 );
97
98 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
99 assert_eq!(permalink.to_string(), expected_url.to_string())
100 }
101
102 #[test]
103 fn test_build_gitlab_permalink_from_ssh_url_single_line_selection() {
104 let remote = ParsedGitRemote {
105 owner: "zed-industries",
106 repo: "zed",
107 };
108 let permalink = Gitlab.build_permalink(
109 remote,
110 BuildPermalinkParams {
111 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
112 path: "crates/editor/src/git/permalink.rs",
113 selection: Some(6..6),
114 },
115 );
116
117 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
118 assert_eq!(permalink.to_string(), expected_url.to_string())
119 }
120
121 #[test]
122 fn test_build_gitlab_permalink_from_ssh_url_multi_line_selection() {
123 let remote = ParsedGitRemote {
124 owner: "zed-industries",
125 repo: "zed",
126 };
127 let permalink = Gitlab.build_permalink(
128 remote,
129 BuildPermalinkParams {
130 sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
131 path: "crates/editor/src/git/permalink.rs",
132 selection: Some(23..47),
133 },
134 );
135
136 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-48";
137 assert_eq!(permalink.to_string(), expected_url.to_string())
138 }
139
140 #[test]
141 fn test_build_gitlab_permalink_from_https_url() {
142 let remote = ParsedGitRemote {
143 owner: "zed-industries",
144 repo: "zed",
145 };
146 let permalink = Gitlab.build_permalink(
147 remote,
148 BuildPermalinkParams {
149 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
150 path: "crates/zed/src/main.rs",
151 selection: None,
152 },
153 );
154
155 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
156 assert_eq!(permalink.to_string(), expected_url.to_string())
157 }
158
159 #[test]
160 fn test_build_gitlab_permalink_from_https_url_single_line_selection() {
161 let remote = ParsedGitRemote {
162 owner: "zed-industries",
163 repo: "zed",
164 };
165 let permalink = Gitlab.build_permalink(
166 remote,
167 BuildPermalinkParams {
168 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
169 path: "crates/zed/src/main.rs",
170 selection: Some(6..6),
171 },
172 );
173
174 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
175 assert_eq!(permalink.to_string(), expected_url.to_string())
176 }
177
178 #[test]
179 fn test_build_gitlab_permalink_from_https_url_multi_line_selection() {
180 let remote = ParsedGitRemote {
181 owner: "zed-industries",
182 repo: "zed",
183 };
184 let permalink = Gitlab.build_permalink(
185 remote,
186 BuildPermalinkParams {
187 sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
188 path: "crates/zed/src/main.rs",
189 selection: Some(23..47),
190 },
191 );
192
193 let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-48";
194 assert_eq!(permalink.to_string(), expected_url.to_string())
195 }
196}