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 git::repository::repo_path;
 88    use pretty_assertions::assert_eq;
 89
 90    use super::*;
 91
 92    #[test]
 93    fn test_parse_remote_url_given_ssh_url() {
 94        let parsed_remote = Gitee
 95            .parse_remote_url("git@gitee.com:zed-industries/zed.git")
 96            .unwrap();
 97
 98        assert_eq!(
 99            parsed_remote,
100            ParsedGitRemote {
101                owner: "zed-industries".into(),
102                repo: "zed".into(),
103            }
104        );
105    }
106
107    #[test]
108    fn test_parse_remote_url_given_https_url() {
109        let parsed_remote = Gitee
110            .parse_remote_url("https://gitee.com/zed-industries/zed.git")
111            .unwrap();
112
113        assert_eq!(
114            parsed_remote,
115            ParsedGitRemote {
116                owner: "zed-industries".into(),
117                repo: "zed".into(),
118            }
119        );
120    }
121
122    #[test]
123    fn test_build_gitee_permalink() {
124        let permalink = Gitee.build_permalink(
125            ParsedGitRemote {
126                owner: "zed-industries".into(),
127                repo: "zed".into(),
128            },
129            BuildPermalinkParams::new(
130                "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
131                &repo_path("crates/editor/src/git/permalink.rs"),
132                None,
133            ),
134        );
135
136        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs";
137        assert_eq!(permalink.to_string(), expected_url.to_string())
138    }
139
140    #[test]
141    fn test_build_gitee_permalink_with_single_line_selection() {
142        let permalink = Gitee.build_permalink(
143            ParsedGitRemote {
144                owner: "zed-industries".into(),
145                repo: "zed".into(),
146            },
147            BuildPermalinkParams::new(
148                "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
149                &repo_path("crates/editor/src/git/permalink.rs"),
150                Some(6..6),
151            ),
152        );
153
154        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L7";
155        assert_eq!(permalink.to_string(), expected_url.to_string())
156    }
157
158    #[test]
159    fn test_build_gitee_permalink_with_multi_line_selection() {
160        let permalink = Gitee.build_permalink(
161            ParsedGitRemote {
162                owner: "zed-industries".into(),
163                repo: "zed".into(),
164            },
165            BuildPermalinkParams::new(
166                "e5fe811d7ad0fc26934edd76f891d20bdc3bb194",
167                &repo_path("crates/editor/src/git/permalink.rs"),
168                Some(23..47),
169            ),
170        );
171
172        let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L24-48";
173        assert_eq!(permalink.to_string(), expected_url.to_string())
174    }
175}