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 0000000..93ba260 Binary files /dev/null and b/progress.png differ diff --git a/src/lib.rs b/src/lib.rs index cd40856..9bedb0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ +pub mod macros; pub mod types; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..042cdcb --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,113 @@ +// Define the macro that generates the implementation for the enum +#[macro_export] +macro_rules! implement_boolean_enum { + ($module_name:ident, $enum_name:ident) => { + 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 +}