deployment_changelog/api/bitbucket.rs
1//! The `deployment_changelog::api::bitbucket` module provides a high-level API for interacting with
2//! the Bitbucket REST API, making it easy to retrieve information related to commits, pull requests,
3//! and issues.
4//!
5//! This module provides the `BitbucketClient` struct for interacting with the Bitbucket API, as well
6//! as various structs for representing Bitbucket objects, such as `BitbucketCommit`, `BitbucketPullRequest`,
7//! and `BitbucketPullRequestIssue`.
8//!
9//! # Examples
10//!
11//! Creating a new `BitbucketClient` with a base URL and fetching commits between two revisions:
12//!
13//! ```rust
14//! use deployment_changelog::api::bitbucket::BitbucketClient;
15//!
16//! let bitbucket_client = BitbucketClient::new("https://api.bitbucket.org")
17//! .unwrap();
18//!
19//! let mut commits = bitbucket_client.compare_commits("MY_PROJECT", "MY_REPO", "abcdef123456", "fedcba654321");
20//!
21//! let all_commits = commits.all().await.unwrap();
22//!
23//! for commit in all_commits {
24//! println!("{}", commit);
25//! }
26//! ```
27//!
28//! Fetching pull requests for a specific commit:
29//!
30//! ```rust
31//! use deployment_changelog::api::bitbucket::BitbucketClient;
32//!
33//! let bitbucket_client = BitbucketClient::new("https://api.bitbucket.org")
34//! .unwrap();
35//!
36//! let mut pull_requests = bitbucket_client.get_pull_requests("MY_PROJECT", "MY_REPO", "abcdef123456");
37//!
38//! let all_pull_requests = pull_requests.all().await.unwrap();
39//!
40//! for pr in all_pull_requests {
41//! println!("{}", pr);
42//! }
43//! ```
44//!
45//! Fetching issues associated with a pull request:
46//!
47//! ```rust
48//! use deployment_changelog::api::bitbucket::BitbucketClient;
49//!
50//! let bitbucket_client = BitbucketClient::new("https://api.bitbucket.org")
51//! .unwrap();
52//!
53//! let issues = bitbucket_client.get_pull_request_issues("MY_PROJECT", "MY_REPO", 42).await.unwrap();
54//!
55//! for issue in issues {
56//! println!("{}", issue);
57//! }
58//! ```
59use std::{fmt::Display, collections::HashMap, marker::PhantomData};
60
61use serde::{Deserialize, Serialize, de::DeserializeOwned};
62use serde_with::chrono::{DateTime, Local};
63use serde_with::TimestampMilliSeconds;
64use serde_with::formats::Flexible;
65use anyhow::Result;
66
67use super::rest::{RestClient, Paginated};
68
69enum BitbucketEndpoints {
70 CompareCommits,
71 PullRequestsForCommit,
72 IssuesForPullRequest
73}
74
75impl BitbucketEndpoints {
76 fn url(&self) -> &'static str {
77 match self {
78 BitbucketEndpoints::CompareCommits => "rest/api/latest/projects/{projectKey}/repos/{repositorySlug}/compare/commits?from={from}&to={to}",
79 BitbucketEndpoints::PullRequestsForCommit => "rest/api/latest/projects/{projectKey}/repos/{repositorySlug}/commits/{commitId}/pull-requests",
80 BitbucketEndpoints::IssuesForPullRequest => "/rest/jira/latest/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/issues"
81 }
82 }
83}
84
85enum BitbucketOptions {
86 PageStart
87}
88
89impl BitbucketOptions {
90 fn option(&self) -> &'static str {
91 match self {
92 BitbucketOptions::PageStart => "start"
93 }
94 }
95}
96
97/// The `BitbucketPage` struct represents a single page of results returned by the Bitbucket API.
98///
99/// It is generic over the type `T` and contains a vector of values, pagination information such as the
100/// current page size, whether this is the last page, the current page start index, the result limit,
101/// and the index for the next page, if available.
102///
103/// You usually don't need to interact with `BitbucketPage` directly, as the `BitbucketPaginated`
104/// iterator takes care of the pagination for you when fetching multiple pages of results.
105///
106/// # Example
107///
108/// Suppose you are fetching commits using the `BitbucketClient::compare_commits()` method. The
109/// response from the Bitbucket API will be represented as a `BitbucketPage<BitbucketCommit>`.
110///
111/// To get the vector of `BitbucketCommit` objects from the page, you can access the `values` field:
112///
113/// ```rust
114/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPage};
115///
116/// // Suppose you fetched a BitbucketPage<BitbucketCommit> named 'commit_page'
117/// let commits: Vec<BitbucketCommit> = commit_page.values;
118///
119/// for commit in commits {
120/// println!("{}", commit);
121/// }
122/// ```
123#[derive(Serialize, Deserialize, Debug)]
124#[serde(rename_all = "camelCase")]
125pub struct BitbucketPage<T> {
126 pub values: Vec<T>,
127 pub size: u32,
128 pub is_last_page: bool,
129 pub start: u32,
130 pub limit: u32,
131 pub next_page_start: Option<u32>
132}
133
134impl<T: Serialize> Display for BitbucketPage<T> {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match serde_json::to_string_pretty(&self) {
137 Ok(json) => write!(f, "{json}"),
138 Err(error) => panic!("Error serializing Bitbucket commit page: {error}")
139 }
140 }
141}
142
143/// The `BitbucketPaginated` struct represents an iterator for paginated results returned by the
144/// Bitbucket API.
145///
146/// It is generic over the type `T`, and is used in conjunction with [`Paginated`](crate::api::rest::Paginated) trait.
147/// It abstracts the pagination logic, allowing you to easily fetch multiple pages of results without
148/// worrying about pagination details.
149///
150/// You usually don't need to create a `BitbucketPaginated` object manually, as the methods from `BitbucketClient`
151/// will return a `BitbucketPaginated` instance when necessary.
152///
153/// # Example
154///
155/// Suppose you want to fetch all commits between two commit hashes using the `BitbucketClient::compare_commits()` method.
156/// It returns a `BitbucketPaginated<BitbucketCommit>` iterator, which you can use to fetch all pages of results:
157///
158/// ```rust
159/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
160/// use deployment_changelog::api::rest::Paginated;
161///
162/// // Suppose you have a BitbucketClient named 'client'
163/// let project_key = "PROJECT";
164/// let repo_slug = "my-repo";
165/// let start_commit = "abcdef";
166/// let end_commit = "123456";
167///
168/// let mut commits_iter = client.compare_commits(project_key, repo_slug, start_commit, end_commit);
169/// let all_commits = commits_iter.all().await.unwrap();
170///
171/// for commit in all_commits {
172/// println!("{}", commit);
173/// }
174/// ```
175pub struct BitbucketPaginated<'a, T> {
176 client: &'a BitbucketClient,
177 url: String,
178 query: HashMap<String, String>,
179 next_page_start: Option<u32>,
180 is_last_page: bool,
181 phantom: PhantomData<T>
182}
183
184impl<'a, T> BitbucketPaginated<'a, T> {
185 /// Creates a new `BitbucketPaginated` instance with the specified client, URL, and query options.
186 ///
187 /// # Example
188 ///
189 /// ```
190 /// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
191 ///
192 /// let bitbucket_base_url = "https://your-bitbucket-instance.com/";
193 /// let client = BitbucketClient::new(bitbucket_base_url).unwrap();
194 /// let url = "some/endpoint";
195 /// let paginated = BitbucketPaginated::new(&client, url.to_string(), None);
196 /// ```
197 fn new(client: &'a BitbucketClient, url: String, query: Option<&HashMap<String, String>>) -> Self {
198 let query_options = match query {
199 Some(query_opts) => query_opts.clone(),
200 None => HashMap::with_capacity(1)
201 };
202
203 BitbucketPaginated {
204 client,
205 url,
206 query: query_options,
207 next_page_start: Some(0),
208 is_last_page: false,
209 phantom: PhantomData
210 }
211 }
212}
213
214#[async_trait::async_trait]
215impl<T: DeserializeOwned + Send> Paginated<T> for BitbucketPaginated<'_, T> {
216 /// Fetches the next page of items of type `T` from the API and returns them as a vector.
217 ///
218 /// # Example
219 ///
220 /// ```
221 /// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketCommit, BitbucketPaginated};
222 ///
223 /// async fn fetch_next_page_of_commits() {
224 /// let bitbucket_base_url = "https://your-bitbucket-instance.com/";
225 /// let client = BitbucketClient::new(bitbucket_base_url).unwrap();
226 /// let url = "some/endpoint";
227 /// let mut paginated = BitbucketPaginated::<BitbucketCommit>::new(&client, url.to_string(), None);
228 ///
229 /// let commits = paginated.next().await.unwrap();
230 /// println!("Fetched {} commits", commits.len());
231 /// }
232 /// ```
233 async fn next(&mut self) -> Result<Vec<T>> {
234 if let Some(next_page_start) = self.next_page_start {
235 self.query.insert(
236 BitbucketOptions::PageStart.option().to_string(),
237 next_page_start.to_string()
238 );
239 };
240
241 let page = self.client.client.get::<BitbucketPage<T>>(&self.url, Some(&self.query)).await?;
242
243 self.next_page_start = page.next_page_start;
244 self.is_last_page = page.is_last_page;
245
246 Ok(page.values)
247 }
248
249 /// Returns whether the last page of items has been fetched.
250 ///
251 /// # Example
252 ///
253 /// ```
254 /// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketCommit, BitbucketPaginated};
255 ///
256 /// async fn iterate_over_all_commits() {
257 /// let bitbucket_base_url = "https://your-bitbucket-instance.com/";
258 /// let client = BitbucketClient::new(bitbucket_base_url).unwrap();
259 /// let url = "some/endpoint";
260 /// let mut paginated = BitbucketPaginated::<BitbucketCommit>::new(&client, url.to_string(), None);
261 ///
262 /// while !paginated.is_last() {
263 /// let commits = paginated.next().await.unwrap();
264 /// println!("Fetched {} commits", commits.len());
265 /// }
266 /// }
267 /// ```
268 fn is_last(&self) -> bool {
269 self.is_last_page
270 }
271}
272
273/// The `BitbucketCommit` struct represents a single commit returned by the Bitbucket API.
274///
275/// It contains information about the commit, such as its ID, display ID, author, committer, and message.
276///
277/// This struct is usually used as a result of API calls made through the `BitbucketClient`.
278///
279/// # Example
280///
281/// Suppose you want to fetch all commits between two commit hashes using the `BitbucketClient::compare_commits()` method.
282/// You'll receive a `BitbucketPaginated<BitbucketCommit>` iterator, which you can use to fetch all pages of commits:
283///
284/// ```rust
285/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
286/// use deployment_changelog::api::rest::Paginated;
287///
288/// // Suppose you have a BitbucketClient named 'client'
289/// let project_key = "PROJECT";
290/// let repo_slug = "my-repo";
291/// let start_commit = "abcdef";
292/// let end_commit = "123456";
293///
294/// let mut commits_iter = client.compare_commits(project_key, repo_slug, start_commit, end_commit);
295/// let all_commits = commits_iter.all().await.unwrap();
296///
297/// for commit in all_commits {
298/// println!("Commit ID: {}", commit.id);
299/// println!("Author: {}", commit.author.display_name);
300/// println!("Message: {}", commit.message);
301/// }
302/// ```
303#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
304#[serde(rename_all = "camelCase")]
305pub struct BitbucketCommit {
306 pub id: String,
307 pub display_id: String,
308 pub author: BitbucketAuthor,
309 pub committer: BitbucketAuthor,
310 pub message: String
311}
312
313impl Display for BitbucketCommit {
314 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
315 match serde_json::to_string_pretty(&self) {
316 Ok(json) => write!(f, "{json}"),
317 Err(error) => panic!("Error serializing Bitbucket commit: {error}")
318 }
319 }
320}
321
322/// The `BitbucketAuthor` struct represents an author or committer of a commit returned by the Bitbucket API.
323///
324/// It contains information about the author, such as their name, email address, and display name.
325///
326/// This struct is usually used as a part of the `BitbucketCommit` struct when working with the `BitbucketClient`.
327///
328/// # Example
329///
330/// Suppose you want to fetch all commits between two commit hashes using the `BitbucketClient::compare_commits()` method.
331/// You'll receive a `BitbucketPaginated<BitbucketCommit>` iterator, which you can use to fetch all pages of commits:
332///
333/// ```rust
334/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
335/// use deployment_changelog::api::rest::Paginated;
336///
337/// // Suppose you have a BitbucketClient named 'client'
338/// let project_key = "PROJECT";
339/// let repo_slug = "my-repo";
340/// let start_commit = "abcdef";
341/// let end_commit = "123456";
342///
343/// let mut commits_iter = client.compare_commits(project_key, repo_slug, start_commit, end_commit);
344/// let all_commits = commits_iter.all().await.unwrap();
345///
346/// for commit in all_commits {
347/// let author = &commit.author;
348/// println!("Author name: {}", author.name);
349/// println!("Author email: {}", author.email_address);
350/// println!("Author display name: {}", author.display_name);
351/// }
352/// ```
353#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
354#[serde(rename_all = "camelCase")]
355pub struct BitbucketAuthor {
356 pub name: String,
357 pub email_address: String,
358 pub display_name: String
359}
360
361impl Display for BitbucketAuthor {
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
363 match serde_json::to_string_pretty(&self) {
364 Ok(json) => write!(f, "{json}"),
365 Err(error) => panic!("Error serializing Bitbucket author: {error}")
366 }
367 }
368}
369
370/// The `BitbucketPullRequest` struct represents a pull request returned by the Bitbucket API.
371///
372/// It contains information about the pull request, such as the ID, title, description, open status, author, and creation and update dates.
373///
374/// This struct is usually used when working with the `BitbucketClient` to fetch pull requests associated with a commit.
375///
376/// # Example
377///
378/// Suppose you want to fetch all pull requests associated with a commit hash using the `BitbucketClient::get_pull_requests()` method.
379/// You'll receive a `BitbucketPaginated<BitbucketPullRequest>` iterator, which you can use to fetch all pages of pull requests:
380///
381/// ```rust
382/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
383/// use deployment_changelog::api::rest::Paginated;
384///
385/// // Suppose you have a BitbucketClient named 'client'
386/// let project_key = "PROJECT";
387/// let repo_slug = "my-repo";
388/// let commit_hash = "abcdef";
389///
390/// let mut pr_iter = client.get_pull_requests(project_key, repo_slug, commit_hash);
391/// let all_pull_requests = pr_iter.all().await.unwrap();
392///
393/// for pr in all_pull_requests {
394/// println!("Pull request ID: {}", pr.id);
395/// println!("Title: {}", pr.title);
396/// println!("Description: {}", pr.description);
397/// println!("Open: {}", pr.open);
398/// println!("Created: {}", pr.created_date);
399/// println!("Updated: {}", pr.updated_date);
400/// }
401/// ```
402#[serde_with::serde_as]
403#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
404#[serde(rename_all = "camelCase")]
405pub struct BitbucketPullRequest {
406 pub id: u64,
407 pub title: String,
408 pub description: String,
409 pub open: bool,
410 pub author: BitbucketPullRequestAuthor,
411
412 #[serde_as(as = "TimestampMilliSeconds<String, Flexible>")]
413 pub created_date: DateTime<Local>,
414
415 #[serde_as(as = "TimestampMilliSeconds<String, Flexible>")]
416 pub updated_date: DateTime<Local>
417}
418
419impl Display for BitbucketPullRequest {
420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421 match serde_json::to_string_pretty(&self) {
422 Ok(json) => write!(f, "{json}"),
423 Err(error) => panic!("Error serializing Bitbucket pull request: {error}")
424 }
425 }
426}
427
428/// The `BitbucketPullRequestAuthor` struct represents the author of a pull request returned by the Bitbucket API.
429///
430/// It contains information about the author, such as the user and whether the pull request has been approved by the author.
431///
432/// This struct is usually used as part of the `BitbucketPullRequest` struct when working with the `BitbucketClient` to fetch pull requests associated with a commit.
433///
434/// # Example
435///
436/// Suppose you want to fetch all pull requests associated with a commit hash using the `BitbucketClient::get_pull_requests()` method.
437/// You'll receive a `BitbucketPaginated<BitbucketPullRequest>` iterator, which you can use to fetch all pages of pull requests:
438///
439/// ```rust
440/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketPaginated};
441/// use deployment_changelog::api::rest::Paginated;
442///
443/// // Suppose you have a BitbucketClient named 'client'
444/// let project_key = "PROJECT";
445/// let repo_slug = "my-repo";
446/// let commit_hash = "abcdef";
447///
448/// let mut pr_iter = client.get_pull_requests(project_key, repo_slug, commit_hash);
449/// let all_pull_requests = pr_iter.all().await.unwrap();
450///
451/// for pr in all_pull_requests {
452/// println!("Author display name: {}", pr.author.user.display_name);
453/// println!("Author email: {}", pr.author.user.email_address);
454/// println!("Author approval status: {}", pr.author.approved);
455/// }
456/// ```
457#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
458#[serde(rename_all = "camelCase")]
459pub struct BitbucketPullRequestAuthor {
460 pub user: BitbucketAuthor,
461 pub approved: bool
462}
463
464impl Display for BitbucketPullRequestAuthor {
465 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
466 match serde_json::to_string_pretty(&self) {
467 Ok(json) => write!(f, "{json}"),
468 Err(error) => panic!("Error serializing Bitbucket pull request author: {error}")
469 }
470 }
471}
472
473/// The `BitbucketPullRequestIssue` struct represents an issue associated with a pull request returned by the Bitbucket API.
474///
475/// It contains information about the issue, such as the key and URL of the issue.
476///
477/// This struct is usually used when working with the `BitbucketClient` to fetch issues associated with a specific pull request.
478///
479/// # Example
480///
481/// Suppose you want to fetch all issues associated with a pull request using the `BitbucketClient::get_pull_request_issues()` method.
482/// You'll receive a `Result<Vec<BitbucketPullRequestIssue>>`, which you can use to access and process the associated issues:
483///
484/// ```rust
485/// use deployment_changelog::api::bitbucket::BitbucketClient;
486///
487/// // Suppose you have a BitbucketClient named 'client'
488/// let project_key = "PROJECT";
489/// let repo_slug = "my-repo";
490/// let pull_request_id = 42;
491///
492/// let issues_result = client.get_pull_request_issues(project_key, repo_slug, pull_request_id).await;
493///
494/// match issues_result {
495/// Ok(issues) => {
496/// for issue in issues {
497/// println!("Issue key: {}", issue.key);
498/// println!("Issue URL: {}", issue.url);
499/// }
500/// },
501/// Err(error) => {
502/// println!("Error fetching pull request issues: {:?}", error);
503/// }
504/// }
505/// ```
506#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
507#[serde(rename_all = "camelCase")]
508pub struct BitbucketPullRequestIssue {
509 pub key: String,
510 pub url: String
511}
512
513impl Display for BitbucketPullRequestIssue {
514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515 match serde_json::to_string_pretty(&self) {
516 Ok(json) => write!(f, "{json}"),
517 Err(error) => panic!("Error serializing Bitbucket pull request issue: {error}")
518 }
519 }
520}
521
522/// The `BitbucketClient` struct is a high-level API client for working with the Bitbucket API.
523///
524/// It provides methods for common operations like comparing commits, fetching pull requests for a commit, and getting issues associated with a pull request.
525///
526/// Internally, it uses the `RestClient` struct for making API calls.
527///
528/// # Example
529///
530/// To create a new `BitbucketClient`, you can use the `new()` method and pass the base URL of your Bitbucket instance:
531///
532/// ```rust
533/// use deployment_changelog::api::bitbucket::BitbucketClient;
534///
535/// let base_url = "https://bitbucket.example.com";
536/// let client = BitbucketClient::new(base_url).unwrap();
537/// ```
538///
539/// Once you have a `BitbucketClient`, you can use it to interact with the Bitbucket API:
540///
541/// ```rust
542/// use deployment_changelog::api::bitbucket::{BitbucketClient, BitbucketCommit};
543///
544/// // Suppose you have a BitbucketClient named 'client'
545/// let project_key = "PROJECT";
546/// let repo_slug = "my-repo";
547/// let start_commit = "abcdef";
548/// let end_commit = "ghijkl";
549///
550/// let mut commits_paginated = client.compare_commits(project_key, repo_slug, start_commit, end_commit);
551///
552/// while let Some(commits_result) = commits_paginated.next().await {
553/// match commits_result {
554/// Ok(commits) => {
555/// for commit in commits {
556/// println!("Commit ID: {}", commit.id);
557/// println!("Commit message: {}", commit.message);
558/// }
559/// },
560/// Err(error) => {
561/// println!("Error fetching commits: {:?}", error);
562/// }
563/// }
564/// }
565/// ```
566/// BitbucketClient is a struct that provides methods for interacting with the Bitbucket API.
567///
568/// It wraps the RestClient struct and exposes methods for fetching commits, pull requests,
569/// and related issues.
570///
571/// # Example
572///
573/// ```
574/// let client = BitbucketClient::new("https://api.bitbucket.com").unwrap();
575/// ```
576#[derive(Debug)]
577pub struct BitbucketClient {
578 client: RestClient
579}
580
581impl BitbucketClient {
582 /// Creates a new BitbucketClient instance given the base URL.
583 ///
584 /// # Arguments
585 ///
586 /// * `base_url` - The base URL of the Bitbucket API.
587 ///
588 /// # Returns
589 ///
590 /// A Result containing a BitbucketClient instance or an error if the provided base URL is invalid.
591 pub fn new(base_url: &str) -> Result<Self> {
592 Ok(Self {
593 client: RestClient::new(base_url)?
594 })
595 }
596
597 /// Constructs a BitbucketClient instance from a pre-initialized RestClient.
598 ///
599 /// # Arguments
600 ///
601 /// * `client` - An instance of RestClient.
602 pub fn from_client(client: RestClient) -> Self {
603 Self {
604 client
605 }
606 }
607
608 /// Returns a `BitbucketPaginated<BitbucketCommit>` instance for fetching commits between
609 /// two commit IDs (start_commit and end_commit) in a specified Bitbucket project and repository.
610 ///
611 /// # Arguments
612 ///
613 /// * `project` - The project key in Bitbucket.
614 /// * `repo` - The repository slug in Bitbucket.
615 /// * `start_commit` - The commit ID to start the comparison from.
616 /// * `end_commit` - The commit ID to end the comparison at.
617 ///
618 /// # Returns
619 ///
620 /// A `BitbucketPaginated<BitbucketCommit>` instance.
621 pub fn compare_commits(&self, project: &str, repo: &str, start_commit: &str, end_commit: &str) -> BitbucketPaginated<BitbucketCommit> {
622 let compare_commits_path: String = BitbucketEndpoints::CompareCommits.url()
623 .replace("{projectKey}", project)
624 .replace("{repositorySlug}", repo)
625 .replace("{from}", start_commit)
626 .replace("{to}", end_commit);
627
628 BitbucketPaginated::new(&self, compare_commits_path, None)
629 }
630
631 /// Returns a `BitbucketPaginated<BitbucketPullRequest>` instance for fetching pull requests
632 /// associated with a specific commit in a Bitbucket project and repository.
633 ///
634 /// # Arguments
635 ///
636 /// * `project` - The project key in Bitbucket.
637 /// * `repo` - The repository slug in Bitbucket.
638 /// * `commit` - The commit ID to fetch the pull requests for.
639 ///
640 /// # Returns
641 ///
642 /// A `BitbucketPaginated<BitbucketPullRequest>` instance.
643 pub fn get_pull_requests(&self, project: &str, repo: &str, commit: &str) -> BitbucketPaginated<BitbucketPullRequest> {
644 let get_pull_requests_path: String = BitbucketEndpoints::PullRequestsForCommit.url()
645 .replace("{projectKey}", project)
646 .replace("{repositorySlug}", repo)
647 .replace("{commitId}", commit);
648
649 BitbucketPaginated::new(&self, get_pull_requests_path, None)
650 }
651
652 /// Fetches issues associated with a specific pull request in a Bitbucket project and repository.
653 ///
654 /// # Arguments
655 ///
656 /// * `project` - The project key in Bitbucket.
657 /// * `repo` - The repository slug in Bitbucket.
658 /// * `pull_request_id` - The ID of the pull request to fetch the issues for.
659 ///
660 /// # Returns
661 ///
662 /// A Result containing a Vec of BitbucketPullRequestIssue instances or an error if the request fails.
663 pub async fn get_pull_request_issues(&self, project: &str, repo: &str, pull_request_id: u64) -> Result<Vec<BitbucketPullRequestIssue>> {
664 let get_pull_request_issues_path: String = BitbucketEndpoints::IssuesForPullRequest.url()
665 .replace("{projectKey}", project)
666 .replace("{repositorySlug}", repo)
667 .replace("{pullRequestId}", &pull_request_id.to_string());
668
669 self.client.get::<Vec<BitbucketPullRequestIssue>>(&get_pull_request_issues_path, None).await
670 }
671}