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}