git_worktree_cli/commands/
list_helpers.rs1use crate::{
2 bitbucket_api, bitbucket_data_center_api,
3 error::{Error, Result},
4 github,
5};
6
7pub struct PullRequestInfo {
8 pub url: String,
9 pub status: String,
10 pub title: String,
11}
12
13pub async fn fetch_pr_for_branch(
14 platform: &str,
15 owner_or_workspace: &str,
16 repo: &str,
17 branch: &str,
18 github_client: &Option<github::GitHubClient>,
19 bitbucket_client: &Option<bitbucket_api::BitbucketClient>,
20 bitbucket_data_center_client: &Option<bitbucket_data_center_api::BitbucketDataCenterClient>,
21) -> Result<Option<PullRequestInfo>> {
22 match platform {
23 "github" => fetch_github_pr(github_client, owner_or_workspace, repo, branch),
24 "bitbucket-cloud" => fetch_bitbucket_cloud_pr(bitbucket_client, owner_or_workspace, repo, branch).await,
25 "bitbucket-data-center" => {
26 fetch_bitbucket_data_center_pr(bitbucket_data_center_client, owner_or_workspace, repo, branch).await
27 }
28 _ => Ok(None),
29 }
30}
31
32fn fetch_github_pr(
33 client: &Option<github::GitHubClient>,
34 owner: &str,
35 repo: &str,
36 branch: &str,
37) -> Result<Option<PullRequestInfo>> {
38 if let Some(ref client) = client {
39 match client.get_pull_requests(owner, repo, branch) {
40 Ok(prs) => {
41 if let Some(pr) = prs.first() {
42 let status = if pr.draft {
43 "DRAFT".to_string()
44 } else {
45 match pr.state.to_lowercase().as_str() {
46 "open" => "OPEN".to_string(),
47 "closed" => "CLOSED".to_string(),
48 "merged" => "MERGED".to_string(),
49 _ => pr.state.to_uppercase(),
50 }
51 };
52
53 Ok(Some(PullRequestInfo {
54 url: pr.html_url.clone(),
55 status,
56 title: pr.title.clone(),
57 }))
58 } else {
59 Ok(None)
60 }
61 }
62 Err(_) => Err(Error::provider("Failed to fetch GitHub PRs")),
63 }
64 } else {
65 Ok(None)
66 }
67}
68
69async fn fetch_bitbucket_cloud_pr(
70 client: &Option<bitbucket_api::BitbucketClient>,
71 workspace: &str,
72 repo: &str,
73 branch: &str,
74) -> Result<Option<PullRequestInfo>> {
75 if let Some(ref client) = client {
76 match client.get_pull_requests(workspace, repo).await {
77 Ok(prs) => {
78 if let Some(pr) = prs.iter().find(|pr| pr.source.branch.name == branch) {
79 let url = extract_bitbucket_cloud_url(pr);
80 Ok(Some(PullRequestInfo {
81 url,
82 status: pr.state.to_uppercase(),
83 title: pr.title.clone(),
84 }))
85 } else {
86 Ok(None)
87 }
88 }
89 Err(_) => Err(Error::provider("Failed to fetch Bitbucket Cloud PRs")),
90 }
91 } else {
92 Ok(None)
93 }
94}
95
96async fn fetch_bitbucket_data_center_pr(
97 client: &Option<bitbucket_data_center_api::BitbucketDataCenterClient>,
98 project: &str,
99 repo: &str,
100 branch: &str,
101) -> Result<Option<PullRequestInfo>> {
102 if let Some(ref client) = client {
103 match client.get_pull_requests(project, repo).await {
104 Ok(prs) => {
105 if let Some(pr) = prs.iter().find(|pr| pr.from_ref.display_id == branch) {
106 let url = extract_bitbucket_data_center_url(pr);
107 Ok(Some(PullRequestInfo {
108 url,
109 status: pr.state.to_uppercase(),
110 title: pr.title.clone(),
111 }))
112 } else {
113 Ok(None)
114 }
115 }
116 Err(_) => Err(Error::provider("Failed to fetch Bitbucket Data Center PRs")),
117 }
118 } else {
119 Ok(None)
120 }
121}
122
123pub fn extract_bitbucket_cloud_url(pr: &bitbucket_api::BitbucketPullRequest) -> String {
124 if let Some(html_link) = pr.links.get("html") {
125 if let Some(href) = html_link.get("href") {
126 if let Some(url) = href.as_str() {
127 return url.to_string();
128 }
129 }
130 }
131 format!("PR #{}", pr.id)
132}
133
134pub fn extract_bitbucket_data_center_url(pr: &bitbucket_data_center_api::BitbucketDataCenterPullRequest) -> String {
135 if let Some(self_link) = pr.links.get("self") {
136 if let Some(links_array) = self_link.as_array() {
137 if let Some(first_link) = links_array.first() {
138 if let Some(href) = first_link.get("href") {
139 if let Some(url) = href.as_str() {
140 return url.to_string();
141 }
142 }
143 }
144 }
145 }
146 format!("PR #{}", pr.id)
147}