1use crate::{error::GiteeError, GiteeClient};
2use reqwest::Method;
3
4mod models;
5pub use models::*;
6
7impl GiteeClient {
8 pub async fn list_pulls(&self, owner: &str, repo: &str, options: Option<PullListOptions>) -> Result<Vec<PullRequest>, GiteeError> {
10 let url = format!("{}/repos/{}/{}/pulls", self.base_url(), owner, repo);
11 let mut request = self.client().request(Method::GET, &url)
12 .header("Authorization", self.auth_header());
13
14 if let Some(opts) = options {
15 request = request.query(&opts);
16 }
17
18 let response = request.send().await?;
19
20 if !response.status().is_success() {
21 return Err(GiteeError::ApiError(format!(
22 "Failed to list pull requests: {}",
23 response.status()
24 )));
25 }
26
27 let pulls: Vec<PullRequest> = response.json().await?;
28 Ok(pulls)
29 }
30
31 pub async fn create_pull(
33 &self,
34 owner: &str,
35 repo: &str,
36 title: &str,
37 head: &str,
38 base: &str,
39 body: Option<&str>,
40 ) -> Result<PullRequest, GiteeError> {
41 let url = format!("{}/repos/{}/{}/pulls", self.base_url(), owner, repo);
42
43 let mut payload = std::collections::HashMap::new();
44 payload.insert("title", title.to_string());
45 payload.insert("head", head.to_string());
46 payload.insert("base", base.to_string());
47 if let Some(body) = body {
48 payload.insert("body", body.to_string());
49 }
50
51 let response = self
52 .client()
53 .request(Method::POST, &url)
54 .header("Authorization", self.auth_header())
55 .json(&payload)
56 .send()
57 .await?;
58
59 if !response.status().is_success() {
60 return Err(GiteeError::ApiError(format!(
61 "Failed to create pull request: {}",
62 response.status()
63 )));
64 }
65
66 let pull: PullRequest = response.json().await?;
67 Ok(pull)
68 }
69
70 pub async fn close_pull(
72 &self,
73 owner: &str,
74 repo: &str,
75 pull_number: &str,
76 ) -> Result<PullRequest, GiteeError> {
77 let url = format!(
78 "{}/repos/{}/{}/pulls/{}",
79 self.base_url(),
80 owner,
81 repo,
82 pull_number
83 );
84
85 let payload = serde_json::json!({
86 "state": "closed"
87 });
88
89 let response = self
90 .client()
91 .request(Method::PATCH, &url)
92 .header("Authorization", self.auth_header())
93 .json(&payload)
94 .send()
95 .await?;
96
97 if !response.status().is_success() {
98 return Err(GiteeError::ApiError(format!(
99 "Failed to close pull request: {}",
100 response.status()
101 )));
102 }
103
104 let pull: PullRequest = response.json().await?;
105 Ok(pull)
106 }
107
108 pub async fn merge_pull(
110 &self,
111 owner: &str,
112 repo: &str,
113 pull_number: &str,
114 ) -> Result<PullRequest, GiteeError> {
115 let url = format!(
116 "{}/repos/{}/{}/pulls/{}/merge",
117 self.base_url(),
118 owner,
119 repo,
120 pull_number
121 );
122
123 let response = self
124 .client()
125 .request(Method::PUT, &url)
126 .header("Authorization", self.auth_header())
127 .send()
128 .await?;
129
130 if !response.status().is_success() {
131 return Err(GiteeError::ApiError(format!(
132 "Failed to merge pull request: {}",
133 response.status()
134 )));
135 }
136
137 self.get_pull_detail(owner, repo, pull_number).await
140 }
141
142 pub async fn get_pull_detail(&self, owner: &str, repo: &str, number: &str) -> Result<PullRequest, GiteeError> {
144 let url = format!("{}/repos/{}/{}/pulls/{}", self.base_url(), owner, repo, number);
145
146 let response = self
147 .client()
148 .request(Method::GET, &url)
149 .header("Authorization", self.auth_header())
150 .send()
151 .await?;
152
153 if !response.status().is_success() {
154 return Err(GiteeError::ApiError(format!(
155 "Failed to get pull request detail: {}",
156 response.status()
157 )));
158 }
159
160 let pull: PullRequest = response.json().await?;
161 Ok(pull)
162 }
163
164 pub async fn update_pull(&self, owner: &str, repo: &str, number: &str, title: Option<&str>, body: Option<&str>, state: Option<&str>) -> Result<PullRequest, GiteeError> {
166 let url = format!("{}/repos/{}/{}/pulls/{}", self.base_url(), owner, repo, number);
167
168 let mut payload = std::collections::HashMap::new();
169 if let Some(t) = title {
170 payload.insert("title", t);
171 }
172 if let Some(b) = body {
173 payload.insert("body", b);
174 }
175 if let Some(s) = state {
176 payload.insert("state", s); }
178
179 let response = self
180 .client()
181 .request(Method::PATCH, &url)
182 .header("Authorization", self.auth_header())
183 .json(&payload)
184 .send()
185 .await?;
186
187 if !response.status().is_success() {
188 return Err(GiteeError::ApiError(format!(
189 "Failed to update pull request: {}",
190 response.status()
191 )));
192 }
193
194 let pull: PullRequest = response.json().await?;
195 Ok(pull)
196 }
197
198 pub async fn comment_pull(&self, owner: &str, repo: &str, number: &str, body: &str) -> Result<Comment, GiteeError> {
200 let url = format!("{}/repos/{}/{}/pulls/{}/comments", self.base_url(), owner, repo, number);
201
202 let payload = [("body", body)];
203
204 let response = self
205 .client()
206 .request(Method::POST, &url)
207 .header("Authorization", self.auth_header())
208 .form(&payload)
209 .send()
210 .await?;
211
212 if !response.status().is_success() {
213 return Err(GiteeError::ApiError(format!(
214 "Failed to comment on pull request: {}",
215 response.status()
216 )));
217 }
218
219 let comment: Comment = response.json().await?;
220 Ok(comment)
221 }
222
223 pub async fn list_pull_comments(&self, owner: &str, repo: &str, number: &str) -> Result<Vec<Comment>, GiteeError> {
225 let url = format!("{}/repos/{}/{}/pulls/{}/comments", self.base_url(), owner, repo, number);
226
227 let response = self
228 .client()
229 .request(Method::GET, &url)
230 .header("Authorization", self.auth_header())
231 .send()
232 .await?;
233
234 if !response.status().is_success() {
235 return Err(GiteeError::ApiError(format!(
236 "Failed to list pull request comments: {}",
237 response.status()
238 )));
239 }
240
241 let comments: Vec<Comment> = response.json().await?;
242 Ok(comments)
243 }
244
245 pub async fn get_diff_files(&self, owner: &str, repo: &str, number: &str) -> Result<Vec<FileDiff>, GiteeError> {
247 let url = format!("{}/repos/{}/{}/pulls/{}/files", self.base_url(), owner, repo, number);
248
249 let response = self
250 .client()
251 .request(Method::GET, &url)
252 .header("Authorization", self.auth_header())
253 .send()
254 .await?;
255
256 if !response.status().is_success() {
257 return Err(GiteeError::ApiError(format!(
258 "Failed to get diff files: {}",
259 response.status()
260 )));
261 }
262
263 let files: Vec<FileDiff> = response.json().await?;
264 Ok(files)
265 }
266}