gitee.rs

  1use std::str::FromStr;
  2
  3use url::Url;
  4
  5use git::{
  6    BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, ParsedGitRemote,
  7    RemoteUrl,
  8};
  9
 10pub struct Gitee;
 11
 12impl GitHostingProvider for Gitee {
 13    fn name(&self) -> String {
 14        "Gitee".to_string()
 15    }
 16
 17    fn base_url(&self) -> Url {
 18        Url::parse("https://gitee.com").unwrap()
 19    }
 20
 21    fn supports_avatars(&self) -> bool {
 22        false
 23    }
 24
 25    fn format_line_number(&self, line: u32) -> String {
 26        format!("L{line}")
 27    }
 28
 29    fn format_line_numbers(&self, start_line: u32, end_line: u32) -> String {
 30        format!("L{start_line}-{end_line}")
 31    }
 32
 33    fn parse_remote_url(&self, url: &str) -> Option<ParsedGitRemote> {
 34        let url = RemoteUrl::from_str(url).ok()?;
 35
 36        let host = url.host_str()?;
 37        if host != "gitee.com" {
 38            return None;
 39        }
 40
 41        let mut path_segments = url.path_segments()?;
 42        let owner = path_segments.next()?;
 43        let repo = path_segments.next()?.trim_end_matches(".git");
 44
 45        Some(ParsedGitRemote {
 46            owner: owner.into(),
 47            repo: repo.into(),
 48        })
 49    }
 50
 51    fn build_commit_permalink(
 52        &self,
 53        remote: &ParsedGitRemote,
 54        params: BuildCommitPermalinkParams,
 55    ) -> Url {
 56        let BuildCommitPermalinkParams { sha } = params;
 57        let ParsedGitRemote { owner, repo } = remote;
 58
 59        self.base_url()
 60            .join(&format!("{owner}/{repo}/commit/{sha}"))
 61            .unwrap()
 62    }
 63
 64    fn build_permalink(&self, remote: ParsedGitRemote, params: BuildPermalinkParams) -> Url {
 65        let ParsedGitRemote { owner, repo } = remote;
 66        let BuildPermalinkParams {
 67            sha,
 68            path,
 69            selection,
 70        } = params;
 71
 72        let mut permalink = self
 73            .base_url()
 74            .join(&format!("{owner}/{repo}/blob/{sha}/{path}"))
 75            .unwrap();
 76        permalink.set_fragment(
 77            selection
 78                .map(|selection| self.line_fragment(&selection))
 79                .as_deref(),
 80        );
 81        permalink
 82    }
 83}
 84
 85#[cfg(test)]
 86mod tests {
 87    use pretty_assertions::assert_eq;
 88
 89    use super::*;
 90
 91    #[test]
 92    fn test_parse_remote_url_given_ssh_url() {
 93        let parsed_remote = Gitee
 94            .parse_remote_url("git@gitee.com:zed-industries/zed.git")
 95            .unwrap();
 96
 97        assert_eq!(
 98            parsed_remote,
 99            ParsedGitRemote {
100                owner: "zed-industries".into(),
101                repo: "zed".into(),
102            }
103        );
104    }
105
106    #[test]
107    fn test_parse_remote_url_given_https_url() {
108        let parsed_remote = Gitee
109            .parse_remote_url("https://gitee.com/zed-industries/zed.git")
110            .unwrap();
111
112        assert_eq!(
113            parsed_remote,
114            ParsedGitRemote {
115                owner: "zed-industries".into(),
116                repo: "zed".into(),
117            }
118        );
119    }
120
121    #[test]
122    fn test_build_gitee_permalink() {
123        let permalink = Gitee.build_permalink(
124            ParsedGitRemote {
125                owner: "zed-industries".into(),
126                repo: "zed".into(),
127            },
128            BuildPermalinkParams {
129                sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
130                path: "crates/editor/src/git/permalink.rs",
131                selection: None,
132            },
133        );
134
135        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs";
136        assert_eq!(permalink.to_string(), expected_url.to_string())
137    }
138
139    #[test]
140    fn test_build_gitee_permalink_with_single_line_selection() {
141        let permalink = Gitee.build_permalink(
142            ParsedGitRemote {
143                owner: "zed-industries".into(),
144                repo: "zed".into(),
145            },
146            BuildPermalinkParams {
147                sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
148                path: "crates/editor/src/git/permalink.rs",
149                selection: Some(6..6),
150            },
151        );
152
153        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L7";
154        assert_eq!(permalink.to_string(), expected_url.to_string())
155    }
156
157    #[test]
158    fn test_build_gitee_permalink_with_multi_line_selection() {
159        let permalink = Gitee.build_permalink(
160            ParsedGitRemote {
161                owner: "zed-industries".into(),
162                repo: "zed".into(),
163            },
164            BuildPermalinkParams {
165                sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
166                path: "crates/editor/src/git/permalink.rs",
167                selection: Some(23..47),
168            },
169        );
170
171        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L24-48";
172        assert_eq!(permalink.to_string(), expected_url.to_string())
173    }
174}