From 8cc41b7dc63ba09c2e35dec6ea180bc74522adc9 Mon Sep 17 00:00:00 2001 From: RobWalt Date: Fri, 28 Jul 2023 21:31:04 +0200 Subject: [PATCH] feat: progress and visualize progress --- README.md | 2 + calc_stats.sh | 8 + progress.png | Bin 0 -> 34171 bytes src/lib.rs | 1 + src/macros.rs | 113 ++++++++ src/types/api/access_token.rs | 9 + src/types/api/add/collaborator.rs | 6 + src/types/api/add/label.rs | 10 + src/types/api/add/mod.rs | 5 + src/types/api/add/time.rs | 12 + src/types/api/add/topic.rs | 10 + src/types/api/annotated_tag.rs | 12 + src/types/api/annotated_tag_object.rs | 8 + src/types/api/api_settings.rs | 9 + src/types/api/attachment.rs | 14 + src/types/api/attachment_settings.rs | 9 + src/types/api/branch.rs | 16 ++ src/types/api/branch_protection.rs | 46 ++++ src/types/api/changed_file.rs | 14 + src/types/api/combined_status.rs | 14 + src/types/api/comment.rs | 18 ++ src/types/api/commit.rs | 16 ++ src/types/api/commit_affected_files.rs | 6 + src/types/api/commit_date_options.rs | 7 + src/types/api/commit_meta.rs | 5 + src/types/api/commit_stats.rs | 8 + src/types/api/commit_status.rs | 14 + src/types/api/commit_status_state.rs | 3 + src/types/api/commit_user.rs | 5 + src/types/api/content_response.rs | 30 +++ src/types/api/create_hook_option_config.rs | 7 + src/types/api/creation/access_token.rs | 9 + src/types/api/creation/branch.rs | 13 + src/types/api/creation/branch_protection.rs | 44 +++ src/types/api/creation/comment.rs | 6 + src/types/api/creation/commit_status.rs | 9 + src/types/api/creation/email.rs | 10 + src/types/api/creation/file_options.rs | 24 ++ src/types/api/creation/gpg_key.rs | 10 + src/types/api/creation/hook.rs | 16 ++ src/types/api/creation/issue.rs | 24 ++ src/types/api/creation/key.rs | 16 ++ src/types/api/creation/label.rs | 4 +- src/types/api/creation/milestone.rs | 11 + src/types/api/creation/mod.rs | 25 ++ src/types/api/creation/oath_application.rs | 10 + src/types/api/creation/organization.rs | 12 +- src/types/api/creation/pull_request.rs | 18 ++ src/types/api/creation/pull_review.rs | 11 + src/types/api/creation/pull_review_comment.rs | 15 ++ src/types/api/creation/push_mirror.rs | 7 + src/types/api/creation/release.rs | 11 + src/types/api/creation/repository.rs | 39 +++ src/types/api/creation/request_review.rs | 11 + src/types/api/creation/tag.rs | 8 + src/types/api/creation/template_repository.rs | 39 +++ src/types/api/creation/wiki_page.rs | 14 + src/types/api/deploy_key.rs | 14 + src/types/api/dismiss_pull_review.rs | 7 + src/types/api/edit/attachment.rs | 6 + src/types/api/edit/branch_protection.rs | 40 +++ src/types/api/edit/comment.rs | 6 + src/types/api/edit/deadline.rs | 6 + src/types/api/edit/file_options.rs | 36 +++ src/types/api/edit/git_hook.rs | 6 + src/types/api/edit/hook.rs | 8 +- src/types/api/edit/issue.rs | 18 ++ src/types/api/edit/label.rs | 4 +- src/types/api/edit/milestone.rs | 9 + src/types/api/edit/mod.rs | 15 ++ src/types/api/edit/organization.rs | 12 +- src/types/api/edit/pull_request.rs | 20 ++ src/types/api/edit/reaction.rs | 6 + src/types/api/edit/release.rs | 11 + src/types/api/edit/repository.rs | 81 ++++++ src/types/api/edit/user_setting.rs | 16 ++ src/types/api/external/mod.rs | 2 + src/types/api/external/tracker.rs | 66 +++++ src/types/api/external/wiki.rs | 30 +++ src/types/api/file_link_response.rs | 8 + src/types/api/git_blob.rs | 10 + src/types/api/git_entry.rs | 11 + src/types/api/git_hook.rs | 8 + src/types/api/git_object.rs | 5 + src/types/api/git_ref.rs | 5 + src/types/api/git_tree.rs | 13 + src/types/api/gpg_key.rs | 23 ++ src/types/api/gpg_key_email.rs | 7 + src/types/api/heat_map.rs | 9 + src/types/api/hook.rs | 8 +- src/types/api/identity.rs | 7 + src/types/api/internal_tracker.rs | 44 +++ src/types/api/issue.rs | 35 +++ src/types/api/issue_form_field.rs | 11 + src/types/api/issue_form_field_type.rs | 2 + src/types/api/issue_template.rs | 17 ++ src/types/api/issue_template_labels.rs | 3 + src/types/api/label.rs | 4 +- src/types/api/merge.rs | 15 ++ src/types/api/migration.rs | 32 +++ src/types/api/milestone.rs | 17 ++ src/types/api/mod.rs | 87 ++++++ src/types/api/note.rs | 7 + src/types/api/oath_application.rs | 11 + src/types/api/organization.rs | 12 +- src/types/api/organization_permission.rs | 54 ++++ src/types/api/package.rs | 13 + src/types/api/package_file.rs | 12 + src/types/api/payload_commit.rs | 23 ++ src/types/api/payload_commit_verification.rs | 11 + src/types/api/payload_user.rs | 10 + src/types/api/public_key.rs | 14 + src/types/api/pull_request.rs | 38 +++ src/types/api/pull_request_branch_info.rs | 10 + src/types/api/pull_request_meta.rs | 7 + src/types/api/pull_review.rs | 19 ++ src/types/api/pull_review_comment.rs | 20 ++ src/types/api/push_mirror.rs | 13 + src/types/api/reaction.rs | 8 + src/types/api/release.rs | 22 ++ src/types/api/replace/label.rs | 10 + src/types/api/replace/mod.rs | 2 + src/types/api/repo_collaborator_permission.rs | 8 + src/types/api/repo_commit.rs | 12 + src/types/api/repo_meta.rs | 9 + src/types/api/repo_transfer.rs | 43 +++ src/types/api/repository.rs | 252 ++++++++++++++++++ src/types/api/repository_settings.rs | 11 + src/types/api/review_state.rs | 2 + src/types/api/search_results.rs | 35 +++ src/types/api/state_type.rs | 2 + src/types/api/stop_watch.rs | 12 + src/types/api/submit_pull_review.rs | 7 + src/types/api/tag.rs | 11 + src/types/api/team.rs | 8 +- src/types/api/timeline_comment.rs | 38 +++ src/types/api/topic.rs | 8 + src/types/api/tracked_time.rs | 18 ++ src/types/api/transfer.rs | 11 + src/types/api/ui_settings.rs | 12 + src/types/api/user.rs | 41 +-- src/types/api/user_setting.rs | 16 ++ src/types/api/watch_info.rs | 12 + src/types/api/wiki_commit.rs | 9 + src/types/api/wiki_commit_list.rs | 9 + src/types/api/wiki_page.rs | 15 ++ src/types/misc/active.rs | 87 ------ src/types/misc/admin.rs | 87 ------ src/types/misc/boolean_enums/allow/mod.rs | 12 + src/types/misc/boolean_enums/can/mod.rs | 9 + src/types/misc/boolean_enums/enable/mod.rs | 4 + src/types/misc/boolean_enums/has/mod.rs | 6 + src/types/misc/boolean_enums/is/mod.rs | 15 ++ src/types/misc/boolean_enums/mod.rs | 12 + src/types/misc/can_create_org_repo.rs | 87 ------ src/types/misc/color.rs | 12 +- src/types/misc/exclusive.rs | 87 ------ src/types/misc/external_issue_format.rs | 13 + src/types/misc/includes_all_repositories.rs | 88 ------ src/types/misc/locale.rs | 1 + src/types/misc/mod.rs | 13 +- src/types/misc/{url.rs => optional_url.rs} | 0 src/types/misc/permission.rs | 39 +++ src/types/misc/sshurl.rs | 102 +++++++ src/types/misc/team_access.rs | 80 ------ test_data/example_external_trackers.json | 20 ++ test_data/example_external_wiki.json | 3 + test_data/example_internal_tracker.json | 5 + .../example_organization_permissions.json | 7 + test_data/example_permission.json | 5 + test_data/example_repo.json | 82 ++++++ test_data/example_repo_transfer.json | 110 ++++++++ test_data/example_search_results.json | 35 +++ 173 files changed, 3006 insertions(+), 585 deletions(-) create mode 100644 calc_stats.sh create mode 100644 progress.png create mode 100644 src/macros.rs create mode 100644 src/types/api/access_token.rs create mode 100644 src/types/api/add/collaborator.rs create mode 100644 src/types/api/add/label.rs create mode 100644 src/types/api/add/mod.rs create mode 100644 src/types/api/add/time.rs create mode 100644 src/types/api/add/topic.rs create mode 100644 src/types/api/annotated_tag.rs create mode 100644 src/types/api/annotated_tag_object.rs create mode 100644 src/types/api/api_settings.rs create mode 100644 src/types/api/attachment.rs create mode 100644 src/types/api/attachment_settings.rs create mode 100644 src/types/api/branch.rs create mode 100644 src/types/api/branch_protection.rs create mode 100644 src/types/api/changed_file.rs create mode 100644 src/types/api/combined_status.rs create mode 100644 src/types/api/comment.rs create mode 100644 src/types/api/commit.rs create mode 100644 src/types/api/commit_affected_files.rs create mode 100644 src/types/api/commit_date_options.rs create mode 100644 src/types/api/commit_meta.rs create mode 100644 src/types/api/commit_stats.rs create mode 100644 src/types/api/commit_status.rs create mode 100644 src/types/api/commit_status_state.rs create mode 100644 src/types/api/commit_user.rs create mode 100644 src/types/api/content_response.rs create mode 100644 src/types/api/create_hook_option_config.rs create mode 100644 src/types/api/creation/access_token.rs create mode 100644 src/types/api/creation/branch.rs create mode 100644 src/types/api/creation/branch_protection.rs create mode 100644 src/types/api/creation/comment.rs create mode 100644 src/types/api/creation/commit_status.rs create mode 100644 src/types/api/creation/email.rs create mode 100644 src/types/api/creation/file_options.rs create mode 100644 src/types/api/creation/gpg_key.rs create mode 100644 src/types/api/creation/hook.rs create mode 100644 src/types/api/creation/issue.rs create mode 100644 src/types/api/creation/key.rs create mode 100644 src/types/api/creation/milestone.rs create mode 100644 src/types/api/creation/oath_application.rs create mode 100644 src/types/api/creation/pull_request.rs create mode 100644 src/types/api/creation/pull_review.rs create mode 100644 src/types/api/creation/pull_review_comment.rs create mode 100644 src/types/api/creation/push_mirror.rs create mode 100644 src/types/api/creation/release.rs create mode 100644 src/types/api/creation/repository.rs create mode 100644 src/types/api/creation/request_review.rs create mode 100644 src/types/api/creation/tag.rs create mode 100644 src/types/api/creation/template_repository.rs create mode 100644 src/types/api/creation/wiki_page.rs create mode 100644 src/types/api/deploy_key.rs create mode 100644 src/types/api/dismiss_pull_review.rs create mode 100644 src/types/api/edit/attachment.rs create mode 100644 src/types/api/edit/branch_protection.rs create mode 100644 src/types/api/edit/comment.rs create mode 100644 src/types/api/edit/deadline.rs create mode 100644 src/types/api/edit/file_options.rs create mode 100644 src/types/api/edit/git_hook.rs create mode 100644 src/types/api/edit/issue.rs create mode 100644 src/types/api/edit/milestone.rs create mode 100644 src/types/api/edit/pull_request.rs create mode 100644 src/types/api/edit/reaction.rs create mode 100644 src/types/api/edit/release.rs create mode 100644 src/types/api/edit/repository.rs create mode 100644 src/types/api/edit/user_setting.rs create mode 100644 src/types/api/external/mod.rs create mode 100644 src/types/api/external/tracker.rs create mode 100644 src/types/api/external/wiki.rs create mode 100644 src/types/api/file_link_response.rs create mode 100644 src/types/api/git_blob.rs create mode 100644 src/types/api/git_entry.rs create mode 100644 src/types/api/git_hook.rs create mode 100644 src/types/api/git_object.rs create mode 100644 src/types/api/git_ref.rs create mode 100644 src/types/api/git_tree.rs create mode 100644 src/types/api/gpg_key.rs create mode 100644 src/types/api/gpg_key_email.rs create mode 100644 src/types/api/heat_map.rs create mode 100644 src/types/api/identity.rs create mode 100644 src/types/api/internal_tracker.rs create mode 100644 src/types/api/issue.rs create mode 100644 src/types/api/issue_form_field.rs create mode 100644 src/types/api/issue_form_field_type.rs create mode 100644 src/types/api/issue_template.rs create mode 100644 src/types/api/issue_template_labels.rs create mode 100644 src/types/api/merge.rs create mode 100644 src/types/api/migration.rs create mode 100644 src/types/api/milestone.rs create mode 100644 src/types/api/note.rs create mode 100644 src/types/api/oath_application.rs create mode 100644 src/types/api/organization_permission.rs create mode 100644 src/types/api/package.rs create mode 100644 src/types/api/package_file.rs create mode 100644 src/types/api/payload_commit.rs create mode 100644 src/types/api/payload_commit_verification.rs create mode 100644 src/types/api/payload_user.rs create mode 100644 src/types/api/public_key.rs create mode 100644 src/types/api/pull_request.rs create mode 100644 src/types/api/pull_request_branch_info.rs create mode 100644 src/types/api/pull_request_meta.rs create mode 100644 src/types/api/pull_review.rs create mode 100644 src/types/api/pull_review_comment.rs create mode 100644 src/types/api/push_mirror.rs create mode 100644 src/types/api/reaction.rs create mode 100644 src/types/api/release.rs create mode 100644 src/types/api/replace/label.rs create mode 100644 src/types/api/replace/mod.rs create mode 100644 src/types/api/repo_collaborator_permission.rs create mode 100644 src/types/api/repo_commit.rs create mode 100644 src/types/api/repo_meta.rs create mode 100644 src/types/api/repo_transfer.rs create mode 100644 src/types/api/repository.rs create mode 100644 src/types/api/repository_settings.rs create mode 100644 src/types/api/review_state.rs create mode 100644 src/types/api/search_results.rs create mode 100644 src/types/api/state_type.rs create mode 100644 src/types/api/stop_watch.rs create mode 100644 src/types/api/submit_pull_review.rs create mode 100644 src/types/api/tag.rs create mode 100644 src/types/api/timeline_comment.rs create mode 100644 src/types/api/topic.rs create mode 100644 src/types/api/tracked_time.rs create mode 100644 src/types/api/transfer.rs create mode 100644 src/types/api/ui_settings.rs create mode 100644 src/types/api/user_setting.rs create mode 100644 src/types/api/watch_info.rs create mode 100644 src/types/api/wiki_commit.rs create mode 100644 src/types/api/wiki_commit_list.rs create mode 100644 src/types/api/wiki_page.rs delete mode 100644 src/types/misc/active.rs delete mode 100644 src/types/misc/admin.rs create mode 100644 src/types/misc/boolean_enums/allow/mod.rs create mode 100644 src/types/misc/boolean_enums/can/mod.rs create mode 100644 src/types/misc/boolean_enums/enable/mod.rs create mode 100644 src/types/misc/boolean_enums/has/mod.rs create mode 100644 src/types/misc/boolean_enums/is/mod.rs create mode 100644 src/types/misc/boolean_enums/mod.rs delete mode 100644 src/types/misc/can_create_org_repo.rs delete mode 100644 src/types/misc/exclusive.rs create mode 100644 src/types/misc/external_issue_format.rs delete mode 100644 src/types/misc/includes_all_repositories.rs rename src/types/misc/{url.rs => optional_url.rs} (100%) create mode 100644 src/types/misc/permission.rs create mode 100644 src/types/misc/sshurl.rs delete mode 100644 src/types/misc/team_access.rs create mode 100644 test_data/example_external_trackers.json create mode 100644 test_data/example_external_wiki.json create mode 100644 test_data/example_internal_tracker.json create mode 100644 test_data/example_organization_permissions.json create mode 100644 test_data/example_permission.json create mode 100644 test_data/example_repo.json create mode 100644 test_data/example_repo_transfer.json create mode 100644 test_data/example_search_results.json diff --git a/README.md b/README.md index c42f4ae..603d39d 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ +![Progress](./progress.png) + docs: https://codeberg.org/api/swagger#/organization/orgCreateHook diff --git a/calc_stats.sh b/calc_stats.sh new file mode 100644 index 0000000..4b5d261 --- /dev/null +++ b/calc_stats.sh @@ -0,0 +1,8 @@ +ENUMERATOR=$(rg "to-todo" -c -I | paste -sd+ | bc) +DENOMINATOR=$(rg "pub mod" ./src/types/api/ -c -I | paste -sd+ | bc) + +echo "$ENUMERATOR.0/$DENOMINATOR.0" +UNDONE=$(echo "scale=2; ($ENUMERATOR * 100)/$DENOMINATOR" | bc ) +DONE=$(echo "scale=2; 100 - $UNDONE" | bc) +echo done: $DONE % +echo undone: $UNDONE % diff --git a/progress.png b/progress.png new file mode 100644 index 0000000000000000000000000000000000000000..93ba2608026856ebc4dc2c236b104131ed9e0791 GIT binary patch literal 34171 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 { + implement_boolean_enum!($module_name, $enum_name { Yes, No }); + }; + ($module_name:ident, $enum_name:ident { $yes_variant:ident, $no_variant:ident }) => { + pub mod $module_name { + use clap::ValueEnum; + use strum::{Display, EnumIs, EnumIter, EnumString}; + + #[derive( + Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs, + )] + pub enum $enum_name { + $yes_variant, + $no_variant, + } + + mod serde { + use serde::de::Visitor; + use serde::{Deserialize, Serialize}; + + use super::$enum_name; + + impl Serialize for $enum_name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bool(matches!(*self, $enum_name::$yes_variant)) + } + } + + struct PrivateVisitor; + + impl<'de> Visitor<'de> for PrivateVisitor { + type Value = $enum_name; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a boolean value (true/false)") + } + + fn visit_bool(self, v: bool) -> Result + where + E: serde::de::Error, + { + if v { + Ok($enum_name::$yes_variant) + } else { + Ok($enum_name::$no_variant) + } + } + } + + impl<'de> Deserialize<'de> for $enum_name { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_bool(PrivateVisitor) + } + } + } + + mod from { + use super::$enum_name; + + impl Into for $enum_name { + fn into(self) -> bool { + match self { + $enum_name::$yes_variant => true, + $enum_name::$no_variant => false, + } + } + } + } + + #[cfg(test)] + mod tests { + use super::$enum_name; + + #[test] + fn deserialize_true() { + let input = "true"; + let val: $enum_name = serde_json::from_str(input).unwrap(); + assert_eq!($enum_name::$yes_variant, val); + } + + #[test] + fn deserialize_false() { + let input = "false"; + let val: $enum_name = serde_json::from_str(input).unwrap(); + assert_eq!($enum_name::$no_variant, val); + } + + #[test] + fn serialize_true() { + let input = $enum_name::$yes_variant; + let val = serde_json::to_string(&input).unwrap(); + assert_eq!(val.as_str(), "true"); + } + + #[test] + fn serialize_false() { + let input = $enum_name::$no_variant; + let val = serde_json::to_string(&input).unwrap(); + assert_eq!(val.as_str(), "false"); + } + } + } + }; +} diff --git a/src/types/api/access_token.rs b/src/types/api/access_token.rs new file mode 100644 index 0000000..b064958 --- /dev/null +++ b/src/types/api/access_token.rs @@ -0,0 +1,9 @@ +// [AccessToken represents an API access token.{ +// id integer($int64) +// name string +// scopes [ +// x-go-name: Scopes +// string] +// sha1 string +// token_last_eight string +// }] diff --git a/src/types/api/add/collaborator.rs b/src/types/api/add/collaborator.rs new file mode 100644 index 0000000..847666a --- /dev/null +++ b/src/types/api/add/collaborator.rs @@ -0,0 +1,6 @@ +// AddCollaboratorOption{ +// description: +// AddCollaboratorOption options when adding a user as a collaborator of a repository +// +// permission string +// } diff --git a/src/types/api/add/label.rs b/src/types/api/add/label.rs new file mode 100644 index 0000000..0b41c8e --- /dev/null +++ b/src/types/api/add/label.rs @@ -0,0 +1,10 @@ +// IssueLabelsOption{ +// description: +// IssueLabelsOption a collection of labels +// +// labels [ +// x-go-name: Labels +// list of label IDs +// +// integer($int64)] +// } diff --git a/src/types/api/add/mod.rs b/src/types/api/add/mod.rs new file mode 100644 index 0000000..0dd34a7 --- /dev/null +++ b/src/types/api/add/mod.rs @@ -0,0 +1,5 @@ +/* to-todo */ +pub mod collaborator; +/* to-todo */ pub mod label; +/* to-todo */ pub mod time; +/* to-todo */ pub mod topic; diff --git a/src/types/api/add/time.rs b/src/types/api/add/time.rs new file mode 100644 index 0000000..ff9d75e --- /dev/null +++ b/src/types/api/add/time.rs @@ -0,0 +1,12 @@ +// AddTimeOption{ +// description: +// AddTimeOption options for adding time to an issue +// +// created string($date-time) +// time* integer($int64) +// time in seconds +// +// user_name string +// User who spent the time (optional) +// +// } diff --git a/src/types/api/add/topic.rs b/src/types/api/add/topic.rs new file mode 100644 index 0000000..0b8dd99 --- /dev/null +++ b/src/types/api/add/topic.rs @@ -0,0 +1,10 @@ +// RepoTopicOptions{ +// description: +// RepoTopicOptions a collection of repo topic names +// +// topics [ +// x-go-name: Topics +// list of topic names +// +// string] +// } diff --git a/src/types/api/annotated_tag.rs b/src/types/api/annotated_tag.rs new file mode 100644 index 0000000..053d01d --- /dev/null +++ b/src/types/api/annotated_tag.rs @@ -0,0 +1,12 @@ +// AnnotatedTag{ +// description: +// AnnotatedTag represents an annotated tag +// +// message string +// object AnnotatedTagObject{...} +// sha string +// tag string +// tagger CommitUser contains information of a user in the context of a commit.{...} +// url string +// verification PayloadCommitVerification{...} +// } diff --git a/src/types/api/annotated_tag_object.rs b/src/types/api/annotated_tag_object.rs new file mode 100644 index 0000000..a6e3be1 --- /dev/null +++ b/src/types/api/annotated_tag_object.rs @@ -0,0 +1,8 @@ +// AnnotatedTagObject{ +// description: +// AnnotatedTagObject contains meta information of the tag object +// +// sha string +// type string +// url string +// } diff --git a/src/types/api/api_settings.rs b/src/types/api/api_settings.rs new file mode 100644 index 0000000..0e35b85 --- /dev/null +++ b/src/types/api/api_settings.rs @@ -0,0 +1,9 @@ +// GeneralAPISettings{ +// description: +// GeneralAPISettings contains global api settings exposed by it +// +// default_git_trees_per_page integer($int64) +// default_max_blob_size integer($int64) +// default_paging_num integer($int64) +// max_response_items integer($int64) +// } diff --git a/src/types/api/attachment.rs b/src/types/api/attachment.rs new file mode 100644 index 0000000..22b400b --- /dev/null +++ b/src/types/api/attachment.rs @@ -0,0 +1,14 @@ +// [ +// x-go-name: Attachments +// Attachment{ +// description: +// Attachment a generic attachment +// +// browser_download_url string +// created_at string($date-time) +// download_count integer($int64) +// id integer($int64) +// name string +// size integer($int64) +// uuid string +// }] diff --git a/src/types/api/attachment_settings.rs b/src/types/api/attachment_settings.rs new file mode 100644 index 0000000..5e636a0 --- /dev/null +++ b/src/types/api/attachment_settings.rs @@ -0,0 +1,9 @@ +// GeneralAttachmentSettings{ +// description: +// GeneralAttachmentSettings contains global Attachment settings exposed by API +// +// allowed_types string +// enabled boolean +// max_files integer($int64) +// max_size integer($int64) +// } diff --git a/src/types/api/branch.rs b/src/types/api/branch.rs new file mode 100644 index 0000000..79f2744 --- /dev/null +++ b/src/types/api/branch.rs @@ -0,0 +1,16 @@ +// [Branch{ +// description: +// Branch represents a repository branch +// +// commit PayloadCommit{...} +// effective_branch_protection_name string +// enable_status_check boolean +// name string +// protected boolean +// required_approvals integer($int64) +// status_check_contexts [ +// x-go-name: StatusCheckContexts +// string] +// user_can_merge boolean +// user_can_push boolean +// }] diff --git a/src/types/api/branch_protection.rs b/src/types/api/branch_protection.rs new file mode 100644 index 0000000..1f11ed2 --- /dev/null +++ b/src/types/api/branch_protection.rs @@ -0,0 +1,46 @@ +// [BranchProtection{ +// description: +// BranchProtection represents a branch protection for a repository +// +// approvals_whitelist_teams [ +// x-go-name: ApprovalsWhitelistTeams +// string] +// approvals_whitelist_username [ +// x-go-name: ApprovalsWhitelistUsernames +// string] +// block_on_official_review_requests boolean +// block_on_outdated_branch boolean +// block_on_rejected_reviews boolean +// branch_name string +// Deprecated: true +// +// created_at string($date-time) +// dismiss_stale_approvals boolean +// enable_approvals_whitelist boolean +// enable_merge_whitelist boolean +// enable_push boolean +// enable_push_whitelist boolean +// enable_status_check boolean +// merge_whitelist_teams [ +// x-go-name: MergeWhitelistTeams +// string] +// merge_whitelist_usernames [ +// x-go-name: MergeWhitelistUsernames +// string] +// protected_file_patterns string +// push_whitelist_deploy_keys boolean +// push_whitelist_teams [ +// x-go-name: PushWhitelistTeams +// string] +// push_whitelist_usernames [ +// x-go-name: PushWhitelistUsernames +// string] +// require_signed_commits boolean +// required_approvals integer($int64) +// rule_name string +// status_check_contexts [ +// x-go-name: StatusCheckContexts +// string] +// unprotected_file_patterns string +// updated_at string($date-time) +// }] diff --git a/src/types/api/changed_file.rs b/src/types/api/changed_file.rs new file mode 100644 index 0000000..5c9cd53 --- /dev/null +++ b/src/types/api/changed_file.rs @@ -0,0 +1,14 @@ +// [ChangedFile{ +// description: +// ChangedFile store information about files affected by the pull request +// +// additions integer($int64) +// changes integer($int64) +// contents_url string +// deletions integer($int64) +// filename string +// html_url string +// previous_filename string +// raw_url string +// status string +// }] diff --git a/src/types/api/combined_status.rs b/src/types/api/combined_status.rs new file mode 100644 index 0000000..3679560 --- /dev/null +++ b/src/types/api/combined_status.rs @@ -0,0 +1,14 @@ +// CombinedStatus{ +// description: +// CombinedStatus holds the combined state of several statuses for a single commit +// +// commit_url string +// repository Repository{...} +// sha string +// state CommitStatusState[...] +// statuses [ +// x-go-name: Statuses +// CommitStatus{...}] +// total_count integer($int64) +// url string +// } diff --git a/src/types/api/comment.rs b/src/types/api/comment.rs new file mode 100644 index 0000000..74c5e72 --- /dev/null +++ b/src/types/api/comment.rs @@ -0,0 +1,18 @@ +// Comment{ +// description: +// Comment represents a comment on a commit or issue +// +// assets [ +// x-go-name: Attachments +// Attachment{...}] +// body string +// created_at string($date-time) +// html_url string +// id integer($int64) +// issue_url string +// original_author string +// original_author_id integer($int64) +// pull_request_url string +// updated_at string($date-time) +// user User{...} +// }] diff --git a/src/types/api/commit.rs b/src/types/api/commit.rs new file mode 100644 index 0000000..5206726 --- /dev/null +++ b/src/types/api/commit.rs @@ -0,0 +1,16 @@ +// [Commit contains information generated from a Git commit.{ +// author User{...} +// commit RepoCommit contains information of a commit in the context of a repository.{...} +// committer User{...} +// created string($date-time) +// files [ +// x-go-name: Files +// CommitAffectedFiles{...}] +// html_url string +// parents [ +// x-go-name: Parents +// CommitMeta contains meta information of a commit in terms of API.{...}] +// sha string +// stats CommitStats{...} +// url string +// }] diff --git a/src/types/api/commit_affected_files.rs b/src/types/api/commit_affected_files.rs new file mode 100644 index 0000000..f2630a0 --- /dev/null +++ b/src/types/api/commit_affected_files.rs @@ -0,0 +1,6 @@ +// CommitAffectedFiles{ +// description: +// CommitAffectedFiles store information about files affected by the commit +// +// filename string +// }] diff --git a/src/types/api/commit_date_options.rs b/src/types/api/commit_date_options.rs new file mode 100644 index 0000000..78ce3a4 --- /dev/null +++ b/src/types/api/commit_date_options.rs @@ -0,0 +1,7 @@ +// CommitDateOptions{ +// description: +// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE +// +// author string($date-time) +// committer string($date-time) +// } diff --git a/src/types/api/commit_meta.rs b/src/types/api/commit_meta.rs new file mode 100644 index 0000000..b1a4a7e --- /dev/null +++ b/src/types/api/commit_meta.rs @@ -0,0 +1,5 @@ +// CommitMeta contains meta information of a commit in terms of API.{ +// created string($date-time) +// sha string +// url string +// } diff --git a/src/types/api/commit_stats.rs b/src/types/api/commit_stats.rs new file mode 100644 index 0000000..af251c0 --- /dev/null +++ b/src/types/api/commit_stats.rs @@ -0,0 +1,8 @@ +// CommitStats{ +// description: +// CommitStats is statistics for a RepoCommit +// +// additions integer($int64) +// deletions integer($int64) +// total integer($int64) +// } diff --git a/src/types/api/commit_status.rs b/src/types/api/commit_status.rs new file mode 100644 index 0000000..1b42f0c --- /dev/null +++ b/src/types/api/commit_status.rs @@ -0,0 +1,14 @@ +// CommitStatus{ +// description: +// CommitStatus holds a single status of a single Commit +// +// context string +// created_at string($date-time) +// creator User{...} +// description string +// id integer($int64) +// status CommitStatusState[...] +// target_url string +// updated_at string($date-time) +// url string +// }] diff --git a/src/types/api/commit_status_state.rs b/src/types/api/commit_status_state.rs new file mode 100644 index 0000000..66234a2 --- /dev/null +++ b/src/types/api/commit_status_state.rs @@ -0,0 +1,3 @@ +// CommitStatusStatestring +// CommitStatusState holds the state of a CommitStatus +// It can be "pending", "success", "error", "failure", and "warning" diff --git a/src/types/api/commit_user.rs b/src/types/api/commit_user.rs new file mode 100644 index 0000000..7d223a5 --- /dev/null +++ b/src/types/api/commit_user.rs @@ -0,0 +1,5 @@ +// CommitUser contains information of a user in the context of a commit.{ +// date string +// email string($email) +// name string +// } diff --git a/src/types/api/content_response.rs b/src/types/api/content_response.rs new file mode 100644 index 0000000..98537da --- /dev/null +++ b/src/types/api/content_response.rs @@ -0,0 +1,30 @@ +// [ContentsResponse{ +// description: +// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content +// +// _links FileLinksResponse{...} +// content string +// content is populated when type is file, otherwise null +// +// download_url string +// encoding string +// encoding is populated when type is file, otherwise null +// +// git_url string +// html_url string +// last_commit_sha string +// name string +// path string +// sha string +// size integer($int64) +// submodule_git_url string +// submodule_git_url is populated when type is submodule, otherwise null +// +// target string +// target is populated when type is symlink, otherwise null +// +// type string +// type will be file, dir, symlink, or submodule +// +// url string +// }] diff --git a/src/types/api/create_hook_option_config.rs b/src/types/api/create_hook_option_config.rs new file mode 100644 index 0000000..5dad427 --- /dev/null +++ b/src/types/api/create_hook_option_config.rs @@ -0,0 +1,7 @@ +// CreateHookOptionConfig{ +// description: +// CreateHookOptionConfig has all config options in it +// required are "content_type" and "url" Required +// +// < * >: string +// } diff --git a/src/types/api/creation/access_token.rs b/src/types/api/creation/access_token.rs new file mode 100644 index 0000000..ec8c3bf --- /dev/null +++ b/src/types/api/creation/access_token.rs @@ -0,0 +1,9 @@ +// CreateAccessTokenOption{ +// description: +// CreateAccessTokenOption options when create access token +// +// name* string +// scopes [ +// x-go-name: Scopes +// string] +// } diff --git a/src/types/api/creation/branch.rs b/src/types/api/creation/branch.rs new file mode 100644 index 0000000..b05f953 --- /dev/null +++ b/src/types/api/creation/branch.rs @@ -0,0 +1,13 @@ +// CreateBranchRepoOption{ +// description: +// CreateBranchRepoOption options when creating a branch in a repository +// +// new_branch_name* string +// uniqueItems: true +// Name of the branch to create +// +// old_branch_name string +// uniqueItems: true +// Name of the old branch to create from +// +// } diff --git a/src/types/api/creation/branch_protection.rs b/src/types/api/creation/branch_protection.rs new file mode 100644 index 0000000..c1f1d3e --- /dev/null +++ b/src/types/api/creation/branch_protection.rs @@ -0,0 +1,44 @@ +// CreateBranchProtectionOption{ +// description: +// CreateBranchProtectionOption options for creating a branch protection +// +// approvals_whitelist_teams [ +// x-go-name: ApprovalsWhitelistTeams +// string] +// approvals_whitelist_username [ +// x-go-name: ApprovalsWhitelistUsernames +// string] +// block_on_official_review_requests boolean +// block_on_outdated_branch boolean +// block_on_rejected_reviews boolean +// branch_name string +// Deprecated: true +// +// dismiss_stale_approvals boolean +// enable_approvals_whitelist boolean +// enable_merge_whitelist boolean +// enable_push boolean +// enable_push_whitelist boolean +// enable_status_check boolean +// merge_whitelist_teams [ +// x-go-name: MergeWhitelistTeams +// string] +// merge_whitelist_usernames [ +// x-go-name: MergeWhitelistUsernames +// string] +// protected_file_patterns string +// push_whitelist_deploy_keys boolean +// push_whitelist_teams [ +// x-go-name: PushWhitelistTeams +// string] +// push_whitelist_usernames [ +// x-go-name: PushWhitelistUsernames +// string] +// require_signed_commits boolean +// required_approvals integer($int64) +// rule_name string +// status_check_contexts [ +// x-go-name: StatusCheckContexts +// string] +// unprotected_file_patterns string +// } diff --git a/src/types/api/creation/comment.rs b/src/types/api/creation/comment.rs new file mode 100644 index 0000000..d20ab3e --- /dev/null +++ b/src/types/api/creation/comment.rs @@ -0,0 +1,6 @@ +// CreateIssueCommentOption{ +// description: +// CreateIssueCommentOption options for creating a comment on an issue +// +// body* string +// } diff --git a/src/types/api/creation/commit_status.rs b/src/types/api/creation/commit_status.rs new file mode 100644 index 0000000..b81e2fe --- /dev/null +++ b/src/types/api/creation/commit_status.rs @@ -0,0 +1,9 @@ +// CreateStatusOption{ +// description: +// CreateStatusOption holds the information needed to create a new CommitStatus for a Commit +// +// context string +// description string +// state CommitStatusState[...] +// target_url string +// } diff --git a/src/types/api/creation/email.rs b/src/types/api/creation/email.rs new file mode 100644 index 0000000..785b5da --- /dev/null +++ b/src/types/api/creation/email.rs @@ -0,0 +1,10 @@ +// CreateEmailOption{ +// description: +// CreateEmailOption options when creating email addresses +// +// emails [ +// x-go-name: Emails +// email addresses to add +// +// string] +// } diff --git a/src/types/api/creation/file_options.rs b/src/types/api/creation/file_options.rs new file mode 100644 index 0000000..36ccec1 --- /dev/null +++ b/src/types/api/creation/file_options.rs @@ -0,0 +1,24 @@ +// CreateFileOptions{ +// description: +// CreateFileOptions options for creating files +// Note: author and committer are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) +// +// author Identity{...} +// branch string +// branch (optional) to base this file from. if not given, the default branch is used +// +// committer Identity{...} +// content* string +// content must be base64 encoded +// +// dates CommitDateOptions{...} +// message string +// message (optional) for the commit of this file. if not supplied, a default message will be used +// +// new_branch string +// new_branch (optional) will make a new branch from branch before creating the file +// +// signoff boolean +// Add a Signed-off-by trailer by the committer at the end of the commit log message. +// +// } diff --git a/src/types/api/creation/gpg_key.rs b/src/types/api/creation/gpg_key.rs new file mode 100644 index 0000000..3e68ecc --- /dev/null +++ b/src/types/api/creation/gpg_key.rs @@ -0,0 +1,10 @@ +// CreateGPGKeyOption{ +// description: +// CreateGPGKeyOption options create user GPG key +// +// armored_public_key* string +// uniqueItems: true +// An armored GPG key to add +// +// armored_signature string +// } diff --git a/src/types/api/creation/hook.rs b/src/types/api/creation/hook.rs new file mode 100644 index 0000000..3875154 --- /dev/null +++ b/src/types/api/creation/hook.rs @@ -0,0 +1,16 @@ +// CreateHookOption{ +// description: +// CreateHookOption options when create a hook +// +// active boolean +// default: false +// authorization_header string +// branch_filter string +// config* CreateHookOptionConfig{...} +// events [ +// x-go-name: Events +// string] +// type* string +// Enum: +// [ forgejo, dingtalk, discord, gitea, gogs, msteams, slack, telegram, feishu, wechatwork, packagist ] +// } diff --git a/src/types/api/creation/issue.rs b/src/types/api/creation/issue.rs new file mode 100644 index 0000000..4a711aa --- /dev/null +++ b/src/types/api/creation/issue.rs @@ -0,0 +1,24 @@ +// CreateIssueOption{ +// description: +// CreateIssueOption options to create one issue +// +// assignee string +// deprecated +// +// assignees [ +// x-go-name: Assignees +// string] +// body string +// closed [...] +// due_date string($date-time) +// labels [ +// x-go-name: Labels +// list of label ids +// +// integer($int64)] +// milestone integer($int64) +// milestone id +// +// ref string +// title* string +// } diff --git a/src/types/api/creation/key.rs b/src/types/api/creation/key.rs new file mode 100644 index 0000000..9936a3e --- /dev/null +++ b/src/types/api/creation/key.rs @@ -0,0 +1,16 @@ +// CreateKeyOption{ +// description: +// CreateKeyOption options when creating a key +// +// key* string +// uniqueItems: true +// An armored SSH key to add +// +// read_only boolean +// Describe if the key has only read access or read/write +// +// title* string +// uniqueItems: true +// Title of the key to add +// +// } diff --git a/src/types/api/creation/label.rs b/src/types/api/creation/label.rs index 07f6c6a..ba1b44e 100644 --- a/src/types/api/creation/label.rs +++ b/src/types/api/creation/label.rs @@ -2,8 +2,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; +use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; -use crate::types::misc::exclusive::Exclusive; /// CreateLabelOption represents options for creating a label. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -29,8 +29,8 @@ mod tests { use palette::rgb::Rgb; use crate::types::api::creation::label::CreateLabelOption; + use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; - use crate::types::misc::exclusive::Exclusive; #[test] fn deserialize_create_label_option() { diff --git a/src/types/api/creation/milestone.rs b/src/types/api/creation/milestone.rs new file mode 100644 index 0000000..6b867da --- /dev/null +++ b/src/types/api/creation/milestone.rs @@ -0,0 +1,11 @@ +// CreateMilestoneOption{ +// description: +// CreateMilestoneOption options for creating a milestone +// +// description string +// due_on string($date-time) +// state string +// Enum: +// [ open, closed ] +// title string +// } diff --git a/src/types/api/creation/mod.rs b/src/types/api/creation/mod.rs index b3e7ec7..8407bda 100644 --- a/src/types/api/creation/mod.rs +++ b/src/types/api/creation/mod.rs @@ -1,2 +1,27 @@ pub mod label; pub mod organization; + +/* to-todo */ +pub mod access_token; +/* to-todo */ pub mod branch; +/* to-todo */ pub mod branch_protection; +/* to-todo */ pub mod comment; +/* to-todo */ pub mod commit_status; +/* to-todo */ pub mod email; +/* to-todo */ pub mod file_options; +/* to-todo */ pub mod gpg_key; +/* to-todo */ pub mod hook; +/* to-todo */ pub mod issue; +/* to-todo */ pub mod key; +/* to-todo */ pub mod milestone; +/* to-todo */ pub mod oath_application; +/* to-todo */ pub mod pull_request; +/* to-todo */ pub mod pull_review; +/* to-todo */ pub mod pull_review_comment; +/* to-todo */ pub mod push_mirror; +/* to-todo */ pub mod release; +/* to-todo */ pub mod repository; +/* to-todo */ pub mod request_review; +/* to-todo */ pub mod tag; +/* to-todo */ pub mod template_repository; +/* to-todo */ pub mod wiki_page; diff --git a/src/types/api/creation/oath_application.rs b/src/types/api/creation/oath_application.rs new file mode 100644 index 0000000..75c2f80 --- /dev/null +++ b/src/types/api/creation/oath_application.rs @@ -0,0 +1,10 @@ +// CreateOAuth2ApplicationOptions{ +// description: +// CreateOAuth2ApplicationOptions holds options to create an oauth2 application +// +// confidential_client boolean +// name string +// redirect_uris [ +// x-go-name: RedirectURIs +// string] +// } diff --git a/src/types/api/creation/organization.rs b/src/types/api/creation/organization.rs index d50fc1d..c60cd46 100644 --- a/src/types/api/creation/organization.rs +++ b/src/types/api/creation/organization.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; use std::fmt::Display; -use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; -use crate::types::misc::url::OptionalUrl; +use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; +use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; /// CreateOrgOption represents options for creating an organization @@ -15,7 +15,7 @@ pub struct CreateOrgOption { /// Location of the organization as a string pub location: String, /// Boolean flag indicating if repo admin can change team access - pub repo_admin_change_team_access: RepoAdminCanChangeTeamAccess, + pub repo_admin_change_team_access: CanRepoAdminChangeTeamAccess, /// The organization's username pub username: String, /// Visibility of the organization @@ -38,8 +38,8 @@ mod tests { use url::Url; use crate::types::api::creation::organization::CreateOrgOption; - use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; - use crate::types::misc::url::OptionalUrl; + use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; + use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; #[test] @@ -50,7 +50,7 @@ mod tests { description: String::from("Sample organization"), full_name: String::from("SampleOrg"), location: String::from("Sample City, Country"), - repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::Yes, + repo_admin_change_team_access: CanRepoAdminChangeTeamAccess::Yes, username: String::from("sample_org"), visibility: Visibility::Public, website: OptionalUrl::Some(Url::from_str("https://sample.org").unwrap()), diff --git a/src/types/api/creation/pull_request.rs b/src/types/api/creation/pull_request.rs new file mode 100644 index 0000000..c4f82c9 --- /dev/null +++ b/src/types/api/creation/pull_request.rs @@ -0,0 +1,18 @@ +// CreatePullRequestOption{ +// description: +// CreatePullRequestOption options when creating a pull request +// +// assignee string +// assignees [ +// x-go-name: Assignees +// string] +// base string +// body string +// due_date string($date-time) +// head string +// labels [ +// x-go-name: Labels +// integer($int64)] +// milestone integer($int64) +// title string +// } diff --git a/src/types/api/creation/pull_review.rs b/src/types/api/creation/pull_review.rs new file mode 100644 index 0000000..950464a --- /dev/null +++ b/src/types/api/creation/pull_review.rs @@ -0,0 +1,11 @@ +// CreatePullReviewOptions{ +// description: +// CreatePullReviewOptions are options to create a pull review +// +// body string +// comments [ +// x-go-name: Comments +// CreatePullReviewComment{...}] +// commit_id string +// event ReviewStateType[...] +// } diff --git a/src/types/api/creation/pull_review_comment.rs b/src/types/api/creation/pull_review_comment.rs new file mode 100644 index 0000000..51ceaf1 --- /dev/null +++ b/src/types/api/creation/pull_review_comment.rs @@ -0,0 +1,15 @@ +// CreatePullReviewComment{ +// description: +// CreatePullReviewComment represent a review comment for creation api +// +// body string +// new_position integer($int64) +// if comment to new file line or 0 +// +// old_position integer($int64) +// if comment to old file line or 0 +// +// path string +// the tree path +// +// }] diff --git a/src/types/api/creation/push_mirror.rs b/src/types/api/creation/push_mirror.rs new file mode 100644 index 0000000..5fa60bb --- /dev/null +++ b/src/types/api/creation/push_mirror.rs @@ -0,0 +1,7 @@ +// CreatePushMirrorOption represents need information to create a push mirror of a repository.{ +// interval string +// remote_address string +// remote_password string +// remote_username string +// sync_on_commit boolean +// } diff --git a/src/types/api/creation/release.rs b/src/types/api/creation/release.rs new file mode 100644 index 0000000..b97debc --- /dev/null +++ b/src/types/api/creation/release.rs @@ -0,0 +1,11 @@ +// CreateReleaseOption{ +// description: +// CreateReleaseOption options when creating a release +// +// body string +// draft boolean +// name string +// prerelease boolean +// tag_name* string +// target_commitish string +// } diff --git a/src/types/api/creation/repository.rs b/src/types/api/creation/repository.rs new file mode 100644 index 0000000..21560d0 --- /dev/null +++ b/src/types/api/creation/repository.rs @@ -0,0 +1,39 @@ +//CreateRepoOption{ +//description: +//CreateRepoOption options when creating repository +// +//auto_init boolean +//Whether the repository should be auto-initialized? +// +//default_branch string +//DefaultBranch of the repository (used when initializes and in template) +// +//description string +//Description of the repository to create +// +//gitignores string +//Gitignores to use +// +//issue_labels string +//Label-Set to use +// +//license string +//License to use +// +//name* string +//uniqueItems: true +//Name of the repository to create +// +//private boolean +//Whether the repository is private +// +//readme [...] +//template boolean +//Whether the repository is template +// +//trust_model string +//TrustModel of the repository +// +//Enum: +//[ default, collaborator, committer, collaboratorcommitter ] +//} diff --git a/src/types/api/creation/request_review.rs b/src/types/api/creation/request_review.rs new file mode 100644 index 0000000..b71683d --- /dev/null +++ b/src/types/api/creation/request_review.rs @@ -0,0 +1,11 @@ +// PullReviewRequestOptions{ +// description: +// PullReviewRequestOptions are options to add or remove pull review requests +// +// reviewers [ +// x-go-name: Reviewers +// string] +// team_reviewers [ +// x-go-name: TeamReviewers +// string] +// } diff --git a/src/types/api/creation/tag.rs b/src/types/api/creation/tag.rs new file mode 100644 index 0000000..a324fed --- /dev/null +++ b/src/types/api/creation/tag.rs @@ -0,0 +1,8 @@ +// CreateTagOption{ +// description: +// CreateTagOption options when creating a tag +// +// message string +// tag_name* string +// target string +// } diff --git a/src/types/api/creation/template_repository.rs b/src/types/api/creation/template_repository.rs new file mode 100644 index 0000000..acab8b0 --- /dev/null +++ b/src/types/api/creation/template_repository.rs @@ -0,0 +1,39 @@ +// GenerateRepoOption{ +// description: +// GenerateRepoOption options when creating repository using a template +// +// avatar boolean +// include avatar of the template repo +// +// default_branch string +// Default branch of the new repository +// +// description string +// Description of the repository to create +// +// git_content boolean +// include git content of default branch in template repo +// +// git_hooks boolean +// include git hooks in template repo +// +// labels boolean +// include labels in template repo +// +// name* string +// uniqueItems: true +// Name of the repository to create +// +// owner* string +// The organization or person who will own the new repository +// +// private boolean +// Whether the repository is private +// +// topics boolean +// include topics in template repo +// +// webhooks boolean +// include webhooks in template repo +// +// } diff --git a/src/types/api/creation/wiki_page.rs b/src/types/api/creation/wiki_page.rs new file mode 100644 index 0000000..824b531 --- /dev/null +++ b/src/types/api/creation/wiki_page.rs @@ -0,0 +1,14 @@ +// CreateWikiPageOptions{ +// description: +// CreateWikiPageOptions form for creating wiki +// +// content_base64 string +// content must be base64 encoded +// +// message string +// optional commit message summarizing the change +// +// title string +// page title. leave empty to keep unchanged +// +// } diff --git a/src/types/api/deploy_key.rs b/src/types/api/deploy_key.rs new file mode 100644 index 0000000..17d2142 --- /dev/null +++ b/src/types/api/deploy_key.rs @@ -0,0 +1,14 @@ +// [DeployKey{ +// description: +// DeployKey a deploy key +// +// created_at string($date-time) +// fingerprint string +// id integer($int64) +// key string +// key_id integer($int64) +// read_only boolean +// repository Repository{...} +// title string +// url string +// }] diff --git a/src/types/api/dismiss_pull_review.rs b/src/types/api/dismiss_pull_review.rs new file mode 100644 index 0000000..9ac4e33 --- /dev/null +++ b/src/types/api/dismiss_pull_review.rs @@ -0,0 +1,7 @@ +// DismissPullReviewOptions{ +// description: +// DismissPullReviewOptions are options to dismiss a pull review +// +// message string +// priors boolean +// } diff --git a/src/types/api/edit/attachment.rs b/src/types/api/edit/attachment.rs new file mode 100644 index 0000000..39ff662 --- /dev/null +++ b/src/types/api/edit/attachment.rs @@ -0,0 +1,6 @@ +// EditAttachmentOptions{ +// description: +// EditAttachmentOptions options for editing attachments +// +// name string +// } diff --git a/src/types/api/edit/branch_protection.rs b/src/types/api/edit/branch_protection.rs new file mode 100644 index 0000000..950739e --- /dev/null +++ b/src/types/api/edit/branch_protection.rs @@ -0,0 +1,40 @@ +// EditBranchProtectionOption{ +// description: +// EditBranchProtectionOption options for editing a branch protection +// +// approvals_whitelist_teams [ +// x-go-name: ApprovalsWhitelistTeams +// string] +// approvals_whitelist_username [ +// x-go-name: ApprovalsWhitelistUsernames +// string] +// block_on_official_review_requests boolean +// block_on_outdated_branch boolean +// block_on_rejected_reviews boolean +// dismiss_stale_approvals boolean +// enable_approvals_whitelist boolean +// enable_merge_whitelist boolean +// enable_push boolean +// enable_push_whitelist boolean +// enable_status_check boolean +// merge_whitelist_teams [ +// x-go-name: MergeWhitelistTeams +// string] +// merge_whitelist_usernames [ +// x-go-name: MergeWhitelistUsernames +// string] +// protected_file_patterns string +// push_whitelist_deploy_keys boolean +// push_whitelist_teams [ +// x-go-name: PushWhitelistTeams +// string] +// push_whitelist_usernames [ +// x-go-name: PushWhitelistUsernames +// string] +// require_signed_commits boolean +// required_approvals integer($int64) +// status_check_contexts [ +// x-go-name: StatusCheckContexts +// string] +// unprotected_file_patterns string +// } diff --git a/src/types/api/edit/comment.rs b/src/types/api/edit/comment.rs new file mode 100644 index 0000000..5300b34 --- /dev/null +++ b/src/types/api/edit/comment.rs @@ -0,0 +1,6 @@ +// EditIssueCommentOption{ +// description: +// EditIssueCommentOption options for editing a comment +// +// body* string +// } diff --git a/src/types/api/edit/deadline.rs b/src/types/api/edit/deadline.rs new file mode 100644 index 0000000..5c82bfd --- /dev/null +++ b/src/types/api/edit/deadline.rs @@ -0,0 +1,6 @@ +// EditDeadlineOption{ +// description: +// EditDeadlineOption options for creating a deadline +// +// due_date* string($date-time) +// } diff --git a/src/types/api/edit/file_options.rs b/src/types/api/edit/file_options.rs new file mode 100644 index 0000000..23a92a6 --- /dev/null +++ b/src/types/api/edit/file_options.rs @@ -0,0 +1,36 @@ +// UpdateFileOptions{ +// description: +// UpdateFileOptions options for updating files +// Note: author and committer are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used) +// +// author Identity{ +// description: +// Identity for a person's identity like an author or committer +// +// email string($email) +// name string +// } +// branch string +// branch (optional) to base this file from. if not given, the default branch is used +// +// committer Identity{...} +// content* string +// content must be base64 encoded +// +// dates CommitDateOptions{...} +// from_path string +// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL +// +// message string +// message (optional) for the commit of this file. if not supplied, a default message will be used +// +// new_branch string +// new_branch (optional) will make a new branch from branch before creating the file +// +// sha* string +// sha is the SHA for the file that already exists +// +// signoff boolean +// Add a Signed-off-by trailer by the committer at the end of the commit log message. +// +// } diff --git a/src/types/api/edit/git_hook.rs b/src/types/api/edit/git_hook.rs new file mode 100644 index 0000000..b423360 --- /dev/null +++ b/src/types/api/edit/git_hook.rs @@ -0,0 +1,6 @@ +// EditGitHookOption{ +// description: +// EditGitHookOption options when modifying one Git hook +// +// content string +// } diff --git a/src/types/api/edit/hook.rs b/src/types/api/edit/hook.rs index 478ac98..403c578 100644 --- a/src/types/api/edit/hook.rs +++ b/src/types/api/edit/hook.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use crate::types::misc::active::ActiveStatus; +use crate::types::misc::boolean_enums::is::active::IsActive; use crate::types::misc::header::Header; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -9,7 +9,7 @@ pub struct EditHookOption { /// Description of the options when modifying a hook description: String, /// Boolean flag indicating if the hook is active - active: ActiveStatus, + active: IsActive, /// Authorization header for the hook (if required) authorization_header: Header, /// Branch filter for the hook @@ -27,7 +27,7 @@ mod tests { use hyper::http::{HeaderName, HeaderValue}; use crate::types::api::edit::hook::EditHookOption; - use crate::types::misc::active::ActiveStatus; + use crate::types::misc::boolean_enums::is::active::IsActive; use crate::types::misc::header::Header; #[test] @@ -38,7 +38,7 @@ mod tests { // Example usage: let expected = EditHookOption { description: "Options when modifying a hook".to_string(), - active: ActiveStatus::Active, + active: IsActive::Yes, authorization_header: Header(hyper::HeaderMap::from_iter(std::iter::once(( HeaderName::from_static("bearer"), HeaderValue::from_static("TOKEN"), diff --git a/src/types/api/edit/issue.rs b/src/types/api/edit/issue.rs new file mode 100644 index 0000000..8f09d4d --- /dev/null +++ b/src/types/api/edit/issue.rs @@ -0,0 +1,18 @@ +// EditIssueOption{ +// description: +// EditIssueOption options for editing an issue +// +// assignee string +// deprecated +// +// assignees [ +// x-go-name: Assignees +// string] +// body string +// due_date string($date-time) +// milestone integer($int64) +// ref string +// state string +// title string +// unset_due_date boolean +// } diff --git a/src/types/api/edit/label.rs b/src/types/api/edit/label.rs index 1699dfa..59dda96 100644 --- a/src/types/api/edit/label.rs +++ b/src/types/api/edit/label.rs @@ -2,8 +2,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; +use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; -use crate::types::misc::exclusive::Exclusive; /// CreateLabelOption represents options for creating a label. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -29,8 +29,8 @@ mod tests { use palette::rgb::Rgb; use crate::types::api::creation::label::CreateLabelOption; + use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; - use crate::types::misc::exclusive::Exclusive; #[test] fn deserialize_edit_label_option() { diff --git a/src/types/api/edit/milestone.rs b/src/types/api/edit/milestone.rs new file mode 100644 index 0000000..1968a3e --- /dev/null +++ b/src/types/api/edit/milestone.rs @@ -0,0 +1,9 @@ +// EditMilestoneOption{ +// description: +// EditMilestoneOption options for editing a milestone +// +// description string +// due_on string($date-time) +// state string +// title string +// } diff --git a/src/types/api/edit/mod.rs b/src/types/api/edit/mod.rs index c00eb51..00f3853 100644 --- a/src/types/api/edit/mod.rs +++ b/src/types/api/edit/mod.rs @@ -1,3 +1,18 @@ pub mod hook; pub mod label; pub mod organization; + +/* to-todo */ +pub mod attachment; +/* to-todo */ pub mod branch_protection; +/* to-todo */ pub mod comment; +/* to-todo */ pub mod deadline; +/* to-todo */ pub mod file_options; +/* to-todo */ pub mod git_hook; +/* to-todo */ pub mod issue; +/* to-todo */ pub mod milestone; +/* to-todo */ pub mod pull_request; +/* to-todo */ pub mod reaction; +/* to-todo */ pub mod release; +/* to-todo */ pub mod repository; +/* to-todo */ pub mod user_setting; diff --git a/src/types/api/edit/organization.rs b/src/types/api/edit/organization.rs index 139bacf..942e8cb 100644 --- a/src/types/api/edit/organization.rs +++ b/src/types/api/edit/organization.rs @@ -1,8 +1,8 @@ use serde::{Deserialize, Serialize}; use std::fmt::Display; -use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; -use crate::types::misc::url::OptionalUrl; +use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; +use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; /// EditOrgOption represents options for editing an organization @@ -15,7 +15,7 @@ pub struct EditOrgOption { /// Location of the organization as a string pub location: String, /// Boolean flag indicating if repo admin can change team access - pub repo_admin_change_team_access: RepoAdminCanChangeTeamAccess, + pub repo_admin_change_team_access: CanRepoAdminChangeTeamAccess, /// Visibility of the organization pub visibility: Visibility, /// The organization's website URL (optional) @@ -35,8 +35,8 @@ mod tests { use url::Url; use crate::types::api::edit::organization::EditOrgOption; - use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; - use crate::types::misc::url::OptionalUrl; + use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; + use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; #[test] @@ -48,7 +48,7 @@ mod tests { description: String::from("Updated organization"), full_name: String::from("UpdatedOrg"), location: String::from("Updated City, Country"), - repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::No, + repo_admin_change_team_access: CanRepoAdminChangeTeamAccess::No, visibility: Visibility::Private, website: OptionalUrl::Some(Url::from_str("https://updated.org").unwrap()), }; diff --git a/src/types/api/edit/pull_request.rs b/src/types/api/edit/pull_request.rs new file mode 100644 index 0000000..da3aa52 --- /dev/null +++ b/src/types/api/edit/pull_request.rs @@ -0,0 +1,20 @@ +// EditPullRequestOption{ +// description: +// EditPullRequestOption options when modify pull request +// +// allow_maintainer_edit boolean +// assignee string +// assignees [ +// x-go-name: Assignees +// string] +// base string +// body string +// due_date string($date-time) +// labels [ +// x-go-name: Labels +// integer($int64)] +// milestone integer($int64) +// state string +// title string +// unset_due_date boolean +// } diff --git a/src/types/api/edit/reaction.rs b/src/types/api/edit/reaction.rs new file mode 100644 index 0000000..ee63724 --- /dev/null +++ b/src/types/api/edit/reaction.rs @@ -0,0 +1,6 @@ +// EditReactionOption{ +// description: +// EditReactionOption contain the reaction type +// +// content string +// } diff --git a/src/types/api/edit/release.rs b/src/types/api/edit/release.rs new file mode 100644 index 0000000..6bb9139 --- /dev/null +++ b/src/types/api/edit/release.rs @@ -0,0 +1,11 @@ +// EditReleaseOption{ +// description: +// EditReleaseOption options when editing a release +// +// body string +// draft boolean +// name string +// prerelease boolean +// tag_name string +// target_commitish string +// } diff --git a/src/types/api/edit/repository.rs b/src/types/api/edit/repository.rs new file mode 100644 index 0000000..88ad3f9 --- /dev/null +++ b/src/types/api/edit/repository.rs @@ -0,0 +1,81 @@ +// EditRepoOption{ +// description: +// EditRepoOption options when editing a repository's properties +// +// allow_manual_merge boolean +// either true to allow mark pr as merged manually, or false to prevent it. +// +// allow_merge_commits boolean +// either true to allow merging pull requests with a merge commit, or false to prevent merging pull requests with merge commits. +// +// allow_rebase boolean +// either true to allow rebase-merging pull requests, or false to prevent rebase-merging. +// +// allow_rebase_explicit boolean +// either true to allow rebase with explicit merge commits (--no-ff), or false to prevent rebase with explicit merge commits. +// +// allow_rebase_update [...] +// allow_squash_merge boolean +// either true to allow squash-merging pull requests, or false to prevent squash-merging. +// +// archived boolean +// set to true to archive this repository. +// +// autodetect_manual_merge boolean +// either true to enable AutodetectManualMerge, or false to prevent it. Note: In some special cases, misjudgments can occur. +// +// default_allow_maintainer_edit boolean +// set to true to allow edits from maintainers by default +// +// default_branch string +// sets the default branch for this repository. +// +// default_delete_branch_after_merge boolean +// set to true to delete pr branch after merge by default +// +// default_merge_style string +// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". +// +// description string +// a short description of the repository. +// +// enable_prune boolean +// enable prune - remove obsolete remote-tracking references +// +// external_tracker ExternalTracker{...} +// external_wiki ExternalWiki{...} +// has_issues boolean +// either true to enable issues for this repository or false to disable them. +// +// has_projects boolean +// either true to enable project unit, or false to disable them. +// +// has_pull_requests boolean +// either true to allow pull requests, or false to prevent pull request. +// +// has_wiki boolean +// either true to enable the wiki for this repository or false to disable it. +// +// ignore_whitespace_conflicts boolean +// either true to ignore whitespace for conflicts, or false to not ignore whitespace. +// +// internal_tracker InternalTracker{...} +// mirror_interval string +// set to a string like 8h30m0s to set the mirror interval time +// +// name string +// uniqueItems: true +// name of the repository +// +// private boolean +// either true to make the repository private or false to make it public. +// Note: you will get a 422 error if the organization restricts changing repository visibility to organization +// owners and a non-owner tries to change the value of private. +// +// template boolean +// either true to make this repository a template or false to make it a normal repository +// +// website string +// a URL with more information about the repository. +// +// } diff --git a/src/types/api/edit/user_setting.rs b/src/types/api/edit/user_setting.rs new file mode 100644 index 0000000..d58730d --- /dev/null +++ b/src/types/api/edit/user_setting.rs @@ -0,0 +1,16 @@ +// UserSettingsOptions{ +// description: +// UserSettingsOptions represents options to change user settings +// +// description string +// diff_view_style string +// full_name string +// hide_activity boolean +// hide_email boolean +// Privacy +// +// language string +// location string +// theme string +// website string +// } diff --git a/src/types/api/external/mod.rs b/src/types/api/external/mod.rs new file mode 100644 index 0000000..c9b4d79 --- /dev/null +++ b/src/types/api/external/mod.rs @@ -0,0 +1,2 @@ +pub mod tracker; +pub mod wiki; diff --git a/src/types/api/external/tracker.rs b/src/types/api/external/tracker.rs new file mode 100644 index 0000000..c97ffc9 --- /dev/null +++ b/src/types/api/external/tracker.rs @@ -0,0 +1,66 @@ +use serde::{Deserialize, Serialize}; +use url::Url; + +use crate::types::misc::external_issue_format::ExternalIssueFormat; + +// 🚧🚧 TODO 🚧🚧 : custom serde +// 1. Do some validation format and url have to match some parts +// 2. merge regex pattern and style fields (pattern only set when style = regexp) +/// ExternalTracker represents settings for an external tracker. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct ExternalTracker { + /// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} + /// for the username, repository name, and issue index. + pub external_tracker_format: String, + /// External Issue Tracker issue regular expression. + pub external_tracker_regexp_pattern: String, + /// External Issue Tracker Number Format, either numeric, alphanumeric, or regexp. + pub external_tracker_style: ExternalIssueFormat, + /// URL of the external issue tracker. + pub external_tracker_url: Url, +} + +#[cfg(test)] +mod tracker { + use std::str::FromStr; + + use url::Url; + + use crate::types::api::external::tracker::ExternalTracker; + use crate::types::misc::external_issue_format::ExternalIssueFormat; + + #[test] + fn external_tracker_deserialize() { + let data = include_str!("../../../../test_data/example_external_trackers.json"); + let trackers: Vec = serde_json::from_str(data).unwrap(); + + let expected = vec![ + ExternalTracker { + external_tracker_format: String::from( + "https://example-issues.com/{user}/{repo}/{index}", + ), + external_tracker_regexp_pattern: String::default(), + external_tracker_style: ExternalIssueFormat::Numeric, + external_tracker_url: Url::from_str("https://example-issues.com").unwrap(), + }, + ExternalTracker { + external_tracker_format: String::from( + "https://example-bugs.com/{user}/{repo}-{index}", + ), + external_tracker_regexp_pattern: String::default(), + external_tracker_style: ExternalIssueFormat::Alphanumeric, + external_tracker_url: Url::from_str("https://example-bugs.com").unwrap(), + }, + ExternalTracker { + external_tracker_format: String::from( + "https://custom-tracker.com/issue-{user}-{repo}-{index}", + ), + external_tracker_regexp_pattern: String::from("issue-(\\w+)-(\\w+)-(\\d+)"), + external_tracker_style: ExternalIssueFormat::Regexp, + external_tracker_url: Url::from_str("https://custom-tracker.com").unwrap(), + }, + ]; + + assert_eq!(trackers, expected) + } +} diff --git a/src/types/api/external/wiki.rs b/src/types/api/external/wiki.rs new file mode 100644 index 0000000..0374299 --- /dev/null +++ b/src/types/api/external/wiki.rs @@ -0,0 +1,30 @@ +use serde::{Deserialize, Serialize}; +use url::Url; + +/// ExternalWiki represents settings for an external wiki. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct ExternalWiki { + /// URL of the external wiki. + pub external_wiki_url: Url, +} + +#[cfg(test)] +mod wiki { + use std::str::FromStr; + + use url::Url; + + use crate::types::api::external::wiki::ExternalWiki; + + #[test] + fn deserialize_works() { + let data = include_str!("../../../../test_data/example_external_wiki.json"); + let wiki: ExternalWiki = serde_json::from_str(data).unwrap(); + + let expected = ExternalWiki { + external_wiki_url: Url::from_str("https://example-wiki.com").unwrap(), + }; + + assert_eq!(wiki, expected); + } +} diff --git a/src/types/api/file_link_response.rs b/src/types/api/file_link_response.rs new file mode 100644 index 0000000..42e739f --- /dev/null +++ b/src/types/api/file_link_response.rs @@ -0,0 +1,8 @@ +// FileLinksResponse{ +// description: +// FileLinksResponse contains the links for a repo's file +// +// git string +// html string +// self string +// } diff --git a/src/types/api/git_blob.rs b/src/types/api/git_blob.rs new file mode 100644 index 0000000..cfce8d8 --- /dev/null +++ b/src/types/api/git_blob.rs @@ -0,0 +1,10 @@ +// GitBlobResponse{ +// description: +// GitBlobResponse represents a git blob +// +// content string +// encoding string +// sha string +// size integer($int64) +// url string +// } diff --git a/src/types/api/git_entry.rs b/src/types/api/git_entry.rs new file mode 100644 index 0000000..196f43e --- /dev/null +++ b/src/types/api/git_entry.rs @@ -0,0 +1,11 @@ +// GitEntry{ +// description: +// GitEntry represents a git tree +// +// mode string +// path string +// sha string +// size integer($int64) +// type string +// url string +// }] diff --git a/src/types/api/git_hook.rs b/src/types/api/git_hook.rs new file mode 100644 index 0000000..19296a9 --- /dev/null +++ b/src/types/api/git_hook.rs @@ -0,0 +1,8 @@ +// [GitHook{ +// description: +// GitHook represents a Git repository hook +// +// content string +// is_active boolean +// name string +// }] diff --git a/src/types/api/git_object.rs b/src/types/api/git_object.rs new file mode 100644 index 0000000..f6d359c --- /dev/null +++ b/src/types/api/git_object.rs @@ -0,0 +1,5 @@ +// GitObject represents a Git object.{ +// sha string +// type string +// url string +// } diff --git a/src/types/api/git_ref.rs b/src/types/api/git_ref.rs new file mode 100644 index 0000000..ccfd359 --- /dev/null +++ b/src/types/api/git_ref.rs @@ -0,0 +1,5 @@ +// [Reference represents a Git reference.{ +// object GitObject represents a Git object.{...} +// ref string +// url string +// }] diff --git a/src/types/api/git_tree.rs b/src/types/api/git_tree.rs new file mode 100644 index 0000000..f88d718 --- /dev/null +++ b/src/types/api/git_tree.rs @@ -0,0 +1,13 @@ +// GitTreeResponse{ +// description: +// GitTreeResponse returns a git tree +// +// page integer($int64) +// sha string +// total_count integer($int64) +// tree [ +// x-go-name: Entries +// GitEntry{...}] +// truncated boolean +// url string +// } diff --git a/src/types/api/gpg_key.rs b/src/types/api/gpg_key.rs new file mode 100644 index 0000000..a243175 --- /dev/null +++ b/src/types/api/gpg_key.rs @@ -0,0 +1,23 @@ +// GPGKey{ +// description: +// GPGKey a user GPG key to sign commit and tag in repository +// +// can_certify boolean +// can_encrypt_comms boolean +// can_encrypt_storage boolean +// can_sign boolean +// created_at string($date-time) +// emails [ +// x-go-name: Emails +// GPGKeyEmail{...}] +// expires_at string($date-time) +// id integer($int64) +// key_id string +// primary_key_id string +// public_key string +// subkeys [ +// x-go-name: SubsKey +// { +// }] +// verified boolean +// } diff --git a/src/types/api/gpg_key_email.rs b/src/types/api/gpg_key_email.rs new file mode 100644 index 0000000..b873c4c --- /dev/null +++ b/src/types/api/gpg_key_email.rs @@ -0,0 +1,7 @@ +// GPGKeyEmail{ +// description: +// GPGKeyEmail an email attached to a GPGKey +// +// email string +// verified boolean +// }] diff --git a/src/types/api/heat_map.rs b/src/types/api/heat_map.rs new file mode 100644 index 0000000..4ece515 --- /dev/null +++ b/src/types/api/heat_map.rs @@ -0,0 +1,9 @@ +// [UserHeatmapData{ +// description: +// UserHeatmapData represents the data needed to create a heatmap +// +// contributions integer($int64) +// timestamp TimeStampinteger($int64) +// TimeStamp defines a timestamp +// +// }] diff --git a/src/types/api/hook.rs b/src/types/api/hook.rs index ee7157d..d8461eb 100644 --- a/src/types/api/hook.rs +++ b/src/types/api/hook.rs @@ -3,14 +3,14 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt::Display; -use crate::types::misc::active::ActiveStatus; +use crate::types::misc::boolean_enums::is::active::IsActive; use crate::types::misc::header::Header; /// Hook represents a web hook when one repository is changed #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Hook { /// Boolean flag indicating if the hook is active - pub active: ActiveStatus, + pub active: IsActive, /// Authorization header for the Hook /// /// This deviates a bit from the swagger docs and I'm not sure how it's even used correctly or @@ -46,7 +46,7 @@ mod tests { use hyper::http::{HeaderName, HeaderValue}; use crate::types::api::hook::Hook; - use crate::types::misc::active::ActiveStatus; + use crate::types::misc::boolean_enums::is::active::IsActive; use crate::types::misc::header::Header; #[test] @@ -55,7 +55,7 @@ mod tests { let hook: Hook = serde_json::from_str(data).unwrap(); let expected = Hook { - active: ActiveStatus::Active, + active: IsActive::Yes, authorization_header: Header(hyper::HeaderMap::from_iter(std::iter::once(( HeaderName::from_static("bearer"), HeaderValue::from_static("TOKEN"), diff --git a/src/types/api/identity.rs b/src/types/api/identity.rs new file mode 100644 index 0000000..a476b74 --- /dev/null +++ b/src/types/api/identity.rs @@ -0,0 +1,7 @@ +// Identity{ +// description: +// Identity for a person's identity like an author or committer +// +// email string($email) +// name string +// } diff --git a/src/types/api/internal_tracker.rs b/src/types/api/internal_tracker.rs new file mode 100644 index 0000000..2828273 --- /dev/null +++ b/src/types/api/internal_tracker.rs @@ -0,0 +1,44 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::misc::boolean_enums::allow::only_contributors_track_time::AllowOnlyContributorsToTrackTime; +use crate::types::misc::boolean_enums::enable::issue_dependencies::IssueDependencies; +use crate::types::misc::boolean_enums::enable::time_tracker::TimeTracker; + +/// InternalTracker represents settings for an internal tracker. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct InternalTracker { + /// Let only contributors track time (Built-in issue tracker). + pub allow_only_contributors_to_track_time: AllowOnlyContributorsToTrackTime, + /// Enable dependencies for issues and pull requests (Built-in issue tracker). + pub enable_issue_dependencies: IssueDependencies, + /// Enable time tracking (Built-in issue tracker). + pub enable_time_tracker: TimeTracker, +} + +#[cfg(test)] +mod tests { + use serde_json; + + use crate::types::api::internal_tracker::InternalTracker; + use crate::types::misc::boolean_enums::allow::only_contributors_track_time::AllowOnlyContributorsToTrackTime; + use crate::types::misc::boolean_enums::enable::issue_dependencies::IssueDependencies; + use crate::types::misc::boolean_enums::enable::time_tracker::TimeTracker; + + #[test] + fn serialize_and_deserialize_internal_tracker() { + // Define the expected JSON representation + let data = include_str!("../../../test_data/example_internal_tracker.json"); + + // Deserialize the JSON string back to InternalTracker struct + let internal_tracker: InternalTracker = serde_json::from_str(data).unwrap(); + + let expected = InternalTracker { + allow_only_contributors_to_track_time: AllowOnlyContributorsToTrackTime::Yes, + enable_issue_dependencies: IssueDependencies::Off, + enable_time_tracker: TimeTracker::On, + }; + + // Ensure the deserialized InternalTracker matches the original one + assert_eq!(internal_tracker, expected); + } +} diff --git a/src/types/api/issue.rs b/src/types/api/issue.rs new file mode 100644 index 0000000..e8ca29e --- /dev/null +++ b/src/types/api/issue.rs @@ -0,0 +1,35 @@ +// [Issue{ +// description: +// Issue represents an issue in a repository +// +// assets [ +// x-go-name: Attachments +// Attachment{...}] +// assignee User{...} +// assignees [ +// x-go-name: Assignees +// User{...}] +// body string +// closed_at string($date-time) +// comments integer($int64) +// created_at string($date-time) +// due_date string($date-time) +// html_url string +// id integer($int64) +// is_locked boolean +// labels [ +// x-go-name: Labels +// Label{...}] +// milestone Milestone{...} +// number integer($int64) +// original_author string +// original_author_id integer($int64) +// pull_request PullRequestMeta{...} +// ref string +// repository RepositoryMeta{...} +// state StateType[...] +// title string +// updated_at string($date-time) +// url string +// user User{...} +// }] diff --git a/src/types/api/issue_form_field.rs b/src/types/api/issue_form_field.rs new file mode 100644 index 0000000..c4c8bdc --- /dev/null +++ b/src/types/api/issue_form_field.rs @@ -0,0 +1,11 @@ +// IssueFormField{ +// description: +// IssueFormField represents a form field +// +// attributes { +// } +// id string +// type IssueFormFieldType defines issue form field type, can be "markdown", "textarea", "input", "dropdown" or "checkboxes"[...] +// validations { +// } +// }] diff --git a/src/types/api/issue_form_field_type.rs b/src/types/api/issue_form_field_type.rs new file mode 100644 index 0000000..50e5964 --- /dev/null +++ b/src/types/api/issue_form_field_type.rs @@ -0,0 +1,2 @@ +// IssueFormFieldType defines issue form field type, can be "markdown", "textarea", "input", "dropdown" or "checkboxes"string +// title: IssueFormFieldType defines issue form field type, can be "markdown", "textarea", "input", "dropdown" or "checkboxes" diff --git a/src/types/api/issue_template.rs b/src/types/api/issue_template.rs new file mode 100644 index 0000000..00e3ddf --- /dev/null +++ b/src/types/api/issue_template.rs @@ -0,0 +1,17 @@ +// [IssueTemplate{ +// description: +// IssueTemplate represents an issue template for a repository +// +// about string +// body [ +// x-go-name: Fields +// IssueFormField{...}] +// content string +// file_name string +// labels IssueTemplateLabels[ +// x-go-package: code.gitea.io/gitea/modules/structs +// string] +// name string +// ref string +// title string +// }] diff --git a/src/types/api/issue_template_labels.rs b/src/types/api/issue_template_labels.rs new file mode 100644 index 0000000..7c1ba0a --- /dev/null +++ b/src/types/api/issue_template_labels.rs @@ -0,0 +1,3 @@ +// IssueTemplateLabels[ +// x-go-package: code.gitea.io/gitea/modules/structs +// string] diff --git a/src/types/api/label.rs b/src/types/api/label.rs index 96507bd..87fc9dd 100644 --- a/src/types/api/label.rs +++ b/src/types/api/label.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use url::Url; +use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; -use crate::types::misc::exclusive::Exclusive; /// Label represents a label attached to an issue or a PR. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -37,8 +37,8 @@ mod tests { use url::Url; use crate::types::api::label::Label; + use crate::types::misc::boolean_enums::is::exclusive::Exclusive; use crate::types::misc::color::Color; - use crate::types::misc::exclusive::Exclusive; #[test] fn deserialize_label() { diff --git a/src/types/api/merge.rs b/src/types/api/merge.rs new file mode 100644 index 0000000..a5ab5cd --- /dev/null +++ b/src/types/api/merge.rs @@ -0,0 +1,15 @@ +// MergePullRequestOption{ +// description: +// MergePullRequestForm form for merging Pull Request +// +// Do* string +// Enum: +// [ merge, rebase, rebase-merge, squash, manually-merged ] +// MergeCommitID string +// MergeMessageField string +// MergeTitleField string +// delete_branch_after_merge boolean +// force_merge boolean +// head_commit_id string +// merge_when_checks_succeed boolean +// } diff --git a/src/types/api/migration.rs b/src/types/api/migration.rs new file mode 100644 index 0000000..b165951 --- /dev/null +++ b/src/types/api/migration.rs @@ -0,0 +1,32 @@ +// MigrateRepoOptions{ +// description: +// MigrateRepoOptions options for migrating repository's +// this is used to interact with api v1 +// +// auth_password string +// auth_token string +// auth_username string +// clone_addr* string +// description string +// issues boolean +// labels boolean +// lfs boolean +// lfs_endpoint string +// milestones boolean +// mirror boolean +// mirror_interval string +// private boolean +// pull_requests boolean +// releases boolean +// repo_name* string +// repo_owner string +// Name of User or Organisation who will own Repo after migration +// +// service string +// Enum: +// [ git, github, gitea, gitlab ] +// uid integer($int64) +// deprecated (only for backwards compatibility) +// +// wiki boolean +// } diff --git a/src/types/api/milestone.rs b/src/types/api/milestone.rs new file mode 100644 index 0000000..21e65ca --- /dev/null +++ b/src/types/api/milestone.rs @@ -0,0 +1,17 @@ +// Milestone{ +// description: +// Milestone milestone is a collection of issues on one repository +// +// closed_at string($date-time) +// closed_issues integer($int64) +// created_at string($date-time) +// description string +// due_on string($date-time) +// id integer($int64) +// open_issues integer($int64) +// state StateTypestring +// StateType issue state type +// +// title string +// updated_at string($date-time) +// } diff --git a/src/types/api/mod.rs b/src/types/api/mod.rs index 2828d43..5a1180b 100644 --- a/src/types/api/mod.rs +++ b/src/types/api/mod.rs @@ -1,7 +1,94 @@ pub mod creation; pub mod edit; +pub mod external; pub mod hook; +pub mod internal_tracker; pub mod label; pub mod organization; +pub mod organization_permission; +pub mod repo_transfer; +pub mod repository; +pub mod search_results; pub mod team; pub mod user; + +/* to-todo */ +pub mod access_token; +/* to-todo */ pub mod add; +/* to-todo */ pub mod annotated_tag; +/* to-todo */ pub mod annotated_tag_object; +/* to-todo */ pub mod api_settings; +/* to-todo */ pub mod attachment; +/* to-todo */ pub mod attachment_settings; +/* to-todo */ pub mod branch; +/* to-todo */ pub mod branch_protection; +/* to-todo */ pub mod changed_file; +/* to-todo */ pub mod combined_status; +/* to-todo */ pub mod comment; +/* to-todo */ pub mod commit; +/* to-todo */ pub mod commit_affected_files; +/* to-todo */ pub mod commit_date_options; +/* to-todo */ pub mod commit_meta; +/* to-todo */ pub mod commit_stats; +/* to-todo */ pub mod commit_status; +/* to-todo */ pub mod commit_status_state; +/* to-todo */ pub mod commit_user; +/* to-todo */ pub mod content_response; +/* to-todo */ pub mod create_hook_option_config; +/* to-todo */ pub mod deploy_key; +/* to-todo */ pub mod dismiss_pull_review; +/* to-todo */ pub mod file_link_response; +/* to-todo */ pub mod git_blob; +/* to-todo */ pub mod git_entry; +/* to-todo */ pub mod git_hook; +/* to-todo */ pub mod git_object; +/* to-todo */ pub mod git_ref; +/* to-todo */ pub mod git_tree; +/* to-todo */ pub mod gpg_key; +/* to-todo */ pub mod gpg_key_email; +/* to-todo */ pub mod heat_map; +/* to-todo */ pub mod identity; +/* to-todo */ pub mod issue; +/* to-todo */ pub mod issue_form_field; +/* to-todo */ pub mod issue_form_field_type; +/* to-todo */ pub mod issue_template; +/* to-todo */ pub mod issue_template_labels; +/* to-todo */ pub mod merge; +/* to-todo */ pub mod migration; +/* to-todo */ pub mod milestone; +/* to-todo */ pub mod note; +/* to-todo */ pub mod oath_application; +/* to-todo */ pub mod package; +/* to-todo */ pub mod package_file; +/* to-todo */ pub mod payload_commit; +/* to-todo */ pub mod payload_commit_verification; +/* to-todo */ pub mod payload_user; +/* to-todo */ pub mod public_key; +/* to-todo */ pub mod pull_request; +/* to-todo */ pub mod pull_request_branch_info; +/* to-todo */ pub mod pull_request_meta; +/* to-todo */ pub mod pull_review; +/* to-todo */ pub mod pull_review_comment; +/* to-todo */ pub mod push_mirror; +/* to-todo */ pub mod reaction; +/* to-todo */ pub mod release; +/* to-todo */ pub mod replace; +/* to-todo */ pub mod repo_collaborator_permission; +/* to-todo */ pub mod repo_commit; +/* to-todo */ pub mod repo_meta; +/* to-todo */ pub mod repository_settings; +/* to-todo */ pub mod review_state; +/* to-todo */ pub mod state_type; +/* to-todo */ pub mod stop_watch; +/* to-todo */ pub mod submit_pull_review; +/* to-todo */ pub mod tag; +/* to-todo */ pub mod timeline_comment; +/* to-todo */ pub mod topic; +/* to-todo */ pub mod tracked_time; +/* to-todo */ pub mod transfer; +/* to-todo */ pub mod ui_settings; +/* to-todo */ pub mod user_setting; +/* to-todo */ pub mod watch_info; +/* to-todo */ pub mod wiki_commit; +/* to-todo */ pub mod wiki_commit_list; +/* to-todo */ pub mod wiki_page; diff --git a/src/types/api/note.rs b/src/types/api/note.rs new file mode 100644 index 0000000..6663055 --- /dev/null +++ b/src/types/api/note.rs @@ -0,0 +1,7 @@ +// Note{ +// description: +// Note contains information related to a git note +// +// commit Commit contains information generated from a Git commit.{...} +// message string +// } diff --git a/src/types/api/oath_application.rs b/src/types/api/oath_application.rs new file mode 100644 index 0000000..d69620d --- /dev/null +++ b/src/types/api/oath_application.rs @@ -0,0 +1,11 @@ +// [OAuth2Application represents an OAuth2 application.{ +// client_id string +// client_secret string +// confidential_client boolean +// created string($date-time) +// id integer($int64) +// name string +// redirect_uris [ +// x-go-name: RedirectURIs +// string] +// }] diff --git a/src/types/api/organization.rs b/src/types/api/organization.rs index 340407e..e3a9952 100644 --- a/src/types/api/organization.rs +++ b/src/types/api/organization.rs @@ -3,8 +3,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use url::Url; -use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; -use crate::types::misc::url::OptionalUrl; +use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; +use crate::types::misc::optional_url::OptionalUrl; /// Organization represents an organization #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -22,7 +22,7 @@ pub struct Organization { /// Name of the organization pub name: String, /// Boolean flag indicating if repo admin can change team access - pub repo_admin_change_team_access: RepoAdminCanChangeTeamAccess, + pub repo_admin_change_team_access: CanRepoAdminChangeTeamAccess, /// The organization's username pub username: String, /// The organization's website URL (optional) @@ -42,8 +42,8 @@ mod tests { use url::Url; use crate::types::api::organization::Organization; - use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess; - use crate::types::misc::url::OptionalUrl; + use crate::types::misc::boolean_enums::can::repo_admin_change_team_access::CanRepoAdminChangeTeamAccess; + use crate::types::misc::optional_url::OptionalUrl; #[test] fn deserialize_works() { @@ -59,7 +59,7 @@ mod tests { id: 77294, location: String::from(""), name: String::from("---"), - repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::Yes, + repo_admin_change_team_access: CanRepoAdminChangeTeamAccess::Yes, username: String::from("---"), website: OptionalUrl::None, }; diff --git a/src/types/api/organization_permission.rs b/src/types/api/organization_permission.rs new file mode 100644 index 0000000..c35cac6 --- /dev/null +++ b/src/types/api/organization_permission.rs @@ -0,0 +1,54 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::misc::boolean_enums::can::create_repo::CanCreateRepo; +use crate::types::misc::boolean_enums::can::read::CanRead; +use crate::types::misc::boolean_enums::can::write::CanWrite; +use crate::types::misc::boolean_enums::is::admin::IsAdmin; +use crate::types::misc::boolean_enums::is::owner::IsOwner; + +/// Represents different permissions of users on an organization. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct OrganizationPermissions { + /// Whether the user can create repositories in the organization. + can_create_repository: CanCreateRepo, + /// Whether the user can read data from the organization. + can_read: CanRead, + /// Whether the user can write data to the organization (e.g., push code, manage issues). + can_write: CanWrite, + /// Whether the user is an admin of the organization. + is_admin: IsAdmin, + /// Whether the user is the owner of the organization. + is_owner: IsOwner, +} + +#[cfg(test)] +mod organization_permissions { + + // Your implementation of OrganizationPermissions and related enums + use crate::types::api::organization_permission::OrganizationPermissions; + use crate::types::misc::boolean_enums::can::create_repo::CanCreateRepo; + use crate::types::misc::boolean_enums::can::read::CanRead; + use crate::types::misc::boolean_enums::can::write::CanWrite; + use crate::types::misc::boolean_enums::is::admin::IsAdmin; + use crate::types::misc::boolean_enums::is::owner::IsOwner; + + #[test] + fn deserialize_works() { + // Expected JSON string + let data = include_str!("../../../test_data/example_organization_permissions.json"); + + // Deserialize the JSON string back to an instance of OrganizationPermissions + let org_permissions: OrganizationPermissions = serde_json::from_str(data).unwrap(); + // Create a sample instance of OrganizationPermissions + let expected = OrganizationPermissions { + can_create_repository: CanCreateRepo::Yes, + can_read: CanRead::No, + can_write: CanWrite::Yes, + is_admin: IsAdmin::No, + is_owner: IsOwner::Yes, + }; + + // Compare the original and deserialized instances + assert_eq!(org_permissions, expected); + } +} diff --git a/src/types/api/package.rs b/src/types/api/package.rs new file mode 100644 index 0000000..3bbafc6 --- /dev/null +++ b/src/types/api/package.rs @@ -0,0 +1,13 @@ +// Package{ +// description: +// Package represents a package +// +// created_at [...] +// creator User{...} +// id [...] +// name [...] +// owner User{...} +// repository Repository{...} +// type [...] +// version [...] +// } diff --git a/src/types/api/package_file.rs b/src/types/api/package_file.rs new file mode 100644 index 0000000..b4ef1b0 --- /dev/null +++ b/src/types/api/package_file.rs @@ -0,0 +1,12 @@ +// [PackageFile{ +// description: +// PackageFile represents a package file +// +// Size integer($int64) +// id integer($int64) +// md5 string +// name string +// sha1 string +// sha256 string +// sha512 string +// }] diff --git a/src/types/api/payload_commit.rs b/src/types/api/payload_commit.rs new file mode 100644 index 0000000..79343f9 --- /dev/null +++ b/src/types/api/payload_commit.rs @@ -0,0 +1,23 @@ +// PayloadCommit{ +// description: +// PayloadCommit represents a commit +// +// added [ +// x-go-name: Added +// string] +// author PayloadUser{...} +// committer PayloadUser{...} +// id string +// sha1 hash of the commit +// +// message string +// modified [ +// x-go-name: Modified +// string] +// removed [ +// x-go-name: Removed +// string] +// timestamp string($date-time) +// url string +// verification PayloadCommitVerification{...} +// } diff --git a/src/types/api/payload_commit_verification.rs b/src/types/api/payload_commit_verification.rs new file mode 100644 index 0000000..724fad1 --- /dev/null +++ b/src/types/api/payload_commit_verification.rs @@ -0,0 +1,11 @@ +// PayloadCommitVerification{ +// description: +// PayloadCommitVerification represents the GPG verification of a commit +// +// payload string +// reason string +// signature string +// signer PayloadUser{...} +// verified boolean +// } +// } diff --git a/src/types/api/payload_user.rs b/src/types/api/payload_user.rs new file mode 100644 index 0000000..834cb6b --- /dev/null +++ b/src/types/api/payload_user.rs @@ -0,0 +1,10 @@ +// PayloadUser{ +// description: +// PayloadUser represents the author or committer of a commit +// +// email string($email) +// name string +// Full name of the commit author +// +// username string +// } diff --git a/src/types/api/public_key.rs b/src/types/api/public_key.rs new file mode 100644 index 0000000..0777865 --- /dev/null +++ b/src/types/api/public_key.rs @@ -0,0 +1,14 @@ +// [PublicKey{ +// description: +// PublicKey publickey is a user key to push code to repository +// +// created_at string($date-time) +// fingerprint string +// id integer($int64) +// key string +// key_type string +// read_only boolean +// title string +// url string +// user User{...} +// }] diff --git a/src/types/api/pull_request.rs b/src/types/api/pull_request.rs new file mode 100644 index 0000000..d5c172e --- /dev/null +++ b/src/types/api/pull_request.rs @@ -0,0 +1,38 @@ +// [PullRequest{ +// description: +// PullRequest represents a pull request +// +// allow_maintainer_edit boolean +// assignee User{...} +// assignees [ +// x-go-name: Assignees +// User{...}] +// base PRBranchInfo{...} +// body string +// closed_at string($date-time) +// comments integer($int64) +// created_at string($date-time) +// diff_url string +// due_date string($date-time) +// head PRBranchInfo{...} +// html_url string +// id integer($int64) +// is_locked boolean +// labels [ +// x-go-name: Labels +// Label{...}] +// merge_base string +// merge_commit_sha string +// mergeable boolean +// merged boolean +// merged_at string($date-time) +// merged_by User{...} +// milestone Milestone{...} +// number integer($int64) +// patch_url string +// state StateType[...] +// title string +// updated_at string($date-time) +// url string +// user User{...} +// }] diff --git a/src/types/api/pull_request_branch_info.rs b/src/types/api/pull_request_branch_info.rs new file mode 100644 index 0000000..0ef0746 --- /dev/null +++ b/src/types/api/pull_request_branch_info.rs @@ -0,0 +1,10 @@ +// PRBranchInfo{ +// description: +// PRBranchInfo information about a branch +// +// label string +// ref string +// repo Repository{...} +// repo_id integer($int64) +// sha string +// } diff --git a/src/types/api/pull_request_meta.rs b/src/types/api/pull_request_meta.rs new file mode 100644 index 0000000..2591f35 --- /dev/null +++ b/src/types/api/pull_request_meta.rs @@ -0,0 +1,7 @@ +// PullRequestMeta{ +// description: +// PullRequestMeta PR info if an issue is a PR +// +// merged boolean +// merged_at string($date-time) +// } diff --git a/src/types/api/pull_review.rs b/src/types/api/pull_review.rs new file mode 100644 index 0000000..b6ac26a --- /dev/null +++ b/src/types/api/pull_review.rs @@ -0,0 +1,19 @@ +// [PullReview{ +// description: +// PullReview represents a pull request review +// +// body string +// comments_count integer($int64) +// commit_id string +// dismissed boolean +// html_url string +// id integer($int64) +// official boolean +// pull_request_url string +// stale boolean +// state ReviewStateType[...] +// submitted_at string($date-time) +// team Team{...} +// updated_at string($date-time) +// user User{...} +// }] diff --git a/src/types/api/pull_review_comment.rs b/src/types/api/pull_review_comment.rs new file mode 100644 index 0000000..01bece4 --- /dev/null +++ b/src/types/api/pull_review_comment.rs @@ -0,0 +1,20 @@ +// [PullReviewComment{ +// description: +// PullReviewComment represents a comment on a pull request review +// +// body string +// commit_id string +// created_at string($date-time) +// diff_hunk string +// html_url string +// id integer($int64) +// original_commit_id string +// original_position integer($uint64) +// path string +// position integer($uint64) +// pull_request_review_id integer($int64) +// pull_request_url string +// resolver User{...} +// updated_at string($date-time) +// user User{...} +// }] diff --git a/src/types/api/push_mirror.rs b/src/types/api/push_mirror.rs new file mode 100644 index 0000000..ce0fdb7 --- /dev/null +++ b/src/types/api/push_mirror.rs @@ -0,0 +1,13 @@ +// [PushMirror{ +// description: +// PushMirror represents information of a push mirror +// +// created string +// interval string +// last_error string +// last_update string +// remote_address string +// remote_name string +// repo_name string +// sync_on_commit boolean +// }] diff --git a/src/types/api/reaction.rs b/src/types/api/reaction.rs new file mode 100644 index 0000000..37177c7 --- /dev/null +++ b/src/types/api/reaction.rs @@ -0,0 +1,8 @@ +// [Reaction{ +// description: +// Reaction contain one reaction +// +// content [...] +// created_at [...] +// user User{...} +// }] diff --git a/src/types/api/release.rs b/src/types/api/release.rs new file mode 100644 index 0000000..3429cf0 --- /dev/null +++ b/src/types/api/release.rs @@ -0,0 +1,22 @@ +// [Release{ +// description: +// Release represents a repository release +// +// assets [ +// x-go-name: Attachments +// Attachment{...}] +// author User{...} +// body string +// created_at string($date-time) +// draft boolean +// html_url string +// id integer($int64) +// name string +// prerelease boolean +// published_at string($date-time) +// tag_name string +// tarball_url string +// target_commitish string +// url string +// zipball_url string +// }] diff --git a/src/types/api/replace/label.rs b/src/types/api/replace/label.rs new file mode 100644 index 0000000..0b41c8e --- /dev/null +++ b/src/types/api/replace/label.rs @@ -0,0 +1,10 @@ +// IssueLabelsOption{ +// description: +// IssueLabelsOption a collection of labels +// +// labels [ +// x-go-name: Labels +// list of label IDs +// +// integer($int64)] +// } diff --git a/src/types/api/replace/mod.rs b/src/types/api/replace/mod.rs new file mode 100644 index 0000000..754e6af --- /dev/null +++ b/src/types/api/replace/mod.rs @@ -0,0 +1,2 @@ +/* to-todo */ +pub mod label; diff --git a/src/types/api/repo_collaborator_permission.rs b/src/types/api/repo_collaborator_permission.rs new file mode 100644 index 0000000..8aa23e2 --- /dev/null +++ b/src/types/api/repo_collaborator_permission.rs @@ -0,0 +1,8 @@ +// RepoCollaboratorPermission{ +// description: +// RepoCollaboratorPermission to get repository permission for a collaborator +// +// permission string +// role_name string +// user User{...} +// } diff --git a/src/types/api/repo_commit.rs b/src/types/api/repo_commit.rs new file mode 100644 index 0000000..6f3fcd7 --- /dev/null +++ b/src/types/api/repo_commit.rs @@ -0,0 +1,12 @@ +// RepoCommit contains information of a commit in the context of a repository.{ +// author CommitUser contains information of a user in the context of a commit.{...} +// committer CommitUser contains information of a user in the context of a commit.{...} +// message string +// tree CommitMeta contains meta information of a commit in terms of API.{ +// created string($date-time) +// sha string +// url string +// } +// url string +// verification PayloadCommitVerification{...} +// } diff --git a/src/types/api/repo_meta.rs b/src/types/api/repo_meta.rs new file mode 100644 index 0000000..2495cbf --- /dev/null +++ b/src/types/api/repo_meta.rs @@ -0,0 +1,9 @@ +// RepositoryMeta{ +// description: +// RepositoryMeta basic repository information +// +// full_name string +// id integer($int64) +// name string +// owner string +// } diff --git a/src/types/api/repo_transfer.rs b/src/types/api/repo_transfer.rs new file mode 100644 index 0000000..35c8b35 --- /dev/null +++ b/src/types/api/repo_transfer.rs @@ -0,0 +1,43 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::api::team::Team; +use crate::types::api::user::User; + +/// RepoTransfer represents a pending repository transfer. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct RepoTransfer { + /// The user performing the transfer (doer). + pub doer: User, + /// The recipient user receiving the transfer. + pub recipient: User, + /// The teams involved in the transfer. + pub teams: Vec, +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json; + + #[test] + fn serialize_and_deserialize_repo_transfer() { + let data = include_str!("../../../test_data/example_repo_transfer.json"); + + let repo_transfer: RepoTransfer = serde_json::from_str(data).unwrap(); + + // Sample data for the User and Team instances + let user: User = + serde_json::from_str(include_str!("../../../test_data/example_user.json")).unwrap(); + let team: Team = + serde_json::from_str(include_str!("../../../test_data/example_team.json")).unwrap(); + + let expected = RepoTransfer { + doer: user.clone(), + recipient: user.clone(), + teams: vec![team.clone(), team.clone()], + }; + + // Ensure the deserialized RepoTransfer matches the original one + assert_eq!(repo_transfer, expected); + } +} diff --git a/src/types/api/repository.rs b/src/types/api/repository.rs new file mode 100644 index 0000000..c238032 --- /dev/null +++ b/src/types/api/repository.rs @@ -0,0 +1,252 @@ +use std::fmt::Display; + +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use url::Url; + +use crate::types::api::external::tracker::ExternalTracker; +use crate::types::api::external::wiki::ExternalWiki; +use crate::types::api::internal_tracker::InternalTracker; +use crate::types::api::repo_transfer::RepoTransfer; +use crate::types::api::user::User; +use crate::types::misc::boolean_enums::allow::maintainer_edit::AllowMaintainerEdit; +use crate::types::misc::boolean_enums::allow::merge_commits::AllowMergeCommits; +use crate::types::misc::boolean_enums::allow::rebase::AllowRebase; +use crate::types::misc::boolean_enums::allow::rebase_explicit::AllowRebaseExplicit; +use crate::types::misc::boolean_enums::allow::rebase_update::AllowRebaseUpdate; +use crate::types::misc::boolean_enums::allow::squash_merge::AllowSquashMerge; +use crate::types::misc::boolean_enums::delete_branch_after_merge::DeleteBranchAfterMerge; +use crate::types::misc::boolean_enums::has::issues::HasIssues; +use crate::types::misc::boolean_enums::has::projects::HasProjects; +use crate::types::misc::boolean_enums::has::pull_requests::HasPullRequests; +use crate::types::misc::boolean_enums::has::wiki::HasWiki; +use crate::types::misc::boolean_enums::ignore_whitespace_conflicts::IgnoreWhitespaceConflicts; +use crate::types::misc::boolean_enums::is::archived::IsArchived; +use crate::types::misc::boolean_enums::is::empty::IsEmpty; +use crate::types::misc::boolean_enums::is::fork::IsFork; +use crate::types::misc::boolean_enums::is::internal::IsInternal; +use crate::types::misc::boolean_enums::is::mirror::IsMirror; +use crate::types::misc::boolean_enums::is::private::IsPrivate; +use crate::types::misc::boolean_enums::is::template::IsTemplate; +use crate::types::misc::optional_url::OptionalUrl; +use crate::types::misc::permission::Permission; +use crate::types::misc::sshurl::SshUrl; + +/// Repository represents a repository. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Repository { + /// Whether merge commits are allowed in the repository. + pub allow_merge_commits: AllowMergeCommits, + /// Whether rebase is allowed in the repository. + pub allow_rebase: AllowRebase, + /// Whether explicit rebase is allowed in the repository. + pub allow_rebase_explicit: AllowRebaseExplicit, + /// Whether rebase update is allowed in the repository. + pub allow_rebase_update: AllowRebaseUpdate, + /// Whether squash merge is allowed in the repository. + pub allow_squash_merge: AllowSquashMerge, + /// Whether the repository is archived (read-only). + pub archived: IsArchived, + /// URL of the avatar for the repository. + pub avatar_url: OptionalUrl, + /// The clone URL for the repository. + pub clone_url: Url, + /// The timestamp when the repository was created. + pub created_at: DateTime, + /// Whether maintainers are allowed to edit by default. + pub default_allow_maintainer_edit: AllowMaintainerEdit, + /// The default branch of the repository. + pub default_branch: String, + /// Whether to delete the branch after merge by default. + pub default_delete_branch_after_merge: DeleteBranchAfterMerge, + /// The default merge style for pull requests in the repository. + pub default_merge_style: String, + /// The description of the repository. + pub description: String, + /// Whether the repository is empty. + pub empty: IsEmpty, + /// Settings for an external tracker associated with the repository. + pub external_tracker: Option, + /// Settings for an external wiki associated with the repository. + pub external_wiki: Option, + /// Whether the repository is a fork. + pub fork: IsFork, + /// The number of forks of the repository. + pub forks_count: usize, + /// The full name of the repository in the format "owner/repo". + pub full_name: String, + /// Whether the repository has issues enabled. + pub has_issues: HasIssues, + /// Whether the repository has projects enabled. + pub has_projects: HasProjects, + /// Whether the repository has pull requests enabled. + pub has_pull_requests: HasPullRequests, + /// Whether the repository has wiki enabled. + pub has_wiki: HasWiki, + /// The HTML URL of the repository. + pub html_url: Url, + /// The unique ID of the repository. + pub id: usize, + /// Whether to ignore whitespace conflicts. + pub ignore_whitespace_conflicts: IgnoreWhitespaceConflicts, + /// Whether the repository is internal (private to an organization or enterprise). + pub internal: IsInternal, + /// Settings for an internal tracker associated with the repository. + pub internal_tracker: InternalTracker, + /// The primary language of the repository. + pub language: String, + /// URL to retrieve the languages used in the repository. + pub languages_url: OptionalUrl, + /// The link associated with the repository. + pub link: String, + /// Whether the repository is a mirror. + pub mirror: IsMirror, + /// The interval for mirroring the repository (if it's a mirror). + pub mirror_interval: String, + /// The timestamp when the repository was last updated as a mirror. + pub mirror_updated: DateTime, + /// The name of the repository. + pub name: String, + /// The number of open issues in the repository. + pub open_issues_count: usize, + /// The number of open pull requests in the repository. + pub open_pr_counter: usize, + /// The URL to the original repository if this repository is a fork. + pub original_url: OptionalUrl, + /// The owner of the repository. + pub owner: User, + /// The parent repository if this repository is a fork (optional). + pub parent: Option>, + /// The permissions granted to users for this repository. + pub permissions: Permission, + /// Whether the repository is private. + pub private: IsPrivate, + /// The number of releases in the repository. + pub release_counter: usize, + /// Settings for a pending repository transfer. + pub repo_transfer: Option, + /// The size of the repository in bytes. + pub size: usize, + /// The SSH URL for the repository. + pub ssh_url: SshUrl, + /// The number of stars (watchers) the repository has. + pub stars_count: usize, + /// Whether the repository is a template. + pub template: IsTemplate, + /// The timestamp when the repository was last updated. + pub updated_at: DateTime, + /// The number of watchers the repository has. + pub watchers_count: usize, + /// The website associated with the repository. + pub website: OptionalUrl, +} + +impl Display for Repository { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } +} + +#[cfg(test)] +mod repository { + use std::str::FromStr; + + use chrono::DateTime; + use url::Url; + + use crate::types::api::repository::Repository; + use crate::types::misc::boolean_enums::allow::maintainer_edit::AllowMaintainerEdit; + use crate::types::misc::boolean_enums::allow::merge_commits::AllowMergeCommits; + use crate::types::misc::boolean_enums::allow::rebase::AllowRebase; + use crate::types::misc::boolean_enums::allow::rebase_explicit::AllowRebaseExplicit; + use crate::types::misc::boolean_enums::allow::rebase_update::AllowRebaseUpdate; + use crate::types::misc::boolean_enums::allow::squash_merge::AllowSquashMerge; + use crate::types::misc::boolean_enums::delete_branch_after_merge::DeleteBranchAfterMerge; + use crate::types::misc::boolean_enums::has::issues::HasIssues; + use crate::types::misc::boolean_enums::has::projects::HasProjects; + use crate::types::misc::boolean_enums::has::pull_requests::HasPullRequests; + use crate::types::misc::boolean_enums::has::wiki::HasWiki; + use crate::types::misc::boolean_enums::ignore_whitespace_conflicts::IgnoreWhitespaceConflicts; + use crate::types::misc::boolean_enums::is::archived::IsArchived; + use crate::types::misc::boolean_enums::is::empty::IsEmpty; + use crate::types::misc::boolean_enums::is::fork::IsFork; + use crate::types::misc::boolean_enums::is::internal::IsInternal; + use crate::types::misc::boolean_enums::is::mirror::IsMirror; + use crate::types::misc::boolean_enums::is::private::IsPrivate; + use crate::types::misc::boolean_enums::is::template::IsTemplate; + use crate::types::misc::optional_url::OptionalUrl; + use crate::types::misc::sshurl::SshUrl; + + #[test] + fn deserialize_works() { + let data = include_str!("../../../test_data/example_repo.json"); + + let repo: Repository = serde_json::from_str(data).unwrap(); + + let expected = Repository { + id: 128746, + owner: serde_json::from_str(include_str!("../../../test_data/example_user.json")) + .unwrap(), + name: String::from("tmp"), + full_name: String::from("VoiDD/tmp"), + description: String::default(), + empty: IsEmpty::Yes, + private: IsPrivate::No, + fork: IsFork::No, + template: IsTemplate::No, + parent: None, + mirror: IsMirror::No, + size: 24, + language: String::default(), + languages_url: OptionalUrl::Some( + Url::from_str("https://codeberg.org/api/v1/repos/VoiDD/tmp/languages").unwrap(), + ), + html_url: Url::from_str("https://codeberg.org/VoiDD/tmp").unwrap(), + link: String::default(), + ssh_url: SshUrl::from_str("git@codeberg.org:VoiDD/tmp.git").unwrap(), + clone_url: Url::from_str("https://codeberg.org/VoiDD/tmp.git").unwrap(), + original_url: OptionalUrl::None, + website: OptionalUrl::None, + stars_count: 0, + forks_count: 0, + watchers_count: 1, + open_issues_count: 0, + open_pr_counter: 0, + release_counter: 0, + default_branch: String::from("main"), + archived: IsArchived::No, + created_at: DateTime::from_str("2023-07-27T18:59:48Z").unwrap(), + updated_at: DateTime::from_str("2023-07-27T18:59:48Z").unwrap(), + permissions: serde_json::from_str(include_str!( + "../../../test_data/example_permission.json" + )) + .unwrap(), + has_issues: HasIssues::Yes, + internal_tracker: serde_json::from_str(include_str!( + "../../../test_data/example_internal_tracker.json" + )) + .unwrap(), + has_wiki: HasWiki::Yes, + has_pull_requests: HasPullRequests::Yes, + has_projects: HasProjects::Yes, + ignore_whitespace_conflicts: IgnoreWhitespaceConflicts::No, + allow_merge_commits: AllowMergeCommits::Yes, + allow_rebase: AllowRebase::Yes, + allow_rebase_explicit: AllowRebaseExplicit::Yes, + allow_squash_merge: AllowSquashMerge::Yes, + allow_rebase_update: AllowRebaseUpdate::Yes, + default_delete_branch_after_merge: DeleteBranchAfterMerge::No, + default_merge_style: String::from("merge"), + default_allow_maintainer_edit: AllowMaintainerEdit::No, + avatar_url: OptionalUrl::None, + internal: IsInternal::No, + mirror_interval: String::from(""), + mirror_updated: DateTime::from_str("0001-01-01T00:00:00Z").unwrap(), + repo_transfer: None, + external_wiki: None, + external_tracker: None, + }; + + assert_eq!(repo, expected); + } +} diff --git a/src/types/api/repository_settings.rs b/src/types/api/repository_settings.rs new file mode 100644 index 0000000..eb7fffa --- /dev/null +++ b/src/types/api/repository_settings.rs @@ -0,0 +1,11 @@ +// GeneralRepoSettingsGeneralRepoSettings{ +// description: +// GeneralRepoSettings contains global repository settings exposed by API +// +// http_git_disabled boolean +// lfs_disabled boolean +// migrations_disabled boolean +// mirrors_disabled boolean +// stars_disabled boolean +// time_tracking_disabled boolean +// } diff --git a/src/types/api/review_state.rs b/src/types/api/review_state.rs new file mode 100644 index 0000000..8170451 --- /dev/null +++ b/src/types/api/review_state.rs @@ -0,0 +1,2 @@ +// state ReviewStateTypestring +// ReviewStateType review state type diff --git a/src/types/api/search_results.rs b/src/types/api/search_results.rs new file mode 100644 index 0000000..4cf9e19 --- /dev/null +++ b/src/types/api/search_results.rs @@ -0,0 +1,35 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::misc::boolean_enums::is::ok::IsOk; + +// 🚧🚧 TODO 🚧🚧 : Actually parse this into a result? +/// A generic struct representing search results with associated data and an indication of success. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SearchResults { + /// The data representing the search results. + data: T, + /// An indication of whether the search was successful or not. + ok: IsOk, +} + +#[cfg(test)] +mod search_results { + use crate::types::api::search_results::SearchResults; + use crate::types::api::team::Team; + use crate::types::misc::boolean_enums::is::ok::IsOk; + + #[test] + fn deserialize_works() { + let data = include_str!("../../../test_data/example_search_results.json"); + let search_results: SearchResults> = serde_json::from_str(data).unwrap(); + + let expected = SearchResults { + data: vec![ + serde_json::from_str(include_str!("../../../test_data/example_team.json")).unwrap(), + ], + ok: IsOk::Yes, + }; + + assert_eq!(search_results, expected); + } +} diff --git a/src/types/api/state_type.rs b/src/types/api/state_type.rs new file mode 100644 index 0000000..cb0f59d --- /dev/null +++ b/src/types/api/state_type.rs @@ -0,0 +1,2 @@ +// StateTypestring +// StateType issue state type diff --git a/src/types/api/stop_watch.rs b/src/types/api/stop_watch.rs new file mode 100644 index 0000000..a37e7cf --- /dev/null +++ b/src/types/api/stop_watch.rs @@ -0,0 +1,12 @@ +// [StopWatch{ +// description: +// StopWatch represent a running stopwatch +// +// created string($date-time) +// duration string +// issue_index integer($int64) +// issue_title string +// repo_name string +// repo_owner_name string +// seconds integer($int64) +// }] diff --git a/src/types/api/submit_pull_review.rs b/src/types/api/submit_pull_review.rs new file mode 100644 index 0000000..4e9ba91 --- /dev/null +++ b/src/types/api/submit_pull_review.rs @@ -0,0 +1,7 @@ +// SubmitPullReviewOptions{ +// description: +// SubmitPullReviewOptions are options to submit a pending pull review +// +// body string +// event ReviewStateType[...] +// } diff --git a/src/types/api/tag.rs b/src/types/api/tag.rs new file mode 100644 index 0000000..8ac1b6c --- /dev/null +++ b/src/types/api/tag.rs @@ -0,0 +1,11 @@ +// [Tag{ +// description: +// Tag represents a repository tag +// +// commit CommitMeta contains meta information of a commit in terms of API.{...} +// id string +// message string +// name string +// tarball_url string +// zipball_url string +// }] diff --git a/src/types/api/team.rs b/src/types/api/team.rs index aeb25e5..700099d 100644 --- a/src/types/api/team.rs +++ b/src/types/api/team.rs @@ -4,8 +4,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use crate::types::api::organization::Organization; -use crate::types::misc::can_create_org_repo::CanCreateOrgRepo; -use crate::types::misc::includes_all_repositories::IncludesAllRepositories; +use crate::types::misc::boolean_enums::can::create_org_repo::CanCreateOrgRepo; +use crate::types::misc::boolean_enums::includes_all_repositories::IncludesAllRepositories; use crate::types::misc::team_permissions::TeamPermission; /// Team represents a team in an organization @@ -43,8 +43,8 @@ mod tests { use crate::types::api::organization::Organization; use crate::types::api::team::Team; - use crate::types::misc::can_create_org_repo::CanCreateOrgRepo; - use crate::types::misc::includes_all_repositories::IncludesAllRepositories; + use crate::types::misc::boolean_enums::can::create_org_repo::CanCreateOrgRepo; + use crate::types::misc::boolean_enums::includes_all_repositories::IncludesAllRepositories; use crate::types::misc::team_permissions::TeamPermission; #[test] diff --git a/src/types/api/timeline_comment.rs b/src/types/api/timeline_comment.rs new file mode 100644 index 0000000..d61ac74 --- /dev/null +++ b/src/types/api/timeline_comment.rs @@ -0,0 +1,38 @@ +// [TimelineComment{ +// description: +// TimelineComment represents a timeline comment (comment of any type) on a commit or issue +// +// assignee User{...} +// assignee_team Team{...} +// body string +// created_at string($date-time) +// dependent_issue Issue{...} +// html_url string +// id integer($int64) +// issue_url string +// label Label{...} +// milestone Milestone{...} +// new_ref string +// new_title string +// old_milestone Milestone{...} +// old_project_id integer($int64) +// old_ref string +// old_title string +// project_id integer($int64) +// pull_request_url string +// ref_action string +// ref_comment Comment{...} +// ref_commit_sha string +// commit SHA where issue/PR was referenced +// +// ref_issue Issue{...} +// removed_assignee boolean +// whether the assignees were removed or added +// +// resolve_doer User{...} +// review_id integer($int64) +// tracked_time TrackedTime{...} +// type string +// updated_at string($date-time) +// user User{...} +// }] diff --git a/src/types/api/topic.rs b/src/types/api/topic.rs new file mode 100644 index 0000000..5713044 --- /dev/null +++ b/src/types/api/topic.rs @@ -0,0 +1,8 @@ +// TopicName{ +// description: +// TopicName a list of repo topic names +// +// topics [ +// x-go-name: TopicNames +// string] +// } diff --git a/src/types/api/tracked_time.rs b/src/types/api/tracked_time.rs new file mode 100644 index 0000000..9b6db4b --- /dev/null +++ b/src/types/api/tracked_time.rs @@ -0,0 +1,18 @@ +// TrackedTime{ +// description: +// TrackedTime worked time for an issue / pr +// +// created string($date-time) +// id integer($int64) +// issue Issue{...} +// issue_id integer($int64) +// deprecated (only for backwards compatibility) +// +// time integer($int64) +// Time in seconds +// +// user_id integer($int64) +// deprecated (only for backwards compatibility) +// +// user_name string +// } diff --git a/src/types/api/transfer.rs b/src/types/api/transfer.rs new file mode 100644 index 0000000..ae0d9ef --- /dev/null +++ b/src/types/api/transfer.rs @@ -0,0 +1,11 @@ +// TransferRepoOption{ +// description: +// TransferRepoOption options when transfer a repository's ownership +// +// new_owner* string +// team_ids [ +// x-go-name: TeamIDs +// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories. +// +// integer($int64)] +// } diff --git a/src/types/api/ui_settings.rs b/src/types/api/ui_settings.rs new file mode 100644 index 0000000..24bb296 --- /dev/null +++ b/src/types/api/ui_settings.rs @@ -0,0 +1,12 @@ +// GeneralUISettings{ +// description: +// GeneralUISettings contains global ui settings exposed by API +// +// allowed_reactions [ +// x-go-name: AllowedReactions +// string] +// custom_emojis [ +// x-go-name: CustomEmojis +// string] +// default_theme string +// } diff --git a/src/types/api/user.rs b/src/types/api/user.rs index eb33e86..5ac4fa9 100644 --- a/src/types/api/user.rs +++ b/src/types/api/user.rs @@ -3,21 +3,22 @@ use std::fmt::Display; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; -use url::Url; -use crate::types::misc::active::ActiveStatus; -use crate::types::misc::admin::AdminStatus; +use crate::types::misc::boolean_enums::is::active::IsActive; +use crate::types::misc::boolean_enums::is::admin::IsAdmin; +use crate::types::misc::boolean_enums::is::restricted::IsRestricted; +use crate::types::misc::boolean_enums::prohibit_login::ProhibitLogin; use crate::types::misc::locale::Locale; -use crate::types::misc::url::OptionalUrl; +use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; /// User represents a user #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct User { /// is user active - pub active: ActiveStatus, + pub active: IsActive, /// URL to the user's avatar - pub avatar_url: Url, + pub avatar_url: OptionalUrl, /// creation timestamp of the account pub created: DateTime, /// the user's description (optional) @@ -33,7 +34,7 @@ pub struct User { /// an unique ID pub id: usize, /// is user admin - pub is_admin: AdminStatus, + pub is_admin: IsAdmin, /// language as locale pub language: Locale, /// timestamp of last login @@ -44,12 +45,10 @@ pub struct User { pub login: String, /// the user's authentication sign-in name. pub login_name: String, - // 🚧🚧 TODO 🚧🚧 : Enumify /// is user banned - pub prohibit_login: bool, - // 🚧🚧 TODO 🚧🚧 : Enumify + pub prohibit_login: ProhibitLogin, /// is user restricted - pub restricted: bool, + pub restricted: IsRestricted, /// stars the user gave other repos pub starred_repos_count: usize, /// user's name (not mentioned in the API docs, deprecated? -> user login for safety) @@ -75,10 +74,12 @@ mod tests { use url::Url; use crate::types::api::user::User; - use crate::types::misc::active::ActiveStatus; - use crate::types::misc::admin::AdminStatus; + use crate::types::misc::boolean_enums::is::active::IsActive; + use crate::types::misc::boolean_enums::is::admin::IsAdmin; + use crate::types::misc::boolean_enums::is::restricted::IsRestricted; + use crate::types::misc::boolean_enums::prohibit_login::ProhibitLogin; use crate::types::misc::locale::Locale; - use crate::types::misc::url::OptionalUrl; + use crate::types::misc::optional_url::OptionalUrl; use crate::types::misc::visibility::Visibility; #[test] @@ -86,8 +87,10 @@ mod tests { let data = include_str!("../../../test_data/example_user.json"); let user: User = serde_json::from_str(&data).unwrap(); let expected = User { - active: ActiveStatus::Active, - avatar_url: Url::from_str("https://codeberg.org/avatars/foo-bar").unwrap(), + active: IsActive::Yes, + avatar_url: OptionalUrl::Some( + Url::from_str("https://codeberg.org/avatars/foo-bar").unwrap(), + ), created: DateTime::from_str("2022-11-04T14:41:29Z").unwrap(), description: String::from(""), email: Email::from_str("example@mail.com").unwrap(), @@ -95,14 +98,14 @@ mod tests { following_count: 1, full_name: String::from(""), id: 12345, - is_admin: AdminStatus::NonAdmin, + is_admin: IsAdmin::No, language: Locale::EnUs, last_login: DateTime::from_str("2023-07-26T19:38:27Z").unwrap(), location: String::from(""), login: String::from("ExampleUser"), login_name: String::from(""), - prohibit_login: false, - restricted: false, + prohibit_login: ProhibitLogin::No, + restricted: IsRestricted::No, starred_repos_count: 0, username: String::from("ExampleUser"), visibility: Visibility::Public, diff --git a/src/types/api/user_setting.rs b/src/types/api/user_setting.rs new file mode 100644 index 0000000..2023958 --- /dev/null +++ b/src/types/api/user_setting.rs @@ -0,0 +1,16 @@ +//[UserSettings{ +//description: +//UserSettings represents user settings +// +//description string +//diff_view_style string +//full_name string +//hide_activity boolean +//hide_email boolean +//Privacy +// +//language string +//location string +//theme string +//website string +//}] diff --git a/src/types/api/watch_info.rs b/src/types/api/watch_info.rs new file mode 100644 index 0000000..83668ec --- /dev/null +++ b/src/types/api/watch_info.rs @@ -0,0 +1,12 @@ +// WatchInfo{ +// description: +// WatchInfo represents an API watch status of one repository +// +// created_at string($date-time) +// ignored boolean +// reason { +// } +// repository_url string +// subscribed boolean +// url string +// } diff --git a/src/types/api/wiki_commit.rs b/src/types/api/wiki_commit.rs new file mode 100644 index 0000000..be54aa5 --- /dev/null +++ b/src/types/api/wiki_commit.rs @@ -0,0 +1,9 @@ +// WikiCommit{ +// description: +// WikiCommit page commit/revision +// +// author CommitUser contains information of a user in the context of a commit.{...} +// commiter CommitUser contains information of a user in the context of a commit.{...} +// message string +// sha string +// } diff --git a/src/types/api/wiki_commit_list.rs b/src/types/api/wiki_commit_list.rs new file mode 100644 index 0000000..8ccb69a --- /dev/null +++ b/src/types/api/wiki_commit_list.rs @@ -0,0 +1,9 @@ +// WikiCommitList{ +// description: +// WikiCommitList commit/revision list +// +// commits [ +// x-go-name: WikiCommits +// WikiCommit{...}] +// count integer($int64) +// } diff --git a/src/types/api/wiki_page.rs b/src/types/api/wiki_page.rs new file mode 100644 index 0000000..ed8fa56 --- /dev/null +++ b/src/types/api/wiki_page.rs @@ -0,0 +1,15 @@ +// WikiPage{ +// description: +// WikiPage a wiki page +// +// commit_count integer($int64) +// content_base64 string +// Page content, base64 encoded +// +// footer string +// html_url string +// last_commit WikiCommit{...} +// sidebar string +// sub_url string +// title string +// } diff --git a/src/types/misc/active.rs b/src/types/misc/active.rs deleted file mode 100644 index 76aee6b..0000000 --- a/src/types/misc/active.rs +++ /dev/null @@ -1,87 +0,0 @@ -use clap::ValueEnum; -use strum::{Display, EnumIs, EnumIter, EnumString}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs)] -pub enum ActiveStatus { - Inactive, - Active, -} - -mod serde { - use serde::de::Visitor; - use serde::{Deserialize, Serialize}; - - use crate::types::misc::active::ActiveStatus; - - impl Serialize for ActiveStatus { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, ActiveStatus::Active)) - } - } - - struct ActiveStatusVisitor; - - impl<'de> Visitor<'de> for ActiveStatusVisitor { - type Value = ActiveStatus; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(ActiveStatus::Active) - } else { - Ok(ActiveStatus::Inactive) - } - } - } - - impl<'de> Deserialize<'de> for ActiveStatus { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(ActiveStatusVisitor) - } - } -} - -#[cfg(test)] -mod active_status { - use crate::types::misc::active::ActiveStatus; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: ActiveStatus = serde_json::from_str(input).unwrap(); - assert_eq!(ActiveStatus::Active, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: ActiveStatus = serde_json::from_str(input).unwrap(); - assert_eq!(ActiveStatus::Inactive, val); - } - - #[test] - fn serialize_true() { - let input = ActiveStatus::Active; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true") - } - - #[test] - fn serialize_false() { - let input = ActiveStatus::Inactive; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false") - } -} diff --git a/src/types/misc/admin.rs b/src/types/misc/admin.rs deleted file mode 100644 index efa96b9..0000000 --- a/src/types/misc/admin.rs +++ /dev/null @@ -1,87 +0,0 @@ -use clap::ValueEnum; -use strum::{Display, EnumIs, EnumIter, EnumString}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs)] -pub enum AdminStatus { - NonAdmin, - Admin, -} - -mod serde { - use serde::de::Visitor; - use serde::{Deserialize, Serialize}; - - use crate::types::misc::admin::AdminStatus; - - impl Serialize for AdminStatus { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, AdminStatus::Admin)) - } - } - - struct AdminStatusVisitor; - - impl<'de> Visitor<'de> for AdminStatusVisitor { - type Value = AdminStatus; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(AdminStatus::Admin) - } else { - Ok(AdminStatus::NonAdmin) - } - } - } - - impl<'de> Deserialize<'de> for AdminStatus { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(AdminStatusVisitor) - } - } -} - -#[cfg(test)] -mod active_status { - use crate::types::misc::admin::AdminStatus; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: AdminStatus = serde_json::from_str(input).unwrap(); - assert_eq!(AdminStatus::Admin, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: AdminStatus = serde_json::from_str(input).unwrap(); - assert_eq!(AdminStatus::NonAdmin, val); - } - - #[test] - fn serialize_true() { - let input = AdminStatus::Admin; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true") - } - - #[test] - fn serialize_false() { - let input = AdminStatus::NonAdmin; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false") - } -} diff --git a/src/types/misc/boolean_enums/allow/mod.rs b/src/types/misc/boolean_enums/allow/mod.rs new file mode 100644 index 0000000..c7fdf1a --- /dev/null +++ b/src/types/misc/boolean_enums/allow/mod.rs @@ -0,0 +1,12 @@ +use crate::implement_boolean_enum; + +implement_boolean_enum!(maintainer_edit, AllowMaintainerEdit); +implement_boolean_enum!(merge_commits, AllowMergeCommits); +implement_boolean_enum!(rebase, AllowRebase); +implement_boolean_enum!(rebase_explicit, AllowRebaseExplicit); +implement_boolean_enum!(rebase_update, AllowRebaseUpdate); +implement_boolean_enum!(squash_merge, AllowSquashMerge); +implement_boolean_enum!( + only_contributors_track_time, + AllowOnlyContributorsToTrackTime +); diff --git a/src/types/misc/boolean_enums/can/mod.rs b/src/types/misc/boolean_enums/can/mod.rs new file mode 100644 index 0000000..df31b15 --- /dev/null +++ b/src/types/misc/boolean_enums/can/mod.rs @@ -0,0 +1,9 @@ +use crate::implement_boolean_enum; + +implement_boolean_enum!(create_org_repo, CanCreateOrgRepo); +implement_boolean_enum!(repo_admin_change_team_access, CanRepoAdminChangeTeamAccess); +implement_boolean_enum!(read, CanRead); +implement_boolean_enum!(write, CanWrite); +implement_boolean_enum!(pull, CanPull); +implement_boolean_enum!(push, CanPush); +implement_boolean_enum!(create_repo, CanCreateRepo); diff --git a/src/types/misc/boolean_enums/enable/mod.rs b/src/types/misc/boolean_enums/enable/mod.rs new file mode 100644 index 0000000..0d6121d --- /dev/null +++ b/src/types/misc/boolean_enums/enable/mod.rs @@ -0,0 +1,4 @@ +use crate::implement_boolean_enum; + +implement_boolean_enum!(issue_dependencies, IssueDependencies { On, Off }); +implement_boolean_enum!(time_tracker, TimeTracker { On, Off }); diff --git a/src/types/misc/boolean_enums/has/mod.rs b/src/types/misc/boolean_enums/has/mod.rs new file mode 100644 index 0000000..93429d1 --- /dev/null +++ b/src/types/misc/boolean_enums/has/mod.rs @@ -0,0 +1,6 @@ +use crate::implement_boolean_enum; + +implement_boolean_enum!(issues, HasIssues); +implement_boolean_enum!(projects, HasProjects); +implement_boolean_enum!(pull_requests, HasPullRequests); +implement_boolean_enum!(wiki, HasWiki); diff --git a/src/types/misc/boolean_enums/is/mod.rs b/src/types/misc/boolean_enums/is/mod.rs new file mode 100644 index 0000000..8f43f93 --- /dev/null +++ b/src/types/misc/boolean_enums/is/mod.rs @@ -0,0 +1,15 @@ +use crate::implement_boolean_enum; + +implement_boolean_enum!(active, IsActive); +implement_boolean_enum!(admin, IsAdmin); +implement_boolean_enum!(archived, IsArchived); +implement_boolean_enum!(empty, IsEmpty); +implement_boolean_enum!(exclusive, Exclusive); +implement_boolean_enum!(fork, IsFork); +implement_boolean_enum!(internal, IsInternal); +implement_boolean_enum!(mirror, IsMirror); +implement_boolean_enum!(private, IsPrivate); +implement_boolean_enum!(restricted, IsRestricted); +implement_boolean_enum!(template, IsTemplate); +implement_boolean_enum!(owner, IsOwner); +implement_boolean_enum!(ok, IsOk); diff --git a/src/types/misc/boolean_enums/mod.rs b/src/types/misc/boolean_enums/mod.rs new file mode 100644 index 0000000..36c65c3 --- /dev/null +++ b/src/types/misc/boolean_enums/mod.rs @@ -0,0 +1,12 @@ +use crate::implement_boolean_enum; + +pub mod allow; +pub mod can; +pub mod enable; +pub mod has; +pub mod is; + +implement_boolean_enum!(delete_branch_after_merge, DeleteBranchAfterMerge); +implement_boolean_enum!(ignore_whitespace_conflicts, IgnoreWhitespaceConflicts); +implement_boolean_enum!(includes_all_repositories, IncludesAllRepositories); +implement_boolean_enum!(prohibit_login, ProhibitLogin); diff --git a/src/types/misc/can_create_org_repo.rs b/src/types/misc/can_create_org_repo.rs deleted file mode 100644 index 975c878..0000000 --- a/src/types/misc/can_create_org_repo.rs +++ /dev/null @@ -1,87 +0,0 @@ -use clap::ValueEnum; -use strum::{Display, EnumIs, EnumIter, EnumString}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs)] -pub enum CanCreateOrgRepo { - Yes, - No, -} - -mod serde { - use serde::de::Visitor; - use serde::{Deserialize, Serialize}; - - use crate::types::misc::can_create_org_repo::CanCreateOrgRepo; - - impl Serialize for CanCreateOrgRepo { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, CanCreateOrgRepo::Yes)) - } - } - - struct CanCreateOrgRepoVisitor; - - impl<'de> Visitor<'de> for CanCreateOrgRepoVisitor { - type Value = CanCreateOrgRepo; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(CanCreateOrgRepo::Yes) - } else { - Ok(CanCreateOrgRepo::No) - } - } - } - - impl<'de> Deserialize<'de> for CanCreateOrgRepo { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(CanCreateOrgRepoVisitor) - } - } -} - -#[cfg(test)] -mod exclusive { - use crate::types::misc::can_create_org_repo::CanCreateOrgRepo; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: CanCreateOrgRepo = serde_json::from_str(input).unwrap(); - assert_eq!(CanCreateOrgRepo::Yes, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: CanCreateOrgRepo = serde_json::from_str(input).unwrap(); - assert_eq!(CanCreateOrgRepo::No, val); - } - - #[test] - fn serialize_true() { - let input = CanCreateOrgRepo::Yes; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true"); - } - - #[test] - fn serialize_false() { - let input = CanCreateOrgRepo::No; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false"); - } -} diff --git a/src/types/misc/color.rs b/src/types/misc/color.rs index c6867bf..f0c66a5 100644 --- a/src/types/misc/color.rs +++ b/src/types/misc/color.rs @@ -78,7 +78,7 @@ mod color { #[test] fn color_serialize() { // Example of serializing and deserializing - let rgb_color = Color(Rgb::new(100, 50, 200)); + let rgb_color = Color(Rgb::new(0x64, 0x32, 0xc8)); let rgb_color_str = "\"#6432c8\""; let serialized = serde_json::to_string(&rgb_color).unwrap(); @@ -88,7 +88,7 @@ mod color { #[test] fn color_deserialize() { // Example of serializing and deserializing - let rgb_color = Color(Rgb::new(100, 50, 200)); + let rgb_color = Color(Rgb::new(0x64, 0x32, 0xc8)); let rgb_color_str = "\"#6432c8\""; let deserialized: Color = serde_json::from_str(&rgb_color_str).unwrap(); @@ -96,13 +96,11 @@ mod color { } #[test] - #[should_panic] - fn color_deserialize_panic() { + fn multiple_pound_symbols_not_allowed() { // Example of serializing and deserializing - let rgb_color = Color(Rgb::new(100, 50, 200)); let rgb_color_str = "\"##6432c8\""; - let deserialized: Color = serde_json::from_str(&rgb_color_str).unwrap(); - assert_eq!(deserialized, rgb_color); + let deserialized: Result = serde_json::from_str(&rgb_color_str); + assert!(deserialized.is_err()); } } diff --git a/src/types/misc/exclusive.rs b/src/types/misc/exclusive.rs deleted file mode 100644 index 753e5bf..0000000 --- a/src/types/misc/exclusive.rs +++ /dev/null @@ -1,87 +0,0 @@ -use clap::ValueEnum; -use strum::{Display, EnumIs, EnumIter, EnumString}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs)] -pub enum Exclusive { - Yes, - No, -} - -mod serde { - use serde::de::Visitor; - use serde::{Deserialize, Serialize}; - - use crate::types::misc::exclusive::Exclusive; - - impl Serialize for Exclusive { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, Exclusive::Yes)) - } - } - - struct ObjectStatusVisitor; - - impl<'de> Visitor<'de> for ObjectStatusVisitor { - type Value = Exclusive; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(Exclusive::Yes) - } else { - Ok(Exclusive::No) - } - } - } - - impl<'de> Deserialize<'de> for Exclusive { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(ObjectStatusVisitor) - } - } -} - -#[cfg(test)] -mod exclusive { - use crate::types::misc::exclusive::Exclusive; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: Exclusive = serde_json::from_str(input).unwrap(); - assert_eq!(Exclusive::Yes, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: Exclusive = serde_json::from_str(input).unwrap(); - assert_eq!(Exclusive::No, val); - } - - #[test] - fn serialize_true() { - let input = Exclusive::Yes; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true"); - } - - #[test] - fn serialize_false() { - let input = Exclusive::No; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false"); - } -} diff --git a/src/types/misc/external_issue_format.rs b/src/types/misc/external_issue_format.rs new file mode 100644 index 0000000..1f32724 --- /dev/null +++ b/src/types/misc/external_issue_format.rs @@ -0,0 +1,13 @@ +use serde::{Deserialize, Serialize}; + +/// ExternalIssueFormat represents the possible formats for the external issue tracker numbers. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum ExternalIssueFormat { + /// Represents a numeric format for the external issue tracker numbers. + Numeric, + /// Represents an alphanumeric format for the external issue tracker numbers. + Alphanumeric, + /// Represents a custom format for the external issue tracker numbers using regular expression. + Regexp, +} diff --git a/src/types/misc/includes_all_repositories.rs b/src/types/misc/includes_all_repositories.rs deleted file mode 100644 index 2bd9e40..0000000 --- a/src/types/misc/includes_all_repositories.rs +++ /dev/null @@ -1,88 +0,0 @@ -use clap::ValueEnum; -use strum::{Display, EnumIs, EnumIter, EnumString}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum, Display, EnumIter, EnumString, EnumIs)] -pub enum IncludesAllRepositories { - Yes, - No, -} - -mod serde { - use serde::de::Visitor; - use serde::{Deserialize, Serialize}; - - use crate::types::misc::includes_all_repositories::IncludesAllRepositories; - - impl Serialize for IncludesAllRepositories { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, IncludesAllRepositories::Yes)) - } - } - - struct IncludesAllRepositoriesVisitor; - - impl<'de> Visitor<'de> for IncludesAllRepositoriesVisitor { - type Value = IncludesAllRepositories; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(IncludesAllRepositories::Yes) - } else { - Ok(IncludesAllRepositories::No) - } - } - } - - impl<'de> Deserialize<'de> for IncludesAllRepositories { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(IncludesAllRepositoriesVisitor) - } - } -} - -#[cfg(test)] -mod exclusive { - - use crate::types::misc::includes_all_repositories::IncludesAllRepositories; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: IncludesAllRepositories = serde_json::from_str(input).unwrap(); - assert_eq!(IncludesAllRepositories::Yes, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: IncludesAllRepositories = serde_json::from_str(input).unwrap(); - assert_eq!(IncludesAllRepositories::No, val); - } - - #[test] - fn serialize_true() { - let input = IncludesAllRepositories::Yes; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true"); - } - - #[test] - fn serialize_false() { - let input = IncludesAllRepositories::No; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false"); - } -} diff --git a/src/types/misc/locale.rs b/src/types/misc/locale.rs index 9eb7913..28d1497 100644 --- a/src/types/misc/locale.rs +++ b/src/types/misc/locale.rs @@ -17,6 +17,7 @@ use strum::{Display, EnumIs, EnumIter, EnumString}; Deserialize, )] pub enum Locale { + // 🚧🚧 TODO 🚧🚧 : extend the list #[serde(rename = "de-DE")] De, #[serde(rename = "en-US")] diff --git a/src/types/misc/mod.rs b/src/types/misc/mod.rs index 8d33ec2..5c32061 100644 --- a/src/types/misc/mod.rs +++ b/src/types/misc/mod.rs @@ -1,12 +1,11 @@ -pub mod active; -pub mod admin; -pub mod can_create_org_repo; +/// bools suck muhahahahaha +pub mod boolean_enums; pub mod color; -pub mod exclusive; +pub mod external_issue_format; pub mod header; -pub mod includes_all_repositories; pub mod locale; -pub mod team_access; +pub mod optional_url; +pub mod permission; +pub mod sshurl; pub mod team_permissions; -pub mod url; pub mod visibility; diff --git a/src/types/misc/url.rs b/src/types/misc/optional_url.rs similarity index 100% rename from src/types/misc/url.rs rename to src/types/misc/optional_url.rs diff --git a/src/types/misc/permission.rs b/src/types/misc/permission.rs new file mode 100644 index 0000000..136d12e --- /dev/null +++ b/src/types/misc/permission.rs @@ -0,0 +1,39 @@ +use serde::{Deserialize, Serialize}; + +use crate::types::misc::boolean_enums::can::pull::CanPull; +use crate::types::misc::boolean_enums::can::push::CanPush; +use crate::types::misc::boolean_enums::is::admin::IsAdmin; + +/// Permission represents a set of permissions. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Permission { + /// Permission to administer (admin). + pub admin: IsAdmin, + /// Permission to pull (read). + pub pull: CanPull, + /// Permission to push (write). + pub push: CanPush, +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json; + + #[test] + fn serialize_and_deserialize_permission() { + // Define the expected JSON representation + let expected_json = include_str!("../../../test_data/example_permission.json"); + // Deserialize the JSON string back to Permission struct + let permission: Permission = serde_json::from_str(expected_json).unwrap(); + + let expected = Permission { + admin: IsAdmin::Yes, + pull: CanPull::No, + push: CanPush::Yes, + }; + + // Ensure the deserialized Permission matches the original one + assert_eq!(permission, expected); + } +} diff --git a/src/types/misc/sshurl.rs b/src/types/misc/sshurl.rs new file mode 100644 index 0000000..c6bd207 --- /dev/null +++ b/src/types/misc/sshurl.rs @@ -0,0 +1,102 @@ +use std::str::FromStr; + +use serde::de::{Deserializer, Error, Visitor}; +use serde::{Deserialize, Serialize}; +use url::Url; + +/// Enum for handling optional URLs that may be empty strings in JSON +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SshUrl { + prefix: String, + url: Url, +} + +impl FromStr for SshUrl { + type Err = String; + + fn from_str(s: &str) -> Result { + let (prefix, rest) = s + .split_once('@') + .ok_or_else(|| String::from("invalid URL: didn't find \"@\""))?; + let url = Url::parse(rest).map_err(|e| format!("invalid URL: {e:?}"))?; + Ok(SshUrl { + prefix: String::from(prefix), + url, + }) + } +} + +impl<'de> Deserialize<'de> for SshUrl { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct OptionalUrlVisitor; + + impl<'de> Visitor<'de> for OptionalUrlVisitor { + type Value = SshUrl; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a URL or an empty string") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + SshUrl::from_str(v).map_err(|e| E::custom(format!("{e:?}"))) + } + } + + deserializer.deserialize_any(OptionalUrlVisitor) + } +} + +impl Serialize for SshUrl { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(format!("{}@{}", self.prefix, self.url).as_str()) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + #[test] + fn deserialize_valid_ssh_url() { + let json_data = r#""git@github.com:username/repo.git""#; + let expected_url = SshUrl { + prefix: String::from("git"), + url: Url::from_str("github.com:username/repo.git").unwrap(), + }; + + let deserialized: SshUrl = serde_json::from_str(json_data).unwrap(); + assert_eq!(deserialized, expected_url); + } + + #[test] + fn deserialize_invalid_ssh_url() { + // Test case for an invalid URL + let json_data = r#""git@invalidurl""#; + + let result: Result = serde_json::from_str(json_data); + assert!(result.is_err()); + } + + #[test] + fn serialize_ssh_url() { + let ssh_url = SshUrl { + prefix: String::from("git"), + url: Url::parse("github.com:username/repo.git").unwrap(), + }; + let expected_json = r#""git@github.com:username/repo.git""#; + + let serialized = serde_json::to_string(&ssh_url).unwrap(); + assert_eq!(serialized, expected_json); + } +} diff --git a/src/types/misc/team_access.rs b/src/types/misc/team_access.rs deleted file mode 100644 index d94287c..0000000 --- a/src/types/misc/team_access.rs +++ /dev/null @@ -1,80 +0,0 @@ -use serde::de::Visitor; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum RepoAdminCanChangeTeamAccess { - Yes, - No, -} - -impl Serialize for RepoAdminCanChangeTeamAccess { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bool(matches!(*self, RepoAdminCanChangeTeamAccess::Yes)) - } -} - -struct TeamAccessVisitor; - -impl<'de> Visitor<'de> for TeamAccessVisitor { - type Value = RepoAdminCanChangeTeamAccess; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a boolean value (true/false)") - } - - fn visit_bool(self, v: bool) -> Result - where - E: serde::de::Error, - { - if v { - Ok(RepoAdminCanChangeTeamAccess::Yes) - } else { - Ok(RepoAdminCanChangeTeamAccess::No) - } - } -} - -impl<'de> Deserialize<'de> for RepoAdminCanChangeTeamAccess { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_bool(TeamAccessVisitor) - } -} - -#[cfg(test)] -mod team_access { - use super::*; - - #[test] - fn deserialize_true() { - let input = "true"; - let val: RepoAdminCanChangeTeamAccess = serde_json::from_str(input).unwrap(); - assert_eq!(RepoAdminCanChangeTeamAccess::Yes, val); - } - - #[test] - fn deserialize_false() { - let input = "false"; - let val: RepoAdminCanChangeTeamAccess = serde_json::from_str(input).unwrap(); - assert_eq!(RepoAdminCanChangeTeamAccess::No, val); - } - - #[test] - fn serialize_true() { - let input = RepoAdminCanChangeTeamAccess::Yes; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "true") - } - - #[test] - fn serialize_false() { - let input = RepoAdminCanChangeTeamAccess::No; - let val = serde_json::to_string(&input).unwrap(); - assert_eq!(val.as_str(), "false") - } -} diff --git a/test_data/example_external_trackers.json b/test_data/example_external_trackers.json new file mode 100644 index 0000000..482cd73 --- /dev/null +++ b/test_data/example_external_trackers.json @@ -0,0 +1,20 @@ +[ + { + "external_tracker_format": "https://example-issues.com/{user}/{repo}/{index}", + "external_tracker_regexp_pattern": "", + "external_tracker_style": "numeric", + "external_tracker_url": "https://example-issues.com" + }, + { + "external_tracker_format": "https://example-bugs.com/{user}/{repo}-{index}", + "external_tracker_regexp_pattern": "", + "external_tracker_style": "alphanumeric", + "external_tracker_url": "https://example-bugs.com" + }, + { + "external_tracker_format": "https://custom-tracker.com/issue-{user}-{repo}-{index}", + "external_tracker_regexp_pattern": "issue-(\\w+)-(\\w+)-(\\d+)", + "external_tracker_style": "regexp", + "external_tracker_url": "https://custom-tracker.com" + } +] diff --git a/test_data/example_external_wiki.json b/test_data/example_external_wiki.json new file mode 100644 index 0000000..134e872 --- /dev/null +++ b/test_data/example_external_wiki.json @@ -0,0 +1,3 @@ +{ + "external_wiki_url": "https://example-wiki.com" +} diff --git a/test_data/example_internal_tracker.json b/test_data/example_internal_tracker.json new file mode 100644 index 0000000..085dfea --- /dev/null +++ b/test_data/example_internal_tracker.json @@ -0,0 +1,5 @@ +{ + "allow_only_contributors_to_track_time": true, + "enable_issue_dependencies": false, + "enable_time_tracker": true +} diff --git a/test_data/example_organization_permissions.json b/test_data/example_organization_permissions.json new file mode 100644 index 0000000..ddc5f5b --- /dev/null +++ b/test_data/example_organization_permissions.json @@ -0,0 +1,7 @@ +{ + "can_create_repository": true, + "can_read": false, + "can_write": true, + "is_admin": false, + "is_owner": true +} diff --git a/test_data/example_permission.json b/test_data/example_permission.json new file mode 100644 index 0000000..2ca76a4 --- /dev/null +++ b/test_data/example_permission.json @@ -0,0 +1,5 @@ +{ + "admin": true, + "pull": false, + "push": true +} diff --git a/test_data/example_repo.json b/test_data/example_repo.json new file mode 100644 index 0000000..1501bb1 --- /dev/null +++ b/test_data/example_repo.json @@ -0,0 +1,82 @@ +{ + "id": 128746, + "owner": { + "active": true, + "avatar_url": "https://codeberg.org/avatars/foo-bar", + "created": "2022-11-04T14:41:29Z", + "description": "", + "email": "example@mail.com", + "followers_count": 2, + "following_count": 1, + "full_name": "", + "id": 12345, + "is_admin": false, + "language": "en-US", + "last_login": "2023-07-26T19:38:27Z", + "location": "", + "login": "ExampleUser", + "login_name": "", + "prohibit_login": false, + "restricted": false, + "starred_repos_count": 0, + "username": "ExampleUser", + "visibility": "public", + "website": "https://example.com" + }, + "name": "tmp", + "full_name": "VoiDD/tmp", + "description": "", + "empty": true, + "private": false, + "fork": false, + "template": false, + "parent": null, + "mirror": false, + "size": 24, + "language": "", + "languages_url": "https://codeberg.org/api/v1/repos/VoiDD/tmp/languages", + "html_url": "https://codeberg.org/VoiDD/tmp", + "link": "", + "ssh_url": "git@codeberg.org:VoiDD/tmp.git", + "clone_url": "https://codeberg.org/VoiDD/tmp.git", + "original_url": "", + "website": "", + "stars_count": 0, + "forks_count": 0, + "watchers_count": 1, + "open_issues_count": 0, + "open_pr_counter": 0, + "release_counter": 0, + "default_branch": "main", + "archived": false, + "created_at": "2023-07-27T18:59:48Z", + "updated_at": "2023-07-27T18:59:48Z", + "permissions": { + "admin": true, + "pull": false, + "push": true + }, + "has_issues": true, + "internal_tracker": { + "allow_only_contributors_to_track_time": true, + "enable_issue_dependencies": false, + "enable_time_tracker": true + }, + "has_wiki": true, + "has_pull_requests": true, + "has_projects": true, + "ignore_whitespace_conflicts": false, + "allow_merge_commits": true, + "allow_rebase": true, + "allow_rebase_explicit": true, + "allow_squash_merge": true, + "allow_rebase_update": true, + "default_delete_branch_after_merge": false, + "default_merge_style": "merge", + "default_allow_maintainer_edit": false, + "avatar_url": "", + "internal": false, + "mirror_interval": "", + "mirror_updated": "0001-01-01T00:00:00Z", + "repo_transfer": null +} diff --git a/test_data/example_repo_transfer.json b/test_data/example_repo_transfer.json new file mode 100644 index 0000000..bded2ec --- /dev/null +++ b/test_data/example_repo_transfer.json @@ -0,0 +1,110 @@ +{ + "doer": { + "active": true, + "avatar_url": "https://codeberg.org/avatars/foo-bar", + "created": "2022-11-04T14:41:29Z", + "description": "", + "email": "example@mail.com", + "followers_count": 2, + "following_count": 1, + "full_name": "", + "id": 12345, + "is_admin": false, + "language": "en-US", + "last_login": "2023-07-26T19:38:27Z", + "location": "", + "login": "ExampleUser", + "login_name": "", + "prohibit_login": false, + "restricted": false, + "starred_repos_count": 0, + "username": "ExampleUser", + "visibility": "public", + "website": "https://example.com" + }, + "recipient": { + "active": true, + "avatar_url": "https://codeberg.org/avatars/foo-bar", + "created": "2022-11-04T14:41:29Z", + "description": "", + "email": "example@mail.com", + "followers_count": 2, + "following_count": 1, + "full_name": "", + "id": 12345, + "is_admin": false, + "language": "en-US", + "last_login": "2023-07-26T19:38:27Z", + "location": "", + "login": "ExampleUser", + "login_name": "", + "prohibit_login": false, + "restricted": false, + "starred_repos_count": 0, + "username": "ExampleUser", + "visibility": "public", + "website": "https://example.com" + }, + "teams": [ + { + "can_create_org_repo": true, + "description": "Example team description", + "id": 12345, + "includes_all_repositories": false, + "name": "Example Team", + "organization": { + "id": 77294, + "name": "---", + "full_name": "", + "avatar_url": "https://codeberg.org/avatars/9efc314b65237d5d646e1b817372afc6", + "description": "", + "website": "", + "location": "", + "visibility": "public", + "repo_admin_change_team_access": true, + "username": "---" + }, + "permission": "admin", + "units": [ + "repo.code", + "repo.issues", + "repo.ext_issues" + ], + "units_map": { + "repo.code": "read", + "repo.issues": "write", + "repo.ext_issues": "none" + } + }, + { + "can_create_org_repo": true, + "description": "Example team description", + "id": 12345, + "includes_all_repositories": false, + "name": "Example Team", + "organization": { + "id": 77294, + "name": "---", + "full_name": "", + "avatar_url": "https://codeberg.org/avatars/9efc314b65237d5d646e1b817372afc6", + "description": "", + "website": "", + "location": "", + "visibility": "public", + "repo_admin_change_team_access": true, + "username": "---" + }, + "permission": "admin", + "units": [ + "repo.code", + "repo.issues", + "repo.ext_issues" + ], + "units_map": { + "repo.code": "read", + "repo.issues": "write", + "repo.ext_issues": "none" + } + } + ] +} diff --git a/test_data/example_search_results.json b/test_data/example_search_results.json new file mode 100644 index 0000000..a033336 --- /dev/null +++ b/test_data/example_search_results.json @@ -0,0 +1,35 @@ +{ + "data": [ + { + "can_create_org_repo": true, + "description": "Example team description", + "id": 12345, + "includes_all_repositories": false, + "name": "Example Team", + "organization": { + "id": 77294, + "name": "---", + "full_name": "", + "avatar_url": "https://codeberg.org/avatars/9efc314b65237d5d646e1b817372afc6", + "description": "", + "website": "", + "location": "", + "visibility": "public", + "repo_admin_change_team_access": true, + "username": "---" + }, + "permission": "admin", + "units": [ + "repo.code", + "repo.issues", + "repo.ext_issues" + ], + "units_map": { + "repo.code": "read", + "repo.issues": "write", + "repo.ext_issues": "none" + } + } + ], + "ok": true +}