gitlab.rs

  1use url::Url;
  2
  3use git::{BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, ParsedGitRemote};
  4
  5pub struct Gitlab;
  6
  7impl GitHostingProvider for Gitlab {
  8    fn name(&self) -> String {
  9        "GitLab".to_string()
 10    }
 11
 12    fn base_url(&self) -> Url {
 13        Url::parse("https://gitlab.com").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@gitlab.com:") || url.starts_with("https://gitlab.com/") {
 30            let repo_with_owner = url
 31                .trim_start_matches("git@gitlab.com:")
 32                .trim_start_matches("https://gitlab.com/")
 33                .trim_end_matches(".git");
 34
 35            let (owner, repo) = repo_with_owner.split_once('/')?;
 36
 37            return Some(ParsedGitRemote { owner, repo });
 38        }
 39
 40        None
 41    }
 42
 43    fn build_commit_permalink(
 44        &self,
 45        remote: &ParsedGitRemote,
 46        params: BuildCommitPermalinkParams,
 47    ) -> Url {
 48        let BuildCommitPermalinkParams { sha } = params;
 49        let ParsedGitRemote { owner, repo } = remote;
 50
 51        self.base_url()
 52            .join(&format!("{owner}/{repo}/-/commit/{sha}"))
 53            .unwrap()
 54    }
 55
 56    fn build_permalink(&self, remote: ParsedGitRemote, params: BuildPermalinkParams) -> Url {
 57        let ParsedGitRemote { owner, repo } = remote;
 58        let BuildPermalinkParams {
 59            sha,
 60            path,
 61            selection,
 62        } = params;
 63
 64        let mut permalink = self
 65            .base_url()
 66            .join(&format!("{owner}/{repo}/-/blob/{sha}/{path}"))
 67            .unwrap();
 68        if path.ends_with(".md") {
 69            permalink.set_query(Some("plain=1"));
 70        }
 71        permalink.set_fragment(
 72            selection
 73                .map(|selection| self.line_fragment(&selection))
 74                .as_deref(),
 75        );
 76        permalink
 77    }
 78}
 79
 80#[cfg(test)]
 81mod tests {
 82    use super::*;
 83
 84    #[test]
 85    fn test_build_gitlab_permalink_from_ssh_url() {
 86        let remote = ParsedGitRemote {
 87            owner: "zed-industries",
 88            repo: "zed",
 89        };
 90        let permalink = Gitlab.build_permalink(
 91            remote,
 92            BuildPermalinkParams {
 93                sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
 94                path: "crates/editor/src/git/permalink.rs",
 95                selection: None,
 96            },
 97        );
 98
 99        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs";
100        assert_eq!(permalink.to_string(), expected_url.to_string())
101    }
102
103    #[test]
104    fn test_build_gitlab_permalink_from_ssh_url_single_line_selection() {
105        let remote = ParsedGitRemote {
106            owner: "zed-industries",
107            repo: "zed",
108        };
109        let permalink = Gitlab.build_permalink(
110            remote,
111            BuildPermalinkParams {
112                sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
113                path: "crates/editor/src/git/permalink.rs",
114                selection: Some(6..6),
115            },
116        );
117
118        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7";
119        assert_eq!(permalink.to_string(), expected_url.to_string())
120    }
121
122    #[test]
123    fn test_build_gitlab_permalink_from_ssh_url_multi_line_selection() {
124        let remote = ParsedGitRemote {
125            owner: "zed-industries",
126            repo: "zed",
127        };
128        let permalink = Gitlab.build_permalink(
129            remote,
130            BuildPermalinkParams {
131                sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7",
132                path: "crates/editor/src/git/permalink.rs",
133                selection: Some(23..47),
134            },
135        );
136
137        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-48";
138        assert_eq!(permalink.to_string(), expected_url.to_string())
139    }
140
141    #[test]
142    fn test_build_gitlab_permalink_from_https_url() {
143        let remote = ParsedGitRemote {
144            owner: "zed-industries",
145            repo: "zed",
146        };
147        let permalink = Gitlab.build_permalink(
148            remote,
149            BuildPermalinkParams {
150                sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
151                path: "crates/zed/src/main.rs",
152                selection: None,
153            },
154        );
155
156        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs";
157        assert_eq!(permalink.to_string(), expected_url.to_string())
158    }
159
160    #[test]
161    fn test_build_gitlab_permalink_from_https_url_single_line_selection() {
162        let remote = ParsedGitRemote {
163            owner: "zed-industries",
164            repo: "zed",
165        };
166        let permalink = Gitlab.build_permalink(
167            remote,
168            BuildPermalinkParams {
169                sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
170                path: "crates/zed/src/main.rs",
171                selection: Some(6..6),
172            },
173        );
174
175        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L7";
176        assert_eq!(permalink.to_string(), expected_url.to_string())
177    }
178
179    #[test]
180    fn test_build_gitlab_permalink_from_https_url_multi_line_selection() {
181        let remote = ParsedGitRemote {
182            owner: "zed-industries",
183            repo: "zed",
184        };
185        let permalink = Gitlab.build_permalink(
186            remote,
187            BuildPermalinkParams {
188                sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa",
189                path: "crates/zed/src/main.rs",
190                selection: Some(23..47),
191            },
192        );
193
194        let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs#L24-48";
195        assert_eq!(permalink.to_string(), expected_url.to_string())
196    }
197}