diff --git a/src/api/commits.rs b/src/api/commits.rs index fb3716a0..c4321173 100644 --- a/src/api/commits.rs +++ b/src/api/commits.rs @@ -1,6 +1,10 @@ //! The commit API. +mod associated_pull_requests; +mod compare_commit; mod create_comment; +pub use associated_pull_requests::PullRequestTarget; + pub use self::create_comment::CreateCommentBuilder; use crate::{models, Octocrab, Result}; @@ -19,6 +23,21 @@ impl<'octo> CommitHandler<'octo> { // create::CreateIssueBuilder::new(self, title.into()) // } + pub fn compare( + &self, + base: impl Into, + head: impl Into, + ) -> compare_commit::CompareCommitsBuilder<'_, '_> { + compare_commit::CompareCommitsBuilder::new(self, base.into(), head.into()) + } + + pub fn associated_pull_requests( + &self, + target: PullRequestTarget, + ) -> associated_pull_requests::AssociatedPullRequestsBuilder<'_, '_> { + associated_pull_requests::AssociatedPullRequestsBuilder::new(self, target) + } + pub fn create_comment( &self, sha: impl Into, diff --git a/src/api/commits/associated_pull_requests.rs b/src/api/commits/associated_pull_requests.rs new file mode 100644 index 00000000..ecddcf7f --- /dev/null +++ b/src/api/commits/associated_pull_requests.rs @@ -0,0 +1,88 @@ +use super::*; + +/// helper to let users know they can pass a branch name or a commit sha +#[derive(Clone, Debug, serde::Serialize)] +#[serde(untagged)] +pub enum PullRequestTarget { + Branch(String), + Sha(String), +} + +impl ToString for PullRequestTarget { + fn to_string(&self) -> String { + match self { + Self::Branch(branch) => branch.to_string(), + Self::Sha(commit) => commit.to_string(), + } + } +} + +#[derive(serde::Serialize)] +pub struct AssociatedPullRequestsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r super::CommitHandler<'octo>, + target: PullRequestTarget, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, +} + +impl<'octo, 'r> AssociatedPullRequestsBuilder<'octo, 'r> { + /// Sha will return all closed pull requests for the given commit sha. + /// + /// Pass a Branch to return all open pull requests against that branch. + pub(crate) fn new(handler: &'r super::CommitHandler<'octo>, target: PullRequestTarget) -> Self { + Self { + handler, + target, + page: None, + per_page: None, + } + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result> { + let route = format!( + "/repos/{owner}/{repo}/commits/{target}/pulls", + owner = self.handler.owner, + repo = self.handler.repo, + target = self.target.to_string(), + ); + + self.handler.crab.get(route, Some(&self)).await + } +} + +#[cfg(test)] +mod tests { + + #[tokio::test] + async fn associated_pull_requests_serializes_correctly() { + use super::PullRequestTarget; + + let octocrab = crate::Octocrab::default(); + let handler = octocrab.commits("owner", "repo"); + let associated_prs = + handler.associated_pull_requests(PullRequestTarget::Sha("commit_sha".to_string())); + + assert_eq!( + serde_json::to_value(associated_prs).unwrap(), + serde_json::json!({ + "target": "commit_sha" + }) + ); + } +} diff --git a/src/api/commits/compare_commit.rs b/src/api/commits/compare_commit.rs new file mode 100644 index 00000000..0e634b0b --- /dev/null +++ b/src/api/commits/compare_commit.rs @@ -0,0 +1,73 @@ +use super::*; + +#[derive(serde::Serialize)] +pub struct CompareCommitsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r super::CommitHandler<'octo>, + base: String, + head: String, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, +} + +impl<'octo, 'r> CompareCommitsBuilder<'octo, 'r> { + pub(crate) fn new( + handler: &'r super::CommitHandler<'octo>, + base: String, + head: String, + ) -> Self { + Self { + handler, + base, + head, + page: None, + per_page: None, + } + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result { + let route = format!( + "/repos/{owner}/{repo}/compare/{base}...{head}", + owner = self.handler.owner, + repo = self.handler.repo, + base = self.base, + head = self.head, + ); + + self.handler.crab.get(route, Some(&self)).await + } +} + +#[cfg(test)] +mod tests { + + #[tokio::test] + async fn compare_commits_serializes_correctly() { + let octocrab = crate::Octocrab::default(); + let handler = octocrab.commits("owner", "repo"); + let comparison = handler.compare("base", "head"); + + assert_eq!( + serde_json::to_value(comparison).unwrap(), + serde_json::json!({ + "base": "base", + "head": "head", + }) + ); + } +} diff --git a/src/models/commits.rs b/src/models/commits.rs index 32202215..e65c8beb 100644 --- a/src/models/commits.rs +++ b/src/models/commits.rs @@ -22,3 +22,127 @@ pub struct Comment { pub updated_at: Option>, pub author_association: String, } + +/// Commit Comparison +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommitComparison { + pub ahead_by: i64, + /// Commit + pub base_commit: Commit, + pub behind_by: i64, + pub commits: Vec, + pub diff_url: String, + pub files: Option>, + pub html_url: String, + /// Commit + pub merge_base_commit: Commit, + pub patch_url: String, + pub permalink_url: String, + pub status: GithubCommitStatus, + pub total_commits: i64, + pub url: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommitElement { + pub author: Option, + pub comment_count: i64, + pub committer: Option, + pub message: String, + pub tree: Tree, + pub url: String, + pub verification: Option, +} + +/// Metaproperties for Git author/committer information. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GitUser { + pub date: Option, + pub email: Option, + pub name: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Tree { + pub sha: String, + pub url: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Verification { + pub payload: Option, + pub reason: String, + pub signature: Option, + pub verified: bool, +} + +/// Diff Entry +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum FileStatus { + Added, + Changed, + Copied, + Modified, + Removed, + Renamed, + Unchanged, +} + +/// Commit +/// Diff Entry +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommitFile { + pub additions: i64, + // unlike the schema online, this can be null + pub blob_url: Option, + pub changes: i64, + pub contents_url: String, + pub deletions: i64, + pub filename: String, + pub patch: Option, + pub previous_filename: Option, + // unlike the schema online, this can be null + pub raw_url: Option, + pub sha: String, + pub status: FileStatus, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommitParent { + pub html_url: Option, + pub sha: String, + pub url: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommitStats { + pub additions: Option, + pub deletions: Option, + pub total: Option, +} + +/// Commit +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Commit { + pub author: Option, + pub comments_url: String, + pub commit: CommitElement, + pub committer: Option, + pub files: Option>, + pub html_url: String, + pub node_id: String, + pub parents: Vec, + pub sha: String, + pub stats: Option, + pub url: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum GithubCommitStatus { + Ahead, + Behind, + Diverged, + Identical, +} diff --git a/src/models/events/payload/workflow_run.rs b/src/models/events/payload/workflow_run.rs index 49d9383b..d40fb433 100644 --- a/src/models/events/payload/workflow_run.rs +++ b/src/models/events/payload/workflow_run.rs @@ -16,6 +16,7 @@ pub struct WorkflowRunEventPayload { #[non_exhaustive] pub enum WorkflowRunEventAction { Requested, + InProgress, Completed, }