git_worktree_cli/commands/
list_helpers.rs

1use 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}