feat: orgs, hooks, teams, labels
This commit is contained in:
parent
e343273668
commit
01696c7e0e
69 changed files with 55489 additions and 650 deletions
243
Cargo.lock
generated
243
Cargo.lock
generated
|
@ -38,6 +38,15 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -65,6 +74,12 @@ version = "3.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
|
@ -195,6 +210,18 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fast-srgb8"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "forgejo-api-types"
|
||||
version = "0.1.0"
|
||||
|
@ -203,6 +230,8 @@ dependencies = [
|
|||
"clap",
|
||||
"color-eyre",
|
||||
"derive-new",
|
||||
"hyper",
|
||||
"palette",
|
||||
"serde",
|
||||
"serde-email",
|
||||
"serde_json",
|
||||
|
@ -219,6 +248,39 @@ dependencies = [
|
|||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
|
@ -231,6 +293,62 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.57"
|
||||
|
@ -348,18 +466,90 @@ version = "3.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "palette"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1641aee47803391405d0a1250e837d2336fdddd18b27f3ddb8c1d80ce8d7f43"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"fast-srgb8",
|
||||
"palette_derive",
|
||||
"phf",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "palette_derive"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c02bfa6b3ba8af5434fa0531bf5701f750d983d4260acd6867faca51cdc4484"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
|
@ -378,6 +568,21 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
|
@ -446,6 +651,12 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.25.0"
|
||||
|
@ -526,6 +737,23 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
|
@ -568,6 +796,12 @@ dependencies = [
|
|||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
|
@ -607,6 +841,15 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
|
|
|
@ -8,12 +8,12 @@ edition = "2021"
|
|||
[dependencies]
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
clap = { version = "4.3", default-features = false, features = ["derive", "std"] }
|
||||
serde_json = "1.0"
|
||||
color-eyre = "0.6"
|
||||
derive-new = "0.5"
|
||||
hyper = "0.14.27"
|
||||
palette = { version = "0.7.2", features = ["serializing"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde-email = "2.1"
|
||||
strum = { version = "0.25", features = ["derive"] }
|
||||
url = { version = "2.4", features = ["serde"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
|
|
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
docs: https://codeberg.org/api/swagger#/organization/orgCreateHook
|
|
@ -1,14 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Branch {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Display for Branch {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::types::api::user::User;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Comment {
|
||||
pub body: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub id: usize,
|
||||
pub user: User,
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CreateCommentOption {
|
||||
body: String,
|
||||
}
|
||||
|
||||
impl CreateCommentOption {
|
||||
pub fn new(body: String) -> Self {
|
||||
Self { body }
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CreateForkOption {
|
||||
name: Option<String>,
|
||||
organization: Option<String>,
|
||||
}
|
||||
|
||||
impl CreateForkOption {
|
||||
pub fn same_repo_name() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
organization: None,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CreateIssueOption {
|
||||
title: String,
|
||||
body: String,
|
||||
assignees: Vec<String>,
|
||||
labels: Vec<usize>,
|
||||
milestone: Option<usize>,
|
||||
}
|
||||
|
||||
impl CreateIssueOption {
|
||||
pub fn new(title: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
body: Default::default(),
|
||||
assignees: Default::default(),
|
||||
labels: Default::default(),
|
||||
milestone: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_body(mut self, body: String) -> Self {
|
||||
self.body = body;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_assignees(mut self, assignees: Vec<String>) -> Self {
|
||||
self.assignees = assignees;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_labels(mut self, labels: Vec<usize>) -> Self {
|
||||
self.labels = labels;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_milestone(mut self, milestone_id: usize) -> Self {
|
||||
self.milestone.replace(milestone_id);
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CreateLabelOption {
|
||||
color: String,
|
||||
description: String,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl CreateLabelOption {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
color: String::from("#000000"),
|
||||
description: String::from("No description"),
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_color(mut self, color: String) -> Self {
|
||||
self.color = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: String) -> Self {
|
||||
self.description = description;
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CreateMilestoneOption {
|
||||
title: String,
|
||||
due_on: Option<String>,
|
||||
description: Option<String>,
|
||||
}
|
||||
|
||||
impl CreateMilestoneOption {
|
||||
pub fn new(title: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
due_on: Default::default(),
|
||||
description: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: String) -> Self {
|
||||
self.description.replace(description);
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CreatePullRequestOption {
|
||||
assignees: Vec<String>,
|
||||
base: String,
|
||||
body: String,
|
||||
head: String,
|
||||
labels: Vec<usize>,
|
||||
title: String,
|
||||
milestone: Option<usize>,
|
||||
}
|
||||
|
||||
impl CreatePullRequestOption {
|
||||
pub fn new(title: String, from: String, to: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
head: from,
|
||||
base: to,
|
||||
assignees: Default::default(),
|
||||
body: Default::default(),
|
||||
labels: Default::default(),
|
||||
milestone: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_assignees(mut self, assignees: Vec<String>) -> Self {
|
||||
self.assignees = assignees;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: String) -> Self {
|
||||
self.body = description;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_labels(mut self, labels: Vec<usize>) -> Self {
|
||||
self.labels = labels;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_milestone(mut self, milestone_id: usize) -> Self {
|
||||
self.milestone.replace(milestone_id);
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CreateRepoOption {
|
||||
default_branch: String,
|
||||
description: String,
|
||||
name: String,
|
||||
private: bool,
|
||||
readme: String,
|
||||
}
|
||||
|
||||
impl CreateRepoOption {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
default_branch: String::from("main"),
|
||||
description: Default::default(),
|
||||
name,
|
||||
private: true,
|
||||
readme: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_default_branch(mut self, default_branch: String) -> Self {
|
||||
self.default_branch = default_branch;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: String) -> Self {
|
||||
self.description = description;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn private(mut self) -> Self {
|
||||
self.private = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn public(mut self) -> Self {
|
||||
self.private = false;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_readme(mut self, readme: String) -> Self {
|
||||
self.readme = readme;
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
pub mod create_comment_option;
|
||||
pub mod create_fork_option;
|
||||
pub mod create_issue_options;
|
||||
pub mod create_label_options;
|
||||
pub mod create_milestone_option;
|
||||
pub mod create_pull_request_option;
|
||||
pub mod create_repo_options;
|
47
src/types/api/creation/label.rs
Normal file
47
src/types/api/creation/label.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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)]
|
||||
pub struct CreateLabelOption {
|
||||
/// The color of the label (in hexadecimal format).
|
||||
pub color: Color,
|
||||
/// The description of the label.
|
||||
pub description: String,
|
||||
/// Indicates whether the label is exclusive.
|
||||
pub exclusive: Exclusive,
|
||||
/// The name of the label.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Display for CreateLabelOption {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "CreateLabelOption: {}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use palette::rgb::Rgb;
|
||||
|
||||
use crate::types::api::creation::label::CreateLabelOption;
|
||||
use crate::types::misc::color::Color;
|
||||
use crate::types::misc::exclusive::Exclusive;
|
||||
|
||||
#[test]
|
||||
fn deserialize_create_label_option() {
|
||||
let json_data = include_str!("../../../../test_data/example_create_label.json");
|
||||
let option: CreateLabelOption = serde_json::from_str(&json_data).unwrap();
|
||||
let expected = CreateLabelOption {
|
||||
color: Color(Rgb::new(0x00, 0xaa, 0xbb)),
|
||||
description: "CreateLabelOption options for creating a label".to_string(),
|
||||
exclusive: Exclusive::No,
|
||||
name: "example_label".to_string(),
|
||||
};
|
||||
assert_eq!(option, expected);
|
||||
}
|
||||
}
|
2
src/types/api/creation/mod.rs
Normal file
2
src/types/api/creation/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod label;
|
||||
pub mod organization;
|
60
src/types/api/creation/organization.rs
Normal file
60
src/types/api/creation/organization.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
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::visibility::Visibility;
|
||||
|
||||
/// CreateOrgOption represents options for creating an organization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct CreateOrgOption {
|
||||
/// The organization's description
|
||||
pub description: String,
|
||||
/// Full name of the organization
|
||||
pub full_name: String,
|
||||
/// 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,
|
||||
/// The organization's username
|
||||
pub username: String,
|
||||
/// Visibility of the organization
|
||||
pub visibility: Visibility,
|
||||
/// The organization's website URL (optional)
|
||||
pub website: OptionalUrl,
|
||||
}
|
||||
|
||||
impl Display for CreateOrgOption {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "CreateOrgOption: {}", self.full_name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
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::visibility::Visibility;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../../test_data/example_create_organization.json");
|
||||
let org_option: CreateOrgOption = serde_json::from_str(data).unwrap();
|
||||
let expected = CreateOrgOption {
|
||||
description: String::from("Sample organization"),
|
||||
full_name: String::from("SampleOrg"),
|
||||
location: String::from("Sample City, Country"),
|
||||
repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::Yes,
|
||||
username: String::from("sample_org"),
|
||||
visibility: Visibility::Public,
|
||||
website: OptionalUrl::Some(Url::from_str("https://sample.org").unwrap()),
|
||||
};
|
||||
assert_eq!(org_option, expected);
|
||||
}
|
||||
}
|
57
src/types/api/edit/hook.rs
Normal file
57
src/types/api/edit/hook.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::types::misc::active::ActiveStatus;
|
||||
use crate::types::misc::header::Header;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct EditHookOption {
|
||||
/// Description of the options when modifying a hook
|
||||
description: String,
|
||||
/// Boolean flag indicating if the hook is active
|
||||
active: ActiveStatus,
|
||||
/// Authorization header for the hook (if required)
|
||||
authorization_header: Header,
|
||||
/// Branch filter for the hook
|
||||
branch_filter: String,
|
||||
/// Configuration options for the hook
|
||||
config: HashMap<String, String>,
|
||||
/// Events that trigger the hook
|
||||
events: Vec<String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use hyper::http::{HeaderName, HeaderValue};
|
||||
|
||||
use crate::types::api::edit::hook::EditHookOption;
|
||||
use crate::types::misc::active::ActiveStatus;
|
||||
use crate::types::misc::header::Header;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../../test_data/example_edit_hook.json");
|
||||
|
||||
let edit_hook_option: EditHookOption = serde_json::from_str(data).unwrap();
|
||||
// Example usage:
|
||||
let expected = EditHookOption {
|
||||
description: "Options when modifying a hook".to_string(),
|
||||
active: ActiveStatus::Active,
|
||||
authorization_header: Header(hyper::HeaderMap::from_iter(std::iter::once((
|
||||
HeaderName::from_static("bearer"),
|
||||
HeaderValue::from_static("TOKEN"),
|
||||
)))),
|
||||
branch_filter: "main".to_string(),
|
||||
config: {
|
||||
let mut config = HashMap::new();
|
||||
config.insert("key1".to_string(), "value1".to_string());
|
||||
config.insert("key2".to_string(), "value2".to_string());
|
||||
config
|
||||
},
|
||||
events: vec!["push".to_string(), "pull_request".to_string()],
|
||||
};
|
||||
assert_eq!(edit_hook_option, expected);
|
||||
}
|
||||
}
|
47
src/types/api/edit/label.rs
Normal file
47
src/types/api/edit/label.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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)]
|
||||
pub struct EditLabelOption {
|
||||
/// The color of the label (in hexadecimal format).
|
||||
pub color: Color,
|
||||
/// The description of the label.
|
||||
pub description: String,
|
||||
/// Indicates whether the label is exclusive.
|
||||
pub exclusive: Exclusive,
|
||||
/// The name of the label.
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Display for EditLabelOption {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "EditLabelOption: {}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use palette::rgb::Rgb;
|
||||
|
||||
use crate::types::api::creation::label::CreateLabelOption;
|
||||
use crate::types::misc::color::Color;
|
||||
use crate::types::misc::exclusive::Exclusive;
|
||||
|
||||
#[test]
|
||||
fn deserialize_edit_label_option() {
|
||||
let json_data = include_str!("../../../../test_data/example_edit_label.json");
|
||||
let option: CreateLabelOption = serde_json::from_str(&json_data).unwrap();
|
||||
let expected = CreateLabelOption {
|
||||
color: Color(Rgb::new(0x00, 0xaa, 0xbb)),
|
||||
description: "EditLabelOption options for updating a label".to_string(),
|
||||
exclusive: Exclusive::No,
|
||||
name: "example_label".to_string(),
|
||||
};
|
||||
assert_eq!(option, expected);
|
||||
}
|
||||
}
|
3
src/types/api/edit/mod.rs
Normal file
3
src/types/api/edit/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod hook;
|
||||
pub mod label;
|
||||
pub mod organization;
|
57
src/types/api/edit/organization.rs
Normal file
57
src/types/api/edit/organization.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
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::visibility::Visibility;
|
||||
|
||||
/// EditOrgOption represents options for editing an organization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct EditOrgOption {
|
||||
/// The organization's description
|
||||
pub description: String,
|
||||
/// Full name of the organization
|
||||
pub full_name: String,
|
||||
/// 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,
|
||||
/// Visibility of the organization
|
||||
pub visibility: Visibility,
|
||||
/// The organization's website URL (optional)
|
||||
pub website: OptionalUrl,
|
||||
}
|
||||
|
||||
impl Display for EditOrgOption {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "EditOrgOption: {}", self.full_name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
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::visibility::Visibility;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../../test_data/example_edit_organization.json");
|
||||
|
||||
let edit_org_option: EditOrgOption = serde_json::from_str(data).unwrap();
|
||||
let expected = EditOrgOption {
|
||||
description: String::from("Updated organization"),
|
||||
full_name: String::from("UpdatedOrg"),
|
||||
location: String::from("Updated City, Country"),
|
||||
repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::No,
|
||||
visibility: Visibility::Private,
|
||||
website: OptionalUrl::Some(Url::from_str("https://updated.org").unwrap()),
|
||||
};
|
||||
assert_eq!(edit_org_option, expected);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::api::issue::Issue;
|
||||
use crate::types::api::state_type::StateType;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Default)]
|
||||
pub struct EditIssueOption {
|
||||
pub assignees: Option<Vec<String>>,
|
||||
pub body: Option<String>,
|
||||
pub state: Option<StateType>,
|
||||
pub title: Option<String>,
|
||||
}
|
||||
|
||||
impl EditIssueOption {
|
||||
pub fn from_issue(issue: &Issue) -> Self {
|
||||
Self {
|
||||
assignees: issue.assignees.as_ref().map(|assignees| {
|
||||
assignees
|
||||
.iter()
|
||||
.map(|assignee| assignee.login.to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
}),
|
||||
body: Some(issue.body.clone()),
|
||||
state: issue
|
||||
.pull_request
|
||||
.as_ref()
|
||||
.map(|pr_meta| (!pr_meta.merged).then_some(issue.state))
|
||||
.unwrap_or(Some(issue.state)),
|
||||
title: Some(issue.title.clone()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::api::label::Label;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Default)]
|
||||
pub struct EditLabelOption {
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub color: Option<String>,
|
||||
}
|
||||
|
||||
impl EditLabelOption {
|
||||
pub fn from_label(label: &Label) -> Self {
|
||||
Self {
|
||||
name: Some(label.name.to_string()),
|
||||
description: Some(label.description.to_string()),
|
||||
color: Some(label.color.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::types::api::milestone::Milestone;
|
||||
use crate::types::api::state_type::StateType;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Default)]
|
||||
pub struct EditMilestoneOption {
|
||||
pub description: Option<String>,
|
||||
pub state: Option<StateType>,
|
||||
pub title: Option<String>,
|
||||
pub due_on: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl EditMilestoneOption {
|
||||
pub fn from_milestone(milestone: &Milestone) -> Self {
|
||||
Self {
|
||||
description: milestone.description.clone(),
|
||||
due_on: milestone.due_on,
|
||||
state: Some(milestone.state),
|
||||
title: Some(milestone.title.clone()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::types::api::pull_request::PullRequest;
|
||||
use crate::types::api::state_type::StateType;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Default)]
|
||||
pub struct EditPullRequestOption {
|
||||
pub assignees: Option<Vec<String>>,
|
||||
pub body: Option<String>,
|
||||
pub state: Option<StateType>,
|
||||
pub title: Option<String>,
|
||||
pub labels: Option<Vec<usize>>,
|
||||
}
|
||||
|
||||
impl EditPullRequestOption {
|
||||
pub fn from_pull_request(pr: &PullRequest) -> Self {
|
||||
Self {
|
||||
assignees: pr.assignees.as_ref().map(|assignees| {
|
||||
assignees
|
||||
.iter()
|
||||
.map(|assignee| assignee.login.to_owned())
|
||||
.collect::<Vec<_>>()
|
||||
}),
|
||||
body: Some(pr.body.clone()),
|
||||
state: (!pr.merged).then_some(pr.state),
|
||||
title: Some(pr.title.clone()),
|
||||
labels: Some(pr.labels.iter().map(|label| label.id).collect::<Vec<_>>()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
pub mod edit_issue_option;
|
||||
pub mod edit_label_option;
|
||||
pub mod edit_milestone_option;
|
||||
pub mod edit_pull_request_option;
|
|
@ -1,4 +0,0 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct FollowersInfo {}
|
|
@ -1,4 +0,0 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct FollowingInfo {}
|
80
src/types/api/hook.rs
Normal file
80
src/types/api/hook.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::types::misc::active::ActiveStatus;
|
||||
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,
|
||||
/// 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
|
||||
/// what it does
|
||||
pub authorization_header: Header,
|
||||
/// Configuration options for the hook
|
||||
pub config: HashMap<String, String>,
|
||||
/// Timestamp when the hook was created
|
||||
pub created_at: DateTime<Utc>,
|
||||
/// Events that trigger the hook
|
||||
pub events: Vec<String>,
|
||||
/// Unique ID of the hook
|
||||
pub id: usize,
|
||||
// 🚧🚧 TODO 🚧🚧 : enum?
|
||||
/// Type of the hook
|
||||
pub r#type: String,
|
||||
/// Timestamp when the hook was last updated
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Display for Hook {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Hook ID: {}", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use chrono::DateTime;
|
||||
use hyper::http::{HeaderName, HeaderValue};
|
||||
|
||||
use crate::types::api::hook::Hook;
|
||||
use crate::types::misc::active::ActiveStatus;
|
||||
use crate::types::misc::header::Header;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../test_data/example_hook.json");
|
||||
|
||||
let hook: Hook = serde_json::from_str(data).unwrap();
|
||||
let expected = Hook {
|
||||
active: ActiveStatus::Active,
|
||||
authorization_header: Header(hyper::HeaderMap::from_iter(std::iter::once((
|
||||
HeaderName::from_static("bearer"),
|
||||
HeaderValue::from_static("TOKEN"),
|
||||
)))),
|
||||
config: {
|
||||
let mut config = HashMap::new();
|
||||
config.insert(
|
||||
String::from("url"),
|
||||
String::from("https://example.com/webhook"),
|
||||
);
|
||||
config.insert(String::from("content_type"), String::from("json"));
|
||||
config
|
||||
},
|
||||
created_at: DateTime::from_str("2023-07-27T12:34:56Z").unwrap(),
|
||||
events: vec![String::from("push"), String::from("pull_request")],
|
||||
id: 123456,
|
||||
r#type: String::from("web"),
|
||||
updated_at: DateTime::from_str("2023-07-27T14:45:56Z").unwrap(),
|
||||
};
|
||||
assert_eq!(hook, expected);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::types::api::label::Label;
|
||||
use crate::types::api::milestone::Milestone;
|
||||
use crate::types::api::pull_request_meta::PullRequestMeta;
|
||||
use crate::types::api::state_type::StateType;
|
||||
use crate::types::api::user::User;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Issue {
|
||||
pub title: String,
|
||||
pub number: usize,
|
||||
pub labels: Vec<Label>,
|
||||
pub assignees: Option<Vec<User>>,
|
||||
pub body: String,
|
||||
pub state: StateType,
|
||||
pub pull_request: Option<PullRequestMeta>,
|
||||
pub milestone: Option<Milestone>,
|
||||
pub closed_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub due_date: Option<DateTime<Utc>>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Display for Issue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#{} {}", self.number, self.title)
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct IssueLabelsOption {
|
||||
pub labels: Vec<usize>,
|
||||
}
|
|
@ -1,13 +1,26 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
||||
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)]
|
||||
pub struct Label {
|
||||
pub color: String,
|
||||
/// The color of the label (in hexadecimal format).
|
||||
pub color: Color,
|
||||
/// The description of the label.
|
||||
pub description: String,
|
||||
pub name: String,
|
||||
/// Indicates whether the label is exclusive.
|
||||
pub exclusive: Exclusive,
|
||||
/// The unique ID of the label.
|
||||
pub id: usize,
|
||||
/// The name of the label.
|
||||
pub name: String,
|
||||
/// The URL of the label.
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
impl Display for Label {
|
||||
|
@ -15,3 +28,30 @@ impl Display for Label {
|
|||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use palette::rgb::Rgb;
|
||||
use url::Url;
|
||||
|
||||
use crate::types::api::label::Label;
|
||||
use crate::types::misc::color::Color;
|
||||
use crate::types::misc::exclusive::Exclusive;
|
||||
|
||||
#[test]
|
||||
fn deserialize_label() {
|
||||
let data = include_str!("../../../test_data/example_label.json");
|
||||
let label: Label = serde_json::from_str(&data).unwrap();
|
||||
let expected = Label {
|
||||
color: Color(Rgb::from_str("00aabb").unwrap()),
|
||||
description: "Label a label to an issue or a pr".to_string(),
|
||||
exclusive: Exclusive::No,
|
||||
id: 42,
|
||||
name: "bug".to_string(),
|
||||
url: Url::from_str("https://example.com/labels/bug").unwrap(),
|
||||
};
|
||||
assert_eq!(label, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::api::state_type::StateType;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Milestone {
|
||||
pub id: usize,
|
||||
pub title: String,
|
||||
pub due_on: Option<DateTime<Utc>>,
|
||||
pub state: StateType,
|
||||
pub open_issues: usize,
|
||||
pub closed_issues: usize,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
impl Display for Milestone {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.title)
|
||||
}
|
||||
}
|
|
@ -1,18 +1,7 @@
|
|||
pub mod branch;
|
||||
pub mod comment;
|
||||
pub mod create_options;
|
||||
pub mod edit_options;
|
||||
pub mod followers_info;
|
||||
pub mod following_info;
|
||||
pub mod issue;
|
||||
pub mod issue_labels_option;
|
||||
pub mod creation;
|
||||
pub mod edit;
|
||||
pub mod hook;
|
||||
pub mod label;
|
||||
pub mod milestone;
|
||||
pub mod notification;
|
||||
pub mod privacy_type;
|
||||
pub mod pull_request;
|
||||
pub mod pull_request_meta;
|
||||
pub mod repository;
|
||||
pub mod search_results;
|
||||
pub mod state_type;
|
||||
pub mod organization;
|
||||
pub mod team;
|
||||
pub mod user;
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
pub mod notification_count;
|
||||
pub mod notification_state_type;
|
||||
pub mod notification_subject;
|
||||
pub mod notification_thread;
|
||||
pub mod notification_type;
|
|
@ -1,6 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NotificationCount {
|
||||
new: usize,
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
use clap::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumIter, EnumString};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ValueEnum, Display, EnumIter, EnumString)]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[serde(rename(serialize = "lowercase"))]
|
||||
pub enum NotificationStateType {
|
||||
Unread,
|
||||
Read,
|
||||
Pinned,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ValueEnum, Display, EnumIter, EnumString)]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum NotificationStateTypeApi {
|
||||
Closed,
|
||||
Open,
|
||||
All,
|
||||
Merged,
|
||||
}
|
||||
|
||||
impl NotificationStateType {
|
||||
pub fn available_for_choosing() -> [Self; 3] {
|
||||
use NotificationStateType::*;
|
||||
[Unread, Read, Pinned]
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::api::notification::notification_state_type::NotificationStateTypeApi;
|
||||
use crate::types::api::notification::notification_type::NotificationSubjectType;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NotificationSubject {
|
||||
pub html_url: String,
|
||||
pub latest_comment_html_url: String,
|
||||
pub latest_comment_url: String,
|
||||
pub state: NotificationStateTypeApi,
|
||||
pub title: String,
|
||||
#[serde(rename = "type")]
|
||||
pub notify_type: NotificationSubjectType,
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::api::notification::notification_subject::NotificationSubject;
|
||||
use crate::types::api::repository::Repository;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NotificationThread {
|
||||
pub id: usize,
|
||||
pub pinned: bool,
|
||||
pub repository: Repository,
|
||||
pub subject: NotificationSubject,
|
||||
pub unread: bool,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
impl Display for NotificationThread {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(if self.unread { "📕 " } else { "📖 " })?;
|
||||
if self.pinned {
|
||||
f.write_str("📌 ")?;
|
||||
}
|
||||
f.write_str(self.subject.title.as_str())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
use clap::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumIter, EnumString};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ValueEnum, Display, EnumIter, EnumString)]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[serde(rename(serialize = "lowercase"))]
|
||||
pub enum NotificationSubjectType {
|
||||
Issue,
|
||||
Pull,
|
||||
Commit,
|
||||
Repository,
|
||||
}
|
||||
impl NotificationSubjectType {
|
||||
pub fn available_for_choosing() -> [Self; 4] {
|
||||
use NotificationSubjectType::*;
|
||||
[Issue, Pull, Commit, Repository]
|
||||
}
|
||||
}
|
68
src/types/api/organization.rs
Normal file
68
src/types/api/organization.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess;
|
||||
use crate::types::misc::url::OptionalUrl;
|
||||
|
||||
/// Organization represents an organization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Organization {
|
||||
/// URL to the organization's avatar
|
||||
pub avatar_url: Url,
|
||||
/// The organization's description (optional)
|
||||
pub description: String,
|
||||
/// Full name of the organization (optional)
|
||||
pub full_name: String,
|
||||
/// An unique ID
|
||||
pub id: usize,
|
||||
/// Location of the organization as a string (optional)
|
||||
pub location: String,
|
||||
/// Name of the organization
|
||||
pub name: String,
|
||||
/// Boolean flag indicating if repo admin can change team access
|
||||
pub repo_admin_change_team_access: RepoAdminCanChangeTeamAccess,
|
||||
/// The organization's username
|
||||
pub username: String,
|
||||
/// The organization's website URL (optional)
|
||||
pub website: OptionalUrl,
|
||||
}
|
||||
|
||||
impl Display for Organization {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
|
||||
use url::Url;
|
||||
|
||||
use crate::types::api::organization::Organization;
|
||||
use crate::types::misc::team_access::RepoAdminCanChangeTeamAccess;
|
||||
use crate::types::misc::url::OptionalUrl;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../test_data/example_organization.json");
|
||||
let org: Organization = serde_json::from_str(&data).unwrap();
|
||||
let expected = Organization {
|
||||
avatar_url: Url::from_str(
|
||||
"https://codeberg.org/avatars/9efc314b65237d5d646e1b817372afc6",
|
||||
)
|
||||
.unwrap(),
|
||||
description: String::from(""),
|
||||
full_name: String::from(""),
|
||||
id: 77294,
|
||||
location: String::from(""),
|
||||
name: String::from("---"),
|
||||
repo_admin_change_team_access: RepoAdminCanChangeTeamAccess::Yes,
|
||||
username: String::from("---"),
|
||||
website: OptionalUrl::None,
|
||||
};
|
||||
assert_eq!(org, expected);
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
use clap::ValueEnum;
|
||||
use strum::{Display, EnumIter, EnumString};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Display, EnumString, ValueEnum, EnumIter)]
|
||||
pub enum Privacy {
|
||||
#[default]
|
||||
Private,
|
||||
Public,
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::types::api::label::Label;
|
||||
use crate::types::api::milestone::Milestone;
|
||||
use crate::types::api::state_type::StateType;
|
||||
use crate::types::api::user::User;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct PullRequest {
|
||||
pub title: String,
|
||||
pub body: String,
|
||||
pub number: usize,
|
||||
pub labels: Vec<Label>,
|
||||
pub state: StateType,
|
||||
pub assignees: Option<Vec<User>>,
|
||||
pub milestone: Option<Milestone>,
|
||||
pub merged: bool,
|
||||
pub closed_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub due_date: Option<DateTime<Utc>>,
|
||||
pub merged_at: Option<DateTime<Utc>>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Display for PullRequest {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#{} {}", self.number, self.title)
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct PullRequestMeta {
|
||||
pub merged: bool,
|
||||
pub merged_at: Option<String>,
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::api::user::User;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Repository {
|
||||
pub name: String,
|
||||
pub owner: User,
|
||||
pub stars_count: usize,
|
||||
pub ssh_url: String,
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct SearchResults<T> {
|
||||
pub data: T,
|
||||
pub ok: bool,
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use clap::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumIter, EnumString};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ValueEnum, Display, EnumIter, EnumString)]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum StateType {
|
||||
Closed,
|
||||
Open,
|
||||
All,
|
||||
}
|
||||
|
||||
impl StateType {
|
||||
pub fn available_for_choosing() -> [Self; 2] {
|
||||
use StateType::*;
|
||||
[Closed, Open]
|
||||
}
|
||||
|
||||
pub fn is_done(&self) -> bool {
|
||||
use StateType::*;
|
||||
match self {
|
||||
Closed => true,
|
||||
Open => false,
|
||||
All => false,
|
||||
}
|
||||
}
|
||||
}
|
83
src/types/api/team.rs
Normal file
83
src/types/api/team.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use std::collections::HashMap;
|
||||
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::team_permissions::TeamPermission;
|
||||
|
||||
/// Team represents a team in an organization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Team {
|
||||
/// Whether the team can create organization repositories
|
||||
pub can_create_org_repo: CanCreateOrgRepo,
|
||||
/// Description of the team
|
||||
pub description: String,
|
||||
/// ID of the team
|
||||
pub id: usize,
|
||||
/// Whether the team includes all org repositories
|
||||
pub includes_all_repositories: IncludesAllRepositories,
|
||||
/// Name of the team
|
||||
pub name: String,
|
||||
/// Organization the team belongs to
|
||||
pub organization: Organization,
|
||||
/// Permission level of the team
|
||||
pub permission: TeamPermission,
|
||||
/// Units that the team has access to
|
||||
pub units: Vec<String>,
|
||||
/// Units and their corresponding permission as a map
|
||||
pub units_map: HashMap<String, TeamPermission>,
|
||||
}
|
||||
|
||||
impl Display for Team {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Team: {}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
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::team_permissions::TeamPermission;
|
||||
|
||||
#[test]
|
||||
fn deserialize_team_works() {
|
||||
let data = include_str!("../../../test_data/example_team.json");
|
||||
let team: Team = serde_json::from_str(data).unwrap();
|
||||
|
||||
let example_org: Organization =
|
||||
serde_json::from_str(include_str!("../../../test_data/example_organization.json"))
|
||||
.unwrap();
|
||||
let expected = Team {
|
||||
can_create_org_repo: CanCreateOrgRepo::Yes,
|
||||
description: String::from("Example team description"),
|
||||
id: 12345,
|
||||
includes_all_repositories: IncludesAllRepositories::No,
|
||||
name: String::from("Example Team"),
|
||||
organization: example_org,
|
||||
permission: TeamPermission::Admin,
|
||||
//🚧🚧 TODO 🚧🚧 : Units as enum?
|
||||
units: vec![
|
||||
"repo.code".to_string(),
|
||||
"repo.issues".to_string(),
|
||||
"repo.ext_issues".to_string(),
|
||||
],
|
||||
units_map: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert("repo.code".to_string(), TeamPermission::Read);
|
||||
map.insert("repo.issues".to_string(), TeamPermission::Write);
|
||||
map.insert("repo.ext_issues".to_string(), TeamPermission::None);
|
||||
map
|
||||
},
|
||||
};
|
||||
|
||||
assert_eq!(team, expected);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ use url::Url;
|
|||
use crate::types::misc::active::ActiveStatus;
|
||||
use crate::types::misc::admin::AdminStatus;
|
||||
use crate::types::misc::locale::Locale;
|
||||
use crate::types::misc::url::OptionalUrl;
|
||||
use crate::types::misc::visibility::Visibility;
|
||||
|
||||
/// User represents a user
|
||||
|
@ -43,8 +44,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
|
||||
/// is user restricted
|
||||
pub restricted: bool,
|
||||
/// stars the user gave other repos
|
||||
|
@ -54,7 +57,7 @@ pub struct User {
|
|||
/// visibility of user
|
||||
pub visibility: Visibility,
|
||||
/// personal website (optional)
|
||||
pub website: Url,
|
||||
pub website: OptionalUrl,
|
||||
}
|
||||
|
||||
impl Display for User {
|
||||
|
@ -75,11 +78,12 @@ mod tests {
|
|||
use crate::types::misc::active::ActiveStatus;
|
||||
use crate::types::misc::admin::AdminStatus;
|
||||
use crate::types::misc::locale::Locale;
|
||||
use crate::types::misc::url::OptionalUrl;
|
||||
use crate::types::misc::visibility::Visibility;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../test_data/example_user.json");
|
||||
let data = include_str!("../../../test_data/example_user.json");
|
||||
let user: User = serde_json::from_str(&data).unwrap();
|
||||
let expected = User {
|
||||
active: ActiveStatus::Active,
|
||||
|
@ -102,7 +106,7 @@ mod tests {
|
|||
starred_repos_count: 0,
|
||||
username: String::from("ExampleUser"),
|
||||
visibility: Visibility::Public,
|
||||
website: Url::from_str("https://example.com").unwrap(),
|
||||
website: OptionalUrl::Some(Url::from_str("https://example.com").unwrap()),
|
||||
};
|
||||
assert_eq!(user, expected);
|
||||
}
|
||||
|
|
87
src/types/misc/can_create_org_repo.rs
Normal file
87
src/types/misc/can_create_org_repo.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
if v {
|
||||
Ok(CanCreateOrgRepo::Yes)
|
||||
} else {
|
||||
Ok(CanCreateOrgRepo::No)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for CanCreateOrgRepo {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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");
|
||||
}
|
||||
}
|
108
src/types/misc/color.rs
Normal file
108
src/types/misc/color.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use palette::rgb::Rgb;
|
||||
use palette::Srgb;
|
||||
use serde::de::Visitor;
|
||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Color(pub(crate) Rgb<Srgb, u8>);
|
||||
|
||||
impl Deref for Color {
|
||||
type Target = Rgb<Srgb, u8>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Color {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Color {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// Convert the RGB color to a six-digit hexadecimal string
|
||||
let hex_string =
|
||||
format!("#{:02X}{:02X}{:02X}", self.red, self.green, self.blue).to_lowercase();
|
||||
serializer.serialize_str(&hex_string)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Color {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ColorVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ColorVisitor {
|
||||
type Value = Color;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a hex color string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
// convert to simplified hex string
|
||||
let start_char = if v.starts_with('#') { 1 } else { 0 };
|
||||
let hex_string = v[start_char..].to_lowercase();
|
||||
|
||||
// Parse the hexadecimal string to an RGB color
|
||||
let r = u8::from_str_radix(&hex_string[0..2], 16).map_err(Error::custom)?;
|
||||
let g = u8::from_str_radix(&hex_string[2..4], 16).map_err(Error::custom)?;
|
||||
let b = u8::from_str_radix(&hex_string[4..6], 16).map_err(Error::custom)?;
|
||||
|
||||
Ok(Color(Rgb::new(r, g, b)))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(ColorVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod color {
|
||||
use palette::rgb::Rgb;
|
||||
|
||||
use crate::types::misc::color::Color;
|
||||
|
||||
#[test]
|
||||
fn color_serialize() {
|
||||
// Example of serializing and deserializing
|
||||
let rgb_color = Color(Rgb::new(100, 50, 200));
|
||||
let rgb_color_str = "\"#6432c8\"";
|
||||
|
||||
let serialized = serde_json::to_string(&rgb_color).unwrap();
|
||||
assert_eq!(serialized, rgb_color_str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn color_deserialize() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn color_deserialize_panic() {
|
||||
// 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);
|
||||
}
|
||||
}
|
87
src/types/misc/exclusive.rs
Normal file
87
src/types/misc/exclusive.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
if v {
|
||||
Ok(Exclusive::Yes)
|
||||
} else {
|
||||
Ok(Exclusive::No)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Exclusive {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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");
|
||||
}
|
||||
}
|
104
src/types/misc/header.rs
Normal file
104
src/types/misc/header.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use hyper::header::{HeaderName, HeaderValue};
|
||||
use serde::ser::SerializeMap;
|
||||
use serde::{Deserialize, Serialize, Serializer};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Header(pub hyper::HeaderMap);
|
||||
|
||||
impl Deref for Header {
|
||||
type Target = hyper::HeaderMap;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Header {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
// Serialization
|
||||
impl Serialize for Header {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut map = serializer.serialize_map(Some(self.iter().count()))?;
|
||||
for (name, value) in self.iter() {
|
||||
let name_str = name.as_str();
|
||||
let value_str = String::from_utf8_lossy(value.as_bytes()).to_string();
|
||||
map.serialize_entry(&name_str, &value_str)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
// Deserialization
|
||||
impl<'de> Deserialize<'de> for Header {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
struct HeaderMapVisitor;
|
||||
|
||||
impl<'de> serde::de::Visitor<'de> for HeaderMapVisitor {
|
||||
type Value = Header;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a JSON object with header key-value pairs")
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: serde::de::MapAccess<'de>,
|
||||
{
|
||||
let mut headers = hyper::HeaderMap::new();
|
||||
while let Some((key, value)) = map.next_entry::<String, String>()? {
|
||||
let name_obj =
|
||||
HeaderName::from_bytes(key.as_bytes()).map_err(serde::de::Error::custom)?;
|
||||
let value_obj =
|
||||
HeaderValue::from_str(&value).map_err(serde::de::Error::custom)?;
|
||||
headers.insert(name_obj, value_obj);
|
||||
}
|
||||
Ok(Header(headers))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(HeaderMapVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod header {
|
||||
use hyper::http::{HeaderName, HeaderValue};
|
||||
|
||||
use crate::types::misc::header::Header;
|
||||
|
||||
#[test]
|
||||
fn deserialize_works() {
|
||||
let data = include_str!("../../../test_data/example_header_map.json");
|
||||
|
||||
let header: Header = serde_json::from_str(data).unwrap();
|
||||
|
||||
// Create a new HeaderMap
|
||||
let mut headers = hyper::HeaderMap::new();
|
||||
|
||||
// Add some example headers to the map
|
||||
headers.insert(
|
||||
HeaderName::from_static("content-type"),
|
||||
HeaderValue::from_static("application/json"),
|
||||
);
|
||||
|
||||
headers.insert(
|
||||
HeaderName::from_static("authorization"),
|
||||
HeaderValue::from_static("Bearer ABCDEFG123456789"),
|
||||
);
|
||||
let expected = Header(headers);
|
||||
|
||||
assert_eq!(header, expected);
|
||||
}
|
||||
}
|
88
src/types/misc/includes_all_repositories.rs
Normal file
88
src/types/misc/includes_all_repositories.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
if v {
|
||||
Ok(IncludesAllRepositories::Yes)
|
||||
} else {
|
||||
Ok(IncludesAllRepositories::No)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for IncludesAllRepositories {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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");
|
||||
}
|
||||
}
|
|
@ -1,4 +1,12 @@
|
|||
pub mod active;
|
||||
pub mod admin;
|
||||
pub mod can_create_org_repo;
|
||||
pub mod color;
|
||||
pub mod exclusive;
|
||||
pub mod header;
|
||||
pub mod includes_all_repositories;
|
||||
pub mod locale;
|
||||
pub mod team_access;
|
||||
pub mod team_permissions;
|
||||
pub mod url;
|
||||
pub mod visibility;
|
||||
|
|
80
src/types/misc/team_access.rs
Normal file
80
src/types/misc/team_access.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
if v {
|
||||
Ok(RepoAdminCanChangeTeamAccess::Yes)
|
||||
} else {
|
||||
Ok(RepoAdminCanChangeTeamAccess::No)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for RepoAdminCanChangeTeamAccess {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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")
|
||||
}
|
||||
}
|
19
src/types/misc/team_permissions.rs
Normal file
19
src/types/misc/team_permissions.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumIs};
|
||||
|
||||
/// Permission level of the team
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Display, EnumIs)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum TeamPermission {
|
||||
None,
|
||||
Read,
|
||||
Write,
|
||||
Admin,
|
||||
Owner,
|
||||
}
|
||||
|
||||
impl Default for TeamPermission {
|
||||
fn default() -> Self {
|
||||
TeamPermission::None
|
||||
}
|
||||
}
|
54
src/types/misc/url.rs
Normal file
54
src/types/misc/url.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
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 enum OptionalUrl {
|
||||
Some(Url),
|
||||
None,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for OptionalUrl {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct OptionalUrlVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for OptionalUrlVisitor {
|
||||
type Value = OptionalUrl;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a URL or an empty string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
if v.is_empty() {
|
||||
Ok(OptionalUrl::None)
|
||||
} else {
|
||||
Url::parse(v)
|
||||
.map(OptionalUrl::Some)
|
||||
.map_err(|_| E::custom("invalid URL"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(OptionalUrlVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for OptionalUrl {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match self {
|
||||
OptionalUrl::Some(url) => serializer.serialize_str(url.as_str()),
|
||||
OptionalUrl::None => serializer.serialize_str(""),
|
||||
}
|
||||
}
|
||||
}
|
6
test_data/example_create_label.json
Normal file
6
test_data/example_create_label.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"color": "#00aabb",
|
||||
"description": "CreateLabelOption options for creating a label",
|
||||
"exclusive": false,
|
||||
"name": "example_label"
|
||||
}
|
9
test_data/example_create_organization.json
Normal file
9
test_data/example_create_organization.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"description": "Sample organization",
|
||||
"full_name": "SampleOrg",
|
||||
"location": "Sample City, Country",
|
||||
"repo_admin_change_team_access": true,
|
||||
"username": "sample_org",
|
||||
"visibility": "public",
|
||||
"website": "https://sample.org"
|
||||
}
|
16
test_data/example_edit_hook.json
Normal file
16
test_data/example_edit_hook.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"description": "Options when modifying a hook",
|
||||
"active": true,
|
||||
"authorization_header": {
|
||||
"Bearer": "TOKEN"
|
||||
},
|
||||
"branch_filter": "main",
|
||||
"config": {
|
||||
"key1": "value1",
|
||||
"key2": "value2"
|
||||
},
|
||||
"events": [
|
||||
"push",
|
||||
"pull_request"
|
||||
]
|
||||
}
|
6
test_data/example_edit_label.json
Normal file
6
test_data/example_edit_label.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"color": "#00aabb",
|
||||
"description": "EditLabelOption options for updating a label",
|
||||
"exclusive": false,
|
||||
"name": "example_label"
|
||||
}
|
8
test_data/example_edit_organization.json
Normal file
8
test_data/example_edit_organization.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"description": "Updated organization",
|
||||
"full_name": "UpdatedOrg",
|
||||
"location": "Updated City, Country",
|
||||
"repo_admin_change_team_access": false,
|
||||
"visibility": "private",
|
||||
"website": "https://updated.org"
|
||||
}
|
4
test_data/example_header_map.json
Normal file
4
test_data/example_header_map.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer ABCDEFG123456789"
|
||||
}
|
18
test_data/example_hook.json
Normal file
18
test_data/example_hook.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"active": true,
|
||||
"authorization_header": {
|
||||
"Bearer": "TOKEN"
|
||||
},
|
||||
"config": {
|
||||
"url": "https://example.com/webhook",
|
||||
"content_type": "json"
|
||||
},
|
||||
"created_at": "2023-07-27T12:34:56Z",
|
||||
"events": [
|
||||
"push",
|
||||
"pull_request"
|
||||
],
|
||||
"id": 123456,
|
||||
"type": "web",
|
||||
"updated_at": "2023-07-27T14:45:56Z"
|
||||
}
|
8
test_data/example_label.json
Normal file
8
test_data/example_label.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"color": "00aabb",
|
||||
"description": "Label a label to an issue or a pr",
|
||||
"exclusive": false,
|
||||
"id": 42,
|
||||
"name": "bug",
|
||||
"url": "https://example.com/labels/bug"
|
||||
}
|
12
test_data/example_organization.json
Normal file
12
test_data/example_organization.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"id": 77294,
|
||||
"name": "---",
|
||||
"full_name": "",
|
||||
"avatar_url": "https://codeberg.org/avatars/9efc314b65237d5d646e1b817372afc6",
|
||||
"description": "",
|
||||
"website": "",
|
||||
"location": "",
|
||||
"visibility": "public",
|
||||
"repo_admin_change_team_access": true,
|
||||
"username": "---"
|
||||
}
|
30
test_data/example_team.json
Normal file
30
test_data/example_team.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
53930
test_data/org_list.json
Normal file
53930
test_data/org_list.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue