From 7a9bfc4877b19a547dd4df59589226225d2ada9a Mon Sep 17 00:00:00 2001 From: aviac Date: Wed, 25 Oct 2023 22:36:05 +0200 Subject: [PATCH] feat: add "new" implementation for a lot of Options types --- Cargo.toml | 2 +- src/types/api/creation/fork.rs | 9 +++++ src/types/api/creation/issue.rs | 16 +++++++++ src/types/api/creation/issue_comment.rs | 6 ++++ src/types/api/creation/label.rs | 11 ++++++ src/types/api/creation/milestone.rs | 13 +++++++ src/types/api/creation/pull_request.rs | 20 +++++++++-- src/types/api/edit/issue.rs | 24 ++++++++++++- src/types/api/edit/label.rs | 12 +++++++ src/types/api/edit/milestone.rs | 13 +++++++ src/types/api/edit/pull_request.rs | 27 ++++++++++++++ src/types/api/mod.rs | 1 - src/types/api/notification_subject.rs | 18 +++++++--- src/types/api/notification_thread.rs | 8 +++++ src/types/misc/color.rs | 19 ++++++---- src/types/misc/merge_state.rs | 26 ++++++++++++++ src/types/misc/mod.rs | 2 ++ .../notification_subject_type.rs | 35 ++++++++++++++++--- 18 files changed, 241 insertions(+), 21 deletions(-) create mode 100644 src/types/misc/merge_state.rs rename src/types/{api => misc}/notification_subject_type.rs (52%) diff --git a/Cargo.toml b/Cargo.toml index 55fd63e..ad81139 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forgejo-api-types" -version = "0.1.10" +version = "0.1.11" edition = "2021" license = "AGPL-3.0-or-later" keywords = ["forgejo", "types", "codeberg", "api"] diff --git a/src/types/api/creation/fork.rs b/src/types/api/creation/fork.rs index 0a1a307..034cada 100644 --- a/src/types/api/creation/fork.rs +++ b/src/types/api/creation/fork.rs @@ -8,3 +8,12 @@ pub struct CreateForkOption { /// The organization name, if forking into an organization (optional). pub organization: Option, } + +impl CreateForkOption { + pub fn use_same_name_for_fork() -> Self { + Self { + name: Default::default(), + organization: Default::default(), + } + } +} diff --git a/src/types/api/creation/issue.rs b/src/types/api/creation/issue.rs index 70bc474..e25caeb 100644 --- a/src/types/api/creation/issue.rs +++ b/src/types/api/creation/issue.rs @@ -25,3 +25,19 @@ pub struct CreateIssueOption { /// The title of the issue (required). pub title: String, } + +impl CreateIssueOption { + pub fn new(title: String) -> Self { + Self { + title, + closed: StateType::Open, + assignee: Default::default(), + assignees: Default::default(), + body: Default::default(), + due_date: Default::default(), + labels: Default::default(), + milestone: Default::default(), + ref_field: Default::default(), + } + } +} diff --git a/src/types/api/creation/issue_comment.rs b/src/types/api/creation/issue_comment.rs index 05f867a..b3ec779 100644 --- a/src/types/api/creation/issue_comment.rs +++ b/src/types/api/creation/issue_comment.rs @@ -6,3 +6,9 @@ pub struct CreateIssueCommentOption { /// The body of the comment. This field is required. pub body: String, } + +impl CreateIssueCommentOption { + pub fn new(body: String) -> Self { + Self { body } + } +} diff --git a/src/types/api/creation/label.rs b/src/types/api/creation/label.rs index 8bebf51..060d1f7 100644 --- a/src/types/api/creation/label.rs +++ b/src/types/api/creation/label.rs @@ -18,6 +18,17 @@ pub struct CreateLabelOption { pub name: String, } +impl CreateLabelOption { + pub fn new(name: String) -> Self { + Self { + color: Color(palette::rgb::Rgb::new(0, 0, 0)), + description: Default::default(), + exclusive: Exclusive::Yes, + name, + } + } +} + impl Display for CreateLabelOption { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "CreateLabelOption: {}", self.name) diff --git a/src/types/api/creation/milestone.rs b/src/types/api/creation/milestone.rs index 727006f..d1351c6 100644 --- a/src/types/api/creation/milestone.rs +++ b/src/types/api/creation/milestone.rs @@ -1,6 +1,8 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use crate::types::misc::boolean_enums::state_type::StateType; + /// Options for creating a milestone. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct CreateMilestoneOption { @@ -13,3 +15,14 @@ pub struct CreateMilestoneOption { /// The title of the milestone. pub title: String, } + +impl CreateMilestoneOption { + pub fn new(title: String) -> Self { + Self { + description: Default::default(), + due_on: Default::default(), + state: StateType::Open.to_string(), + title, + } + } +} diff --git a/src/types/api/creation/pull_request.rs b/src/types/api/creation/pull_request.rs index f4fb619..27ef8dc 100644 --- a/src/types/api/creation/pull_request.rs +++ b/src/types/api/creation/pull_request.rs @@ -8,13 +8,13 @@ pub struct CreatePullRequestOption { pub assignee: Option, /// The list of assignees for the pull request. pub assignees: Vec, - /// The base branch for the pull request. + /// The base branch for the pull request. The source of new code pub base: String, /// The body of the pull request. pub body: String, /// The due date for the pull request. pub due_date: Option>, - /// The head branch for the pull request. + /// The head branch for the pull request. The target for new code pub head: String, /// The labels associated with the pull request (list of label IDs). pub labels: Vec, @@ -23,3 +23,19 @@ pub struct CreatePullRequestOption { /// The title of the pull request. pub title: String, } + +impl CreatePullRequestOption { + pub fn new(title: String, base: String, head: String) -> Self { + Self { + assignee: Default::default(), + assignees: Default::default(), + base, + body: Default::default(), + due_date: Default::default(), + head, + labels: Default::default(), + milestone: Default::default(), + title, + } + } +} diff --git a/src/types/api/edit/issue.rs b/src/types/api/edit/issue.rs index ead6e3c..1f94063 100644 --- a/src/types/api/edit/issue.rs +++ b/src/types/api/edit/issue.rs @@ -1,6 +1,8 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use crate::types::api::issue::Issue; +use crate::types::misc::boolean_enums::state_type::StateType; use crate::types::misc::boolean_enums::unset_due_date::UnsetDueDate; /// Options for editing an issue. @@ -19,9 +21,29 @@ pub struct EditIssueOption { /// The reference for the issue. pub ref_field: String, /// The state of the issue. ["open" / "closed"] - pub state: String, + pub state: StateType, /// The title of the issue. pub title: String, /// Indicates whether to unset the due date. pub unset_due_date: UnsetDueDate, } + +impl EditIssueOption { + pub fn from_issue(issue: Issue) -> Self { + Self { + assignee: issue.assignee.as_ref().map(|user| user.login_name.clone()), + assignees: issue + .assignees + .iter() + .map(|user| user.login_name.clone()) + .collect::>(), + due_date: issue.due_date, + milestone: issue.milestone.as_ref().map(|milestone| milestone.id), + ref_field: issue.ref_field, + state: issue.state, + title: issue.title, + body: issue.body, + unset_due_date: UnsetDueDate::Keep, + } + } +} diff --git a/src/types/api/edit/label.rs b/src/types/api/edit/label.rs index b936e03..4547ff0 100644 --- a/src/types/api/edit/label.rs +++ b/src/types/api/edit/label.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; +use crate::types::api::label::Label; use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; @@ -18,6 +19,17 @@ pub struct EditLabelOption { pub name: String, } +impl EditLabelOption { + pub fn from_label(label: Label) -> Self { + Self { + name: label.name, + description: label.description, + exclusive: label.exclusive, + color: label.color, + } + } +} + impl Display for EditLabelOption { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "EditLabelOption: {}", self.name) diff --git a/src/types/api/edit/milestone.rs b/src/types/api/edit/milestone.rs index 19509c8..34a9094 100644 --- a/src/types/api/edit/milestone.rs +++ b/src/types/api/edit/milestone.rs @@ -1,6 +1,8 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use crate::types::api::milestone::Milestone; + /// Options for editing a milestone. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct EditMilestoneOption { @@ -13,3 +15,14 @@ pub struct EditMilestoneOption { /// The title of the milestone. pub title: String, } + +impl EditMilestoneOption { + pub fn from_milestone(milestone: Milestone) -> Self { + Self { + description: Some(milestone.description), + due_on: milestone.due_on, + state: milestone.state.to_string(), + title: milestone.title, + } + } +} diff --git a/src/types/api/edit/pull_request.rs b/src/types/api/edit/pull_request.rs index f0679ef..a5eb1cc 100644 --- a/src/types/api/edit/pull_request.rs +++ b/src/types/api/edit/pull_request.rs @@ -1,6 +1,7 @@ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use crate::types::api::pull_request::PullRequest; use crate::types::misc::boolean_enums::allow::maintainer_edit::AllowMaintainerEdit; use crate::types::misc::boolean_enums::unset_due_date::UnsetDueDate; @@ -30,3 +31,29 @@ pub struct EditPullRequestOption { /// Indicates whether to unset the due date. pub unset_due_date: UnsetDueDate, } + +impl EditPullRequestOption { + pub fn from_pull_request(pull_request: PullRequest) -> Self { + Self { + allow_maintainer_edit: pull_request.allow_maintainer_edit, + assignee: Some(pull_request.assignee.username), + assignees: pull_request + .assignees + .iter() + .map(|user| user.username.clone()) + .collect::>(), + base: pull_request.base.label, + body: pull_request.body, + due_date: Some(pull_request.due_date), + labels: pull_request + .labels + .iter() + .map(|label| label.id) + .collect::>(), + milestone: Some(pull_request.milestone.id), + state: pull_request.state.to_string(), + title: pull_request.title, + unset_due_date: UnsetDueDate::Keep, + } + } +} diff --git a/src/types/api/mod.rs b/src/types/api/mod.rs index 39b6d24..0e36112 100644 --- a/src/types/api/mod.rs +++ b/src/types/api/mod.rs @@ -91,7 +91,6 @@ pub mod access_token; /* to-todo */ pub mod note; /* to-todo */ pub mod notification_count; /* to-todo */ pub mod notification_subject; -/* to-todo */ pub mod notification_subject_type; /* to-todo */ pub mod notification_thread; /* to-todo */ pub mod notify_subject_type; /* to-todo */ pub mod oath_application; diff --git a/src/types/api/notification_subject.rs b/src/types/api/notification_subject.rs index b0d931a..bbc9d75 100644 --- a/src/types/api/notification_subject.rs +++ b/src/types/api/notification_subject.rs @@ -1,9 +1,11 @@ +use std::fmt::Display; + use serde::{Deserialize, Serialize}; use url::Url; use crate::define_deserialize_test; -use crate::types::misc::boolean_enums::state_type::StateType; -use crate::types::api::notification_subject_type::NotifySubjectType; +use crate::types::misc::merge_state::MergeState; +use crate::types::misc::notification_subject_type::NotifySubjectType; /// Represents the notification subject, which can be an Issue, Pull Request, or Commit. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -14,16 +16,22 @@ pub struct NotificationSubject { pub latest_comment_html_url: Url, /// The URL of the latest comment on the notification subject. pub latest_comment_url: Url, - /// The state of the notification subject (e.g., "open" or "closed"). - pub state: StateType, + /// The state of the notification subject (e.g., "open" or "closed" or "merged"). + pub state: MergeState, /// The title of the notification subject. pub title: String, - /// The type of the notification subject (e.g., "Issue", "PullRequest", or "Commit"). + /// The type of the notification subject (e.g., "Issue", "Pull", "Commit" or "Repository"). pub r#type: NotifySubjectType, /// The URL of the notification subject. pub url: Url, } +impl Display for NotificationSubject { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.title) + } +} + define_deserialize_test!( NotificationSubject, "../../../test_data/example_notification_subject.json" diff --git a/src/types/api/notification_thread.rs b/src/types/api/notification_thread.rs index e31e5fc..6c3ce8a 100644 --- a/src/types/api/notification_thread.rs +++ b/src/types/api/notification_thread.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use url::Url; @@ -27,6 +29,12 @@ pub struct NotificationThread { pub url: Url, } +impl Display for NotificationThread { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.subject) + } +} + define_deserialize_test!( NotificationThread, "../../../test_data/example_notification_thread.json" diff --git a/src/types/misc/color.rs b/src/types/misc/color.rs index 3139bb2..6cb0393 100644 --- a/src/types/misc/color.rs +++ b/src/types/misc/color.rs @@ -9,6 +9,19 @@ use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; #[derive(Debug, Clone, PartialEq)] pub struct Color(pub(crate) Rgb); +impl Display for Color { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{:02X}{:02X}{:02X}", self.red, self.green, self.blue) + } +} + +impl TryFrom<&str> for Color { + type Error = serde_json::Error; + fn try_from(value: &str) -> Result { + serde_json::from_str(value) + } +} + impl Deref for Color { type Target = Rgb; @@ -17,12 +30,6 @@ impl Deref for Color { } } -impl Display for Color { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{:02X}{:02X}{:02X}", self.red, self.green, self.blue) - } -} - impl DerefMut for Color { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 diff --git a/src/types/misc/merge_state.rs b/src/types/misc/merge_state.rs new file mode 100644 index 0000000..e412f68 --- /dev/null +++ b/src/types/misc/merge_state.rs @@ -0,0 +1,26 @@ +use clap::ValueEnum; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumIs, EnumIter, EnumString}; + +/// State of something mergable, either open/closed/merged +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + ValueEnum, + Display, + EnumIter, + EnumString, + EnumIs, + Serialize, + Deserialize, +)] +#[strum(serialize_all = "lowercase")] +#[serde(rename_all = "lowercase")] +pub enum MergeState { + Open, + Closed, + Merged, +} diff --git a/src/types/misc/mod.rs b/src/types/misc/mod.rs index 79df9f4..01aff37 100644 --- a/src/types/misc/mod.rs +++ b/src/types/misc/mod.rs @@ -4,6 +4,8 @@ pub mod color; pub mod external_issue_format; pub mod header; pub mod locale; +pub mod merge_state; +pub mod notification_subject_type; pub mod optional_url; pub mod permission; pub mod sshurl; diff --git a/src/types/api/notification_subject_type.rs b/src/types/misc/notification_subject_type.rs similarity index 52% rename from src/types/api/notification_subject_type.rs rename to src/types/misc/notification_subject_type.rs index 600cbdf..79a54ce 100644 --- a/src/types/api/notification_subject_type.rs +++ b/src/types/misc/notification_subject_type.rs @@ -1,11 +1,29 @@ +use clap::ValueEnum; use serde::{Deserialize, Serialize}; +use strum::{Display, EnumIs, EnumIter, EnumString}; -/// Represents the type of the notification subject. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +/// Type of note the notification originates from +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + ValueEnum, + Display, + EnumIter, + EnumString, + EnumIs, + Serialize, + Deserialize, +)] +#[strum(serialize_all = "lowercase")] +#[serde(rename_all = "lowercase")] pub enum NotifySubjectType { Issue, - PullRequest, + Pull, Commit, + Repository, } #[cfg(test)] @@ -21,9 +39,9 @@ mod tests { #[test] fn deserialize_notify_subject_type_pull_request() { - let json_data = r#""PullRequest""#; + let json_data = r#""Pull""#; let notify_subject_type: NotifySubjectType = serde_json::from_str(json_data).unwrap(); - assert_eq!(notify_subject_type, NotifySubjectType::PullRequest); + assert_eq!(notify_subject_type, NotifySubjectType::Pull); } #[test] @@ -32,4 +50,11 @@ mod tests { let notify_subject_type: NotifySubjectType = serde_json::from_str(json_data).unwrap(); assert_eq!(notify_subject_type, NotifySubjectType::Commit); } + + #[test] + fn deserialize_notify_subject_type_repository() { + let json_data = r#""Repository""#; + let notify_subject_type: NotifySubjectType = serde_json::from_str(json_data).unwrap(); + assert_eq!(notify_subject_type, NotifySubjectType::Repository); + } }