gitlab.rs

  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}