rust_cnb/
pulls.rs

1//! Pulls API 客户端
2
3use crate::error::{ApiError, Result};
4use reqwest::Client;
5use serde_json::Value;
6use url::Url;
7
8/// Pulls API 客户端
9pub struct PullsClient {
10    base_url: String,
11    client: Client,
12}
13
14impl PullsClient {
15    /// 创建新的 Pulls API 客户端
16    pub fn new(base_url: String, client: Client) -> Self {
17        Self { base_url, client }
18    }
19
20    /// 设置认证信息
21    pub fn with_auth(self, token: &str) -> Self {
22        // 这里可以扩展认证逻辑
23        self
24    }
25
26    /// 查询 Pull Comments 列表。List pull comments requests.
27    pub async fn get_repo_pulls_number_comments(
28        &self,
29        repo: String,
30        number: String,
31        page: Option<i64>,
32        page_size: Option<i64>,
33    ) -> Result<Value> {
34        let path = format!("/{}/-/pulls/{}/comments", repo, number);
35        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
36        
37        if let Some(value) = page {
38            url.query_pairs_mut().append_pair("page", &value.to_string());
39        }
40        if let Some(value) = page_size {
41            url.query_pairs_mut().append_pair("page_size", &value.to_string());
42        }
43
44                let request = self.client.request(
45            reqwest::Method::GET,
46            url
47        );
48        
49
50
51
52        let response = request.send().await?;
53        
54        if response.status().is_success() {
55            let json: Value = response.json().await?;
56            Ok(json)
57        } else {
58            Err(ApiError::HttpError(response.status().as_u16()))
59        }
60    }
61
62    /// 新增一个 Pull Comment。Create a pull comment.
63    pub async fn post_repo_pulls_number_comments(
64        &self,
65        repo: String,
66        number: String,
67        post_pull_comment_form: serde_json::Value,
68    ) -> Result<Value> {
69        let path = format!("/{}/-/pulls/{}/comments", repo, number);
70        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
71        
72
73        
74        let mut request = self.client.request(
75            reqwest::Method::POST,
76            url
77        );
78
79
80
81        request = request.json(&post_pull_comment_form);
82
83        let response = request.send().await?;
84        
85        if response.status().is_success() {
86            let json: Value = response.json().await?;
87            Ok(json)
88        } else {
89            Err(ApiError::HttpError(response.status().as_u16()))
90        }
91    }
92
93    /// 查询 Pull 的状态检查
94    pub async fn get_repo_pulls_number_commit_statuses(
95        &self,
96        repo: String,
97        number: i64,
98    ) -> Result<Value> {
99        let path = format!("/{}/-/pulls/{}/commit-statuses", repo, number);
100        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
101        
102
103                let request = self.client.request(
104            reqwest::Method::GET,
105            url
106        );
107        
108
109
110
111        let response = request.send().await?;
112        
113        if response.status().is_success() {
114            let json: Value = response.json().await?;
115            Ok(json)
116        } else {
117            Err(ApiError::HttpError(response.status().as_u16()))
118        }
119    }
120
121    /// 查询 Pull 的标签(label) 列表。List labels for a pull.
122    pub async fn get_repo_pulls_number_labels(
123        &self,
124        repo: String,
125        number: String,
126        page: Option<i64>,
127        page_size: Option<i64>,
128    ) -> Result<Value> {
129        let path = format!("/{}/-/pulls/{}/labels", repo, number);
130        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
131        
132        if let Some(value) = page {
133            url.query_pairs_mut().append_pair("page", &value.to_string());
134        }
135        if let Some(value) = page_size {
136            url.query_pairs_mut().append_pair("page_size", &value.to_string());
137        }
138
139                let request = self.client.request(
140            reqwest::Method::GET,
141            url
142        );
143        
144
145
146
147        let response = request.send().await?;
148        
149        if response.status().is_success() {
150            let json: Value = response.json().await?;
151            Ok(json)
152        } else {
153            Err(ApiError::HttpError(response.status().as_u16()))
154        }
155    }
156
157    /// 新增 Pull 标签。Add labels to a pull.
158    pub async fn post_repo_pulls_number_labels(
159        &self,
160        repo: String,
161        number: String,
162        post_pull_labels_form: serde_json::Value,
163    ) -> Result<Value> {
164        let path = format!("/{}/-/pulls/{}/labels", repo, number);
165        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
166        
167
168        
169        let mut request = self.client.request(
170            reqwest::Method::POST,
171            url
172        );
173
174
175
176        request = request.json(&post_pull_labels_form);
177
178        let response = request.send().await?;
179        
180        if response.status().is_success() {
181            let json: Value = response.json().await?;
182            Ok(json)
183        } else {
184            Err(ApiError::HttpError(response.status().as_u16()))
185        }
186    }
187
188    /// 设置 Pull 标签。Set the new labels for a pull.
189    pub async fn put_repo_pulls_number_labels(
190        &self,
191        repo: String,
192        number: String,
193        put_pull_labels_form: serde_json::Value,
194    ) -> Result<Value> {
195        let path = format!("/{}/-/pulls/{}/labels", repo, number);
196        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
197        
198
199        
200        let mut request = self.client.request(
201            reqwest::Method::PUT,
202            url
203        );
204
205
206
207        request = request.json(&put_pull_labels_form);
208
209        let response = request.send().await?;
210        
211        if response.status().is_success() {
212            let json: Value = response.json().await?;
213            Ok(json)
214        } else {
215            Err(ApiError::HttpError(response.status().as_u16()))
216        }
217    }
218
219    /// 清空 Pull 标签。Remove all labels from a pull.
220    pub async fn delete_repo_pulls_number_labels(
221        &self,
222        repo: String,
223        number: String,
224    ) -> Result<Value> {
225        let path = format!("/{}/-/pulls/{}/labels", repo, number);
226        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
227        
228
229                let request = self.client.request(
230            reqwest::Method::DELETE,
231            url
232        );
233        
234
235
236
237        let response = request.send().await?;
238        
239        if response.status().is_success() {
240            let json: Value = response.json().await?;
241            Ok(json)
242        } else {
243            Err(ApiError::HttpError(response.status().as_u16()))
244        }
245    }
246
247    /// 删除 Pull 标签。Remove a label from a pull.
248    pub async fn delete_repo_pulls_number_labels_name(
249        &self,
250        repo: String,
251        number: String,
252        name: String,
253    ) -> Result<Value> {
254        let path = format!("/{}/-/pulls/{}/labels/{}", repo, number, name);
255        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
256        
257
258                let request = self.client.request(
259            reqwest::Method::DELETE,
260            url
261        );
262        
263
264
265
266        let response = request.send().await?;
267        
268        if response.status().is_success() {
269            let json: Value = response.json().await?;
270            Ok(json)
271        } else {
272            Err(ApiError::HttpError(response.status().as_u16()))
273        }
274    }
275
276    /// 获取一个 Pull Comment。Get a pull comment.
277    pub async fn get_repo_pulls_number_comments_comment_id(
278        &self,
279        repo: String,
280        number: String,
281        comment_id: i64,
282    ) -> Result<Value> {
283        let path = format!("/{}/-/pulls/{}/comments/{}", repo, number, comment_id);
284        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
285        
286
287                let request = self.client.request(
288            reqwest::Method::GET,
289            url
290        );
291        
292
293
294
295        let response = request.send().await?;
296        
297        if response.status().is_success() {
298            let json: Value = response.json().await?;
299            Ok(json)
300        } else {
301            Err(ApiError::HttpError(response.status().as_u16()))
302        }
303    }
304
305    /// 更新一个 Pull Comment。Update a pull comment.
306    pub async fn patch_repo_pulls_number_comments_comment_id(
307        &self,
308        repo: String,
309        number: String,
310        comment_id: i64,
311        patch_pull_comment_form: serde_json::Value,
312    ) -> Result<Value> {
313        let path = format!("/{}/-/pulls/{}/comments/{}", repo, number, comment_id);
314        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
315        
316
317        
318        let mut request = self.client.request(
319            reqwest::Method::PATCH,
320            url
321        );
322
323
324
325        request = request.json(&patch_pull_comment_form);
326
327        let response = request.send().await?;
328        
329        if response.status().is_success() {
330            let json: Value = response.json().await?;
331            Ok(json)
332        } else {
333            Err(ApiError::HttpError(response.status().as_u16()))
334        }
335    }
336
337    /// 查询特定 pull reviews 列表。List pull reviews.
338    pub async fn get_repo_pulls_number_reviews(
339        &self,
340        repo: String,
341        number: String,
342        page: Option<i64>,
343        page_size: Option<i64>,
344    ) -> Result<Value> {
345        let path = format!("/{}/-/pulls/{}/reviews", repo, number);
346        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
347        
348        if let Some(value) = page {
349            url.query_pairs_mut().append_pair("page", &value.to_string());
350        }
351        if let Some(value) = page_size {
352            url.query_pairs_mut().append_pair("page_size", &value.to_string());
353        }
354
355                let request = self.client.request(
356            reqwest::Method::GET,
357            url
358        );
359        
360
361
362
363        let response = request.send().await?;
364        
365        if response.status().is_success() {
366            let json: Value = response.json().await?;
367            Ok(json)
368        } else {
369            Err(ApiError::HttpError(response.status().as_u16()))
370        }
371    }
372
373    /// 新增一次 pull request 评审。Create a pull review.
374    pub async fn post_repo_pulls_number_reviews(
375        &self,
376        repo: String,
377        number: String,
378        post_pull_review_form: serde_json::Value,
379    ) -> Result<Value> {
380        let path = format!("/{}/-/pulls/{}/reviews", repo, number);
381        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
382        
383
384        
385        let mut request = self.client.request(
386            reqwest::Method::POST,
387            url
388        );
389
390
391
392        request = request.json(&post_pull_review_form);
393
394        let response = request.send().await?;
395        
396        if response.status().is_success() {
397            let json: Value = response.json().await?;
398            Ok(json)
399        } else {
400            Err(ApiError::HttpError(response.status().as_u16()))
401        }
402    }
403
404    /// 查询指定 Pull Review Comments 列表评论。List pull review comments.
405    pub async fn get_repo_pulls_number_reviews_review_id_comments(
406        &self,
407        repo: String,
408        number: i64,
409        review_id: i64,
410        page: Option<i64>,
411        page_size: Option<i64>,
412    ) -> Result<Value> {
413        let path = format!("/{}/-/pulls/{}/reviews/{}/comments", repo, number, review_id);
414        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
415        
416        if let Some(value) = page {
417            url.query_pairs_mut().append_pair("page", &value.to_string());
418        }
419        if let Some(value) = page_size {
420            url.query_pairs_mut().append_pair("page_size", &value.to_string());
421        }
422
423                let request = self.client.request(
424            reqwest::Method::GET,
425            url
426        );
427        
428
429
430
431        let response = request.send().await?;
432        
433        if response.status().is_success() {
434            let json: Value = response.json().await?;
435            Ok(json)
436        } else {
437            Err(ApiError::HttpError(response.status().as_u16()))
438        }
439    }
440
441    /// 根据numbers查询 Pull 列表。List pull requests by numbers.
442    pub async fn get_repo_pull_in_batch(
443        &self,
444        repo: String,
445        n: Vec<String>,
446    ) -> Result<Value> {
447        let path = format!("/{}/-/pull-in-batch", repo);
448        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
449        
450        for item in &n {
451            url.query_pairs_mut().append_pair("n", item);
452        }
453
454                let request = self.client.request(
455            reqwest::Method::GET,
456            url
457        );
458        
459
460
461
462        let response = request.send().await?;
463        
464        if response.status().is_success() {
465            let json: Value = response.json().await?;
466            Ok(json)
467        } else {
468            Err(ApiError::HttpError(response.status().as_u16()))
469        }
470    }
471
472    /// 合并一个 Pull Request。Merge a pull request.
473    pub async fn put_repo_pulls_number_merge(
474        &self,
475        repo: String,
476        number: String,
477        merge_pull_request_form: serde_json::Value,
478    ) -> Result<Value> {
479        let path = format!("/{}/-/pulls/{}/merge", repo, number);
480        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
481        
482
483        
484        let mut request = self.client.request(
485            reqwest::Method::PUT,
486            url
487        );
488
489
490
491        request = request.json(&merge_pull_request_form);
492
493        let response = request.send().await?;
494        
495        if response.status().is_success() {
496            let json: Value = response.json().await?;
497            Ok(json)
498        } else {
499            Err(ApiError::HttpError(response.status().as_u16()))
500        }
501    }
502
503    /// 查询指定 PullRequest 的文件列表。Lists the files in a specified pull request.
504    pub async fn get_repo_pulls_number_files(
505        &self,
506        repo: String,
507        number: String,
508    ) -> Result<Value> {
509        let path = format!("/{}/-/pulls/{}/files", repo, number);
510        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
511        
512
513                let request = self.client.request(
514            reqwest::Method::GET,
515            url
516        );
517        
518
519
520
521        let response = request.send().await?;
522        
523        if response.status().is_success() {
524            let json: Value = response.json().await?;
525            Ok(json)
526        } else {
527            Err(ApiError::HttpError(response.status().as_u16()))
528        }
529    }
530
531    /// 查询指定 PullRequest 的提交列表。Lists the commits in a specified pull request.
532    pub async fn get_repo_pulls_number_commits(
533        &self,
534        repo: String,
535        number: String,
536        page: Option<i64>,
537        page_size: Option<i64>,
538    ) -> Result<Value> {
539        let path = format!("/{}/-/pulls/{}/commits", repo, number);
540        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
541        
542        if let Some(value) = page {
543            url.query_pairs_mut().append_pair("page", &value.to_string());
544        }
545        if let Some(value) = page_size {
546            url.query_pairs_mut().append_pair("page_size", &value.to_string());
547        }
548
549                let request = self.client.request(
550            reqwest::Method::GET,
551            url
552        );
553        
554
555
556
557        let response = request.send().await?;
558        
559        if response.status().is_success() {
560            let json: Value = response.json().await?;
561            Ok(json)
562        } else {
563            Err(ApiError::HttpError(response.status().as_u16()))
564        }
565    }
566
567    /// 查询指定 PullRequest 的 Assignees。List repository pull request assignees.
568    pub async fn get_repo_pulls_number_assignees(
569        &self,
570        repo: String,
571        number: String,
572    ) -> Result<Value> {
573        let path = format!("/{}/-/pulls/{}/assignees", repo, number);
574        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
575        
576
577                let request = self.client.request(
578            reqwest::Method::GET,
579            url
580        );
581        
582
583
584
585        let response = request.send().await?;
586        
587        if response.status().is_success() {
588            let json: Value = response.json().await?;
589            Ok(json)
590        } else {
591            Err(ApiError::HttpError(response.status().as_u16()))
592        }
593    }
594
595    /// 添加 Assignees 到指定的 PullRequest。 Adds up to 10 assignees to a pull request. Users already assigned to an issue are not replaced.
596    pub async fn post_repo_pulls_number_assignees(
597        &self,
598        repo: String,
599        number: String,
600        post_pull_assignees_form: serde_json::Value,
601    ) -> Result<Value> {
602        let path = format!("/{}/-/pulls/{}/assignees", repo, number);
603        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
604        
605
606        
607        let mut request = self.client.request(
608            reqwest::Method::POST,
609            url
610        );
611
612
613
614        request = request.json(&post_pull_assignees_form);
615
616        let response = request.send().await?;
617        
618        if response.status().is_success() {
619            let json: Value = response.json().await?;
620            Ok(json)
621        } else {
622            Err(ApiError::HttpError(response.status().as_u16()))
623        }
624    }
625
626    /// 删除 PullRequest 中的 Assignees。 Removes one or more assignees from a pull request.
627    pub async fn delete_repo_pulls_number_assignees(
628        &self,
629        repo: String,
630        number: String,
631        delete_pull_assignees_form: serde_json::Value,
632    ) -> Result<Value> {
633        let path = format!("/{}/-/pulls/{}/assignees", repo, number);
634        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
635        
636
637        
638        let mut request = self.client.request(
639            reqwest::Method::DELETE,
640            url
641        );
642
643
644
645        request = request.json(&delete_pull_assignees_form);
646
647        let response = request.send().await?;
648        
649        if response.status().is_success() {
650            let json: Value = response.json().await?;
651            Ok(json)
652        } else {
653            Err(ApiError::HttpError(response.status().as_u16()))
654        }
655    }
656
657    /// 查询 Pull 列表。List pull requests.
658    pub async fn get_repo_pulls(
659        &self,
660        repo: String,
661        page: Option<i64>,
662        page_size: Option<i64>,
663        state: Option<String>,
664        authors: Option<String>,
665        reviewers: Option<String>,
666        assignees: Option<String>,
667        base_ref: Option<String>,
668    ) -> Result<Value> {
669        let path = format!("/{}/-/pulls", repo);
670        let mut url = Url::parse(&format!("{}{}", self.base_url, path))?;
671        
672        if let Some(value) = page {
673            url.query_pairs_mut().append_pair("page", &value.to_string());
674        }
675        if let Some(value) = page_size {
676            url.query_pairs_mut().append_pair("page_size", &value.to_string());
677        }
678        if let Some(value) = state {
679            url.query_pairs_mut().append_pair("state", &value.to_string());
680        }
681        if let Some(value) = authors {
682            url.query_pairs_mut().append_pair("authors", &value.to_string());
683        }
684        if let Some(value) = reviewers {
685            url.query_pairs_mut().append_pair("reviewers", &value.to_string());
686        }
687        if let Some(value) = assignees {
688            url.query_pairs_mut().append_pair("assignees", &value.to_string());
689        }
690        if let Some(value) = base_ref {
691            url.query_pairs_mut().append_pair("base_ref", &value.to_string());
692        }
693
694                let request = self.client.request(
695            reqwest::Method::GET,
696            url
697        );
698        
699
700
701
702        let response = request.send().await?;
703        
704        if response.status().is_success() {
705            let json: Value = response.json().await?;
706            Ok(json)
707        } else {
708            Err(ApiError::HttpError(response.status().as_u16()))
709        }
710    }
711
712    /// 新增一个 Pull。Create a pull request.
713    pub async fn post_repo_pulls(
714        &self,
715        repo: String,
716        post_pull_form: serde_json::Value,
717    ) -> Result<Value> {
718        let path = format!("/{}/-/pulls", repo);
719        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
720        
721
722        
723        let mut request = self.client.request(
724            reqwest::Method::POST,
725            url
726        );
727
728
729
730        request = request.json(&post_pull_form);
731
732        let response = request.send().await?;
733        
734        if response.status().is_success() {
735            let json: Value = response.json().await?;
736            Ok(json)
737        } else {
738            Err(ApiError::HttpError(response.status().as_u16()))
739        }
740    }
741
742    /// 检查用户是否可以被添加到 PullRequest 的 Assignees 中。 Checks if a user can be assigned to a pull request.
743    pub async fn get_repo_pulls_number_assignees_assignee(
744        &self,
745        repo: String,
746        number: String,
747        assignee: String,
748    ) -> Result<Value> {
749        let path = format!("/{}/-/pulls/{}/assignees/{}", repo, number, assignee);
750        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
751        
752
753                let request = self.client.request(
754            reqwest::Method::GET,
755            url
756        );
757        
758
759
760
761        let response = request.send().await?;
762        
763        if response.status().is_success() {
764            let json: Value = response.json().await?;
765            Ok(json)
766        } else {
767            Err(ApiError::HttpError(response.status().as_u16()))
768        }
769    }
770
771    /// 查询指定 Pull。Get a pull request.
772    pub async fn get_repo_pulls_number(
773        &self,
774        repo: String,
775        number: String,
776    ) -> Result<Value> {
777        let path = format!("/{}/-/pulls/{}", repo, number);
778        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
779        
780
781                let request = self.client.request(
782            reqwest::Method::GET,
783            url
784        );
785        
786
787
788
789        let response = request.send().await?;
790        
791        if response.status().is_success() {
792            let json: Value = response.json().await?;
793            Ok(json)
794        } else {
795            Err(ApiError::HttpError(response.status().as_u16()))
796        }
797    }
798
799    /// 更新一个 Pull Request。Update a pull request.
800    pub async fn patch_repo_pulls_number(
801        &self,
802        repo: String,
803        number: String,
804        update_pull_request_form: serde_json::Value,
805    ) -> Result<Value> {
806        let path = format!("/{}/-/pulls/{}", repo, number);
807        let url = Url::parse(&format!("{}{}", self.base_url, path))?;
808        
809
810        
811        let mut request = self.client.request(
812            reqwest::Method::PATCH,
813            url
814        );
815
816
817
818        request = request.json(&update_pull_request_form);
819
820        let response = request.send().await?;
821        
822        if response.status().is_success() {
823            let json: Value = response.json().await?;
824            Ok(json)
825        } else {
826            Err(ApiError::HttpError(response.status().as_u16()))
827        }
828    }
829
830}