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}