summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyborus <cyborus@noreply.codeberg.org>2024-03-20 19:09:31 +0100
committerCyborus <cyborus@noreply.codeberg.org>2024-03-20 19:09:31 +0100
commit96b92daf235985c17f19af0f0f19c20055d78f09 (patch)
tree445b0f8a7db46cfd09080084aab0d9d17dc40b38
parentMerge pull request 'add missing `parent` field to `Repository`' (#36) from pa... (diff)
parentcorrect tag creation success status code to `201` (diff)
downloadforgejo-api-96b92daf235985c17f19af0f0f19c20055d78f09.tar.xz
forgejo-api-96b92daf235985c17f19af0f0f19c20055d78f09.zip
Merge pull request 'Auto-generate API' (#38) from autogen into main
Reviewed-on: https://codeberg.org/Cyborus/forgejo-api/pulls/38
-rw-r--r--Cargo.lock61
-rw-r--r--Cargo.toml1
-rw-r--r--generator/Cargo.toml13
-rw-r--r--generator/src/main.rs287
-rw-r--r--generator/src/methods.rs612
-rw-r--r--generator/src/openapi.rs1447
-rw-r--r--generator/src/structs.rs654
-rw-r--r--src/admin.rs502
-rw-r--r--src/generated/methods.rs7226
-rw-r--r--src/generated/mod.rs2
-rw-r--r--src/generated/structs.rs5959
-rw-r--r--src/issue.rs347
-rw-r--r--src/lib.rs257
-rw-r--r--src/misc.rs162
-rw-r--r--src/notification.rs273
-rw-r--r--src/organization.rs30
-rw-r--r--src/package.rs174
-rw-r--r--src/repository.rs743
-rw-r--r--src/user.rs59
-rw-r--r--swagger.v1.json24321
-rw-r--r--tests/ci_test.rs501
21 files changed, 40899 insertions, 2732 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7360368..ea64452 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -136,9 +136,9 @@ dependencies = [
[[package]]
name = "eyre"
-version = "0.6.9"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd"
+checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
dependencies = [
"indenter",
"once_cell",
@@ -191,9 +191,9 @@ dependencies = [
[[package]]
name = "form_urlencoded"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
@@ -238,6 +238,17 @@ dependencies = [
]
[[package]]
+name = "generator"
+version = "0.1.0"
+dependencies = [
+ "eyre",
+ "heck",
+ "serde",
+ "serde_json",
+ "url",
+]
+
+[[package]]
name = "gimli"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -269,6 +280,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
+name = "heck"
+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"
@@ -341,9 +358,9 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -531,9 +548,9 @@ dependencies = [
[[package]]
name = "percent-encoding"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
@@ -561,18 +578,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
-version = "1.0.69"
+version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
+checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.33"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -684,18 +701,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.192"
+version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
+checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.192"
+version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
+checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
@@ -704,9 +721,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.108"
+version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
@@ -762,9 +779,9 @@ checksum = "b5097ec7ea7218135541ad96348f1441d0c616537dd4ed9c47205920c35d7d97"
[[package]]
name = "syn"
-version = "2.0.39"
+version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
@@ -983,9 +1000,9 @@ dependencies = [
[[package]]
name = "url"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
diff --git a/Cargo.toml b/Cargo.toml
index c53d74d..7590571 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,4 @@
+workspace = { members = ["generator"] }
[package]
name = "forgejo-api"
version = "0.1.0"
diff --git a/generator/Cargo.toml b/generator/Cargo.toml
new file mode 100644
index 0000000..21821e0
--- /dev/null
+++ b/generator/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "generator"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+eyre = "0.6.11"
+heck = "0.4.1"
+serde = { version = "1.0.195", features = ["derive"] }
+serde_json = "1.0.111"
+url = { version = "2.5.0", features = ["serde"] }
diff --git a/generator/src/main.rs b/generator/src/main.rs
new file mode 100644
index 0000000..64173bf
--- /dev/null
+++ b/generator/src/main.rs
@@ -0,0 +1,287 @@
+use std::{ffi::OsString, path::PathBuf};
+
+mod methods;
+mod openapi;
+mod structs;
+
+use heck::{ToPascalCase, ToSnakeCase};
+use openapi::*;
+
+fn main() -> eyre::Result<()> {
+ let spec = get_spec()?;
+ let files = [
+ ("mod.rs".into(), "pub mod structs;\npub mod methods;".into()),
+ ("methods.rs".into(), methods::create_methods(&spec)?),
+ ("structs.rs".into(), structs::create_structs(&spec)?),
+ ];
+ save_generated(&files)?;
+ Ok(())
+}
+
+fn get_spec() -> eyre::Result<OpenApiV2> {
+ let path = std::env::var_os("FORGEJO_API_SPEC_PATH")
+ .unwrap_or_else(|| OsString::from("./swagger.v1.json"));
+ let file = std::fs::read(path)?;
+ let spec = serde_json::from_slice::<OpenApiV2>(&file)?;
+ spec.validate()?;
+ Ok(spec)
+}
+
+fn save_generated(files: &[(String, String)]) -> eyre::Result<()> {
+ let root_path = PathBuf::from(
+ std::env::var_os("FORGEJO_API_GENERATED_PATH")
+ .unwrap_or_else(|| OsString::from("./src/generated/")),
+ );
+ for (path, file) in files {
+ let path = root_path.join(path);
+ std::fs::create_dir_all(path.parent().ok_or_else(|| eyre::eyre!("no parent dir"))?)?;
+ std::fs::write(&path, file)?;
+ run_rustfmt_on(&path);
+ }
+ Ok(())
+}
+
+fn run_rustfmt_on(path: &std::path::Path) {
+ let mut rustfmt = std::process::Command::new("rustfmt");
+
+ rustfmt.arg(path);
+ rustfmt.args(["--edition", "2021"]);
+
+ if let Err(e) = rustfmt.status() {
+ println!("Tried to format {path:?}, but failed to do so! :(");
+ println!("Error:\n{e}");
+ }
+}
+
+fn schema_ref_type_name(spec: &OpenApiV2, schema: &MaybeRef<Schema>) -> eyre::Result<String> {
+ let name = if let MaybeRef::Ref { _ref } = schema {
+ _ref.rsplit_once("/").map(|(_, b)| b)
+ } else {
+ None
+ };
+ let schema = schema.deref(spec)?;
+ schema_type_name(spec, name, schema)
+}
+
+fn schema_type_name(
+ spec: &OpenApiV2,
+ definition_name: Option<&str>,
+ schema: &Schema,
+) -> eyre::Result<String> {
+ if let Some(ty) = &schema._type {
+ match ty {
+ SchemaType::One(prim) => {
+ let name = match prim {
+ Primitive::String => match schema.format.as_deref() {
+ Some("date") => "time::Date",
+ Some("date-time") => "time::OffsetDateTime",
+ _ => "String",
+ }
+ .to_string(),
+ Primitive::Number => match schema.format.as_deref() {
+ Some("float") => "f32",
+ Some("double") => "f64",
+ _ => "f64",
+ }
+ .to_string(),
+ Primitive::Integer => match schema.format.as_deref() {
+ Some("int32") => "u32",
+ Some("int64") => "u64",
+ _ => "u32",
+ }
+ .to_string(),
+ Primitive::Boolean => "bool".to_string(),
+ Primitive::Array => {
+ let item_name = match &schema.items {
+ Some(item_schema) => schema_ref_type_name(spec, item_schema)?,
+ None => "serde_json::Value".into(),
+ };
+ format!("Vec<{item_name}>")
+ }
+ Primitive::Null => "()".to_string(),
+ Primitive::Object => {
+ match (&schema.title, definition_name) {
+ // Some of the titles are actually descriptions; not sure why
+ // Checking for a space filters that out
+ (Some(title), _) if !title.contains(' ') => title.to_string(),
+ (_, Some(definition_name)) => definition_name.to_string(),
+ (_, None) => "BTreeMap<String, serde_json::Value>".to_string(),
+ }
+ }
+ };
+ Ok(name.to_owned())
+ }
+ SchemaType::List(_) => todo!(),
+ }
+ } else {
+ Ok("serde_json::Value".into())
+ }
+}
+
+fn schema_is_string(spec: &OpenApiV2, schema: &MaybeRef<Schema>) -> eyre::Result<bool> {
+ let schema = schema.deref(spec)?;
+ let is_str = match schema._type {
+ Some(SchemaType::One(Primitive::String)) => true,
+ _ => false,
+ };
+ Ok(is_str)
+}
+
+fn sanitize_ident(s: &str) -> String {
+ let mut s = s.to_snake_case();
+ let keywords = [
+ "as",
+ "break",
+ "const",
+ "continue",
+ "crate",
+ "else",
+ "enum",
+ "extern",
+ "false",
+ "fn",
+ "for",
+ "if",
+ "impl",
+ "in",
+ "let",
+ "loop",
+ "match",
+ "mod",
+ "move",
+ "mut",
+ "pub",
+ "ref",
+ "return",
+ "self",
+ "Self",
+ "static",
+ "struct",
+ "super",
+ "trait",
+ "true",
+ "type",
+ "unsafe",
+ "use",
+ "where",
+ "while",
+ "abstract",
+ "become",
+ "box",
+ "do",
+ "final",
+ "macro",
+ "override",
+ "priv",
+ "typeof",
+ "unsized",
+ "virtual",
+ "yield",
+ "async",
+ "await",
+ "dyn",
+ "try",
+ "macro_rules",
+ "union",
+ ];
+ if s == "self" {
+ s = "this".into();
+ }
+ if keywords.contains(&&*s) {
+ s.insert_str(0, "r#");
+ }
+ s
+}
+
+fn schema_subtype_name(
+ spec: &OpenApiV2,
+ parent_name: &str,
+ name: &str,
+ schema: &Schema,
+ ty: &mut String,
+) -> eyre::Result<bool> {
+ let b = match schema {
+ Schema {
+ _type: Some(SchemaType::One(Primitive::Object)),
+ properties: Some(_),
+ ..
+ }
+ | Schema {
+ _type: Some(SchemaType::One(Primitive::String)),
+ _enum: Some(_),
+ ..
+ } => {
+ *ty = format!("{parent_name}{}", name.to_pascal_case());
+ true
+ }
+ Schema {
+ _type: Some(SchemaType::One(Primitive::Object)),
+ properties: None,
+ additional_properties: Some(additional),
+ ..
+ } => {
+ let additional = additional.deref(spec)?;
+ let mut additional_ty = crate::schema_type_name(spec, None, additional)?;
+ schema_subtype_name(spec, parent_name, name, additional, &mut additional_ty)?;
+ *ty = format!("BTreeMap<String, {additional_ty}>");
+ true
+ }
+ Schema {
+ _type: Some(SchemaType::One(Primitive::Array)),
+ items: Some(items),
+ ..
+ } => {
+ if let MaybeRef::Value { value } = &**items {
+ if schema_subtype_name(spec, parent_name, name, value, ty)? {
+ *ty = format!("Vec<{ty}>");
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ }
+ _ => false,
+ };
+ Ok(b)
+}
+fn schema_subtypes(
+ spec: &OpenApiV2,
+ parent_name: &str,
+ name: &str,
+ schema: &Schema,
+ subtypes: &mut Vec<String>,
+) -> eyre::Result<()> {
+ match schema {
+ Schema {
+ _type: Some(SchemaType::One(Primitive::Object)),
+ properties: Some(_),
+ ..
+ } => {
+ let name = format!("{parent_name}{}", name.to_pascal_case());
+ let subtype = structs::create_struct_for_definition(spec, &name, schema)?;
+ subtypes.push(subtype);
+ }
+ Schema {
+ _type: Some(SchemaType::One(Primitive::String)),
+ _enum: Some(_enum),
+ ..
+ } => {
+ let name = format!("{parent_name}{}", name.to_pascal_case());
+ let subtype = structs::create_enum(&name, schema.description.as_deref(), _enum, false)?;
+ subtypes.push(subtype);
+ }
+ Schema {
+ _type: Some(SchemaType::One(Primitive::Array)),
+ items: Some(items),
+ ..
+ } => {
+ if let MaybeRef::Value { value } = &**items {
+ schema_subtypes(spec, parent_name, name, value, subtypes)?;
+ }
+ }
+ _ => (),
+ };
+ Ok(())
+}
diff --git a/generator/src/methods.rs b/generator/src/methods.rs
new file mode 100644
index 0000000..6877437
--- /dev/null
+++ b/generator/src/methods.rs
@@ -0,0 +1,612 @@
+use crate::{openapi::*, schema_ref_type_name};
+use eyre::WrapErr;
+use heck::{ToPascalCase, ToSnakeCase};
+use std::fmt::Write;
+
+pub fn create_methods(spec: &OpenApiV2) -> eyre::Result<String> {
+ let mut s = String::new();
+ s.push_str("use crate::ForgejoError;\n");
+ s.push_str("use std::collections::BTreeMap;");
+ s.push_str("use super::structs::*;\n");
+ s.push_str("\n");
+ s.push_str("impl crate::Forgejo {\n");
+ for (path, item) in &spec.paths {
+ s.push_str(&create_methods_for_path(&spec, path, item).wrap_err_with(|| path.clone())?);
+ }
+ s.push_str("}\n");
+ Ok(s)
+}
+
+fn create_methods_for_path(spec: &OpenApiV2, path: &str, item: &PathItem) -> eyre::Result<String> {
+ let mut s = String::new();
+ if let Some(op) = &item.get {
+ s.push_str(&create_get_method(spec, path, op).wrap_err("GET")?);
+ }
+ if let Some(op) = &item.put {
+ s.push_str(&create_put_method(spec, path, op).wrap_err("PUT")?);
+ }
+ if let Some(op) = &item.post {
+ s.push_str(&create_post_method(spec, path, op).wrap_err("POST")?);
+ }
+ if let Some(op) = &item.delete {
+ s.push_str(&create_delete_method(spec, path, op).wrap_err("DELETE")?);
+ }
+ if let Some(op) = &item.options {
+ s.push_str(&create_options_method(spec, path, op).wrap_err("OPTIONS")?);
+ }
+ if let Some(op) = &item.head {
+ s.push_str(&create_head_method(spec, path, op).wrap_err("HEAD")?);
+ }
+ if let Some(op) = &item.patch {
+ s.push_str(&create_patch_method(spec, path, op).wrap_err("PATCH")?);
+ }
+ Ok(s)
+}
+
+fn create_get_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "get", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_put_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "put", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_post_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "post", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_delete_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "delete", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_options_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "options", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_head_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "head", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn create_patch_method(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Result<String> {
+ let doc = method_docs(spec, op)?;
+ let sig = fn_signature_from_op(spec, op)?;
+ let body = create_method_body(spec, "patch", path, op)?;
+ Ok(format!("{doc}{sig} {{\n {body}\n}}\n\n"))
+}
+
+fn method_docs(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let mut out = String::new();
+ let mut prev = false;
+ if let Some(summary) = &op.summary {
+ write!(&mut out, "/// {summary}\n")?;
+ prev = true;
+ }
+ if let Some(params) = &op.parameters {
+ if prev {
+ out.push_str("///\n");
+ }
+ for param in params {
+ let param = param.deref(spec)?;
+ match &param._in {
+ ParameterIn::Path { param: _ } | ParameterIn::FormData { param: _ } => {
+ write!(&mut out, "/// - `{}`", param.name)?;
+ if let Some(description) = &param.description {
+ write!(&mut out, ": {}", description)?;
+ }
+ writeln!(&mut out)?;
+ }
+ ParameterIn::Body { schema } => {
+ write!(&mut out, "/// - `{}`", param.name)?;
+ let ty = schema_ref_type_name(spec, &schema)?;
+ if let Some(description) = &param.description {
+ write!(&mut out, ": {}\n\n/// See [`{}`]", description, ty)?;
+ } else {
+ write!(&mut out, ": See [`{}`]", ty)?;
+ }
+ writeln!(&mut out)?;
+ }
+ _ => (),
+ }
+ }
+ }
+ if out.ends_with("/// \n") {
+ out.truncate(out.len() - 5);
+ }
+ Ok(out)
+}
+
+fn fn_signature_from_op(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let name = op
+ .operation_id
+ .as_deref()
+ .ok_or_else(|| eyre::eyre!("operation did not have id"))?
+ .to_snake_case()
+ .replace("o_auth2", "oauth2");
+ let args = fn_args_from_op(spec, op)?;
+ let ty = fn_return_from_op(spec, op)?;
+ Ok(format!(
+ "pub async fn {name}({args}) -> Result<{ty}, ForgejoError>"
+ ))
+}
+
+fn fn_args_from_op(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let mut args = "&self".to_string();
+ let mut has_query = false;
+ // let mut has_headers = false;
+ if let Some(params) = &op.parameters {
+ for param in params {
+ let full_param = param.deref(spec)?;
+ match &full_param._in {
+ ParameterIn::Path { param } => {
+ let type_name = param_type(&param, false)?;
+ args.push_str(", ");
+ args.push_str(&crate::sanitize_ident(&full_param.name));
+ args.push_str(": ");
+ args.push_str(&type_name);
+ }
+ ParameterIn::Query { param: _ } => has_query = true,
+ ParameterIn::Header { param: _ } => (), // has_headers = true,
+ ParameterIn::Body { schema } => {
+ let ty = crate::schema_ref_type_name(spec, schema)?;
+ args.push_str(", ");
+ args.push_str(&crate::sanitize_ident(&full_param.name));
+ args.push_str(": ");
+ args.push_str(&ty);
+ }
+ ParameterIn::FormData { param: _ } => {
+ args.push_str(", ");
+ args.push_str(&crate::sanitize_ident(&full_param.name));
+ args.push_str(": Vec<u8>");
+ }
+ }
+ }
+ }
+ if has_query {
+ let query_ty = crate::structs::query_struct_name(op)?;
+ args.push_str(", query: ");
+ args.push_str(&query_ty);
+ }
+ Ok(args)
+}
+
+pub fn param_type(param: &NonBodyParameter, owned: bool) -> eyre::Result<String> {
+ param_type_inner(
+ &param._type,
+ param.format.as_deref(),
+ param.items.as_ref(),
+ owned,
+ )
+}
+
+pub fn param_type_inner(
+ ty: &ParameterType,
+ format: Option<&str>,
+ items: Option<&Items>,
+ owned: bool,
+) -> eyre::Result<String> {
+ let ty_name = match ty {
+ ParameterType::String => match format.as_deref() {
+ Some("date") => "time::Date",
+ Some("date-time") => "time::OffsetDateTime",
+ _ => {
+ if owned {
+ "String"
+ } else {
+ "&str"
+ }
+ }
+ }
+ .into(),
+ ParameterType::Number => match format.as_deref() {
+ Some("float") => "f32",
+ Some("double") => "f64",
+ _ => "f64",
+ }
+ .into(),
+ ParameterType::Integer => match format.as_deref() {
+ Some("int32") => "u32",
+ Some("int64") => "u64",
+ _ => "u32",
+ }
+ .into(),
+ ParameterType::Boolean => "bool".into(),
+ ParameterType::Array => {
+ let item = items
+ .as_ref()
+ .ok_or_else(|| eyre::eyre!("array must have item type defined"))?;
+ let item_ty_name = param_type_inner(
+ &item._type,
+ item.format.as_deref(),
+ item.items.as_deref(),
+ owned,
+ )?;
+ if owned {
+ format!("Vec<{item_ty_name}>")
+ } else {
+ format!("&[{item_ty_name}]")
+ }
+ }
+ ParameterType::File => {
+ if owned {
+ format!("Vec<u8>")
+ } else {
+ format!("&[u8]")
+ }
+ }
+ };
+ Ok(ty_name)
+}
+
+fn fn_return_from_op(spec: &OpenApiV2, op: &Operation) -> eyre::Result<ResponseType> {
+ let responses = op
+ .responses
+ .http_codes
+ .iter()
+ .filter(|(k, _)| k.starts_with("2"))
+ .map(|(_, v)| response_ref_type_name(spec, v, op))
+ .collect::<Result<Vec<_>, _>>()?;
+ let mut iter = responses.into_iter();
+ let mut response = iter
+ .next()
+ .ok_or_else(|| eyre::eyre!("must have at least one response type"))?;
+ for next in iter {
+ response = response.merge(next)?;
+ }
+
+ Ok(response)
+}
+
+fn response_ref_type_name(
+ spec: &OpenApiV2,
+ response_ref: &MaybeRef<Response>,
+ op: &Operation,
+) -> eyre::Result<ResponseType> {
+ let response = response_ref.deref(spec)?;
+ let mut ty = ResponseType::default();
+ if response.headers.is_some() {
+ let parent_name = match &response_ref {
+ MaybeRef::Ref { _ref } => _ref
+ .rsplit_once("/")
+ .ok_or_else(|| eyre::eyre!("invalid ref"))?
+ .1
+ .to_string(),
+ MaybeRef::Value { value: _ } => {
+ eyre::bail!("could not find parent name for header type")
+ }
+ };
+ ty.headers = Some(format!("{}Headers", parent_name));
+ }
+ let produces = op
+ .produces
+ .as_deref()
+ .or_else(|| spec.produces.as_deref())
+ .unwrap_or_default();
+ // can't use .contains() because Strings
+ let produces_json = produces.iter().any(|i| matches!(&**i, "application/json"));
+ let produces_text = produces.iter().any(|i| i.starts_with("text/"));
+ let produces_other = produces
+ .iter()
+ .any(|i| !matches!(&**i, "application/json") && !i.starts_with("text/"));
+ match (produces_json, produces_text, produces_other) {
+ (true, false, false) => {
+ if let Some(schema) = &response.schema {
+ ty.kind = Some(ResponseKind::Json);
+ let mut body = crate::schema_ref_type_name(spec, schema)?;
+ if let MaybeRef::Value { value } = schema {
+ let op_name = op.operation_id.as_deref().ok_or_else(|| eyre::eyre!("no operation id"))?.to_pascal_case();
+ crate::schema_subtype_name(spec, &op_name, "Response", value, &mut body)?;
+ }
+ ty.body = Some(body);
+ };
+ }
+ (false, _, true) => {
+ ty.kind = Some(ResponseKind::Bytes);
+ ty.body = Some("Vec<u8>".into());
+ }
+ (false, true, false) => {
+ ty.kind = Some(ResponseKind::Text);
+ ty.body = Some("String".into());
+ }
+ (false, false, false) => {
+ ty.kind = None;
+ ty.body = None;
+ }
+ _ => eyre::bail!("produces value unsupported. json: {produces_json}, text: {produces_text}, other: {produces_other}"),
+ };
+ Ok(ty)
+}
+
+fn create_method_body(
+ spec: &OpenApiV2,
+ method: &str,
+ path: &str,
+ op: &Operation,
+) -> eyre::Result<String> {
+ let request = create_method_request(spec, method, path, op)?;
+ let response = create_method_response(spec, op)?;
+ Ok(format!("{request}\n {response}"))
+}
+
+fn create_method_request(
+ spec: &OpenApiV2,
+ method: &str,
+ path: &str,
+ op: &Operation,
+) -> eyre::Result<String> {
+ let mut has_query = false;
+ // let mut has_headers = false;
+ let mut body_method = String::new();
+ if let Some(params) = &op.parameters {
+ for param in params {
+ let param = param.deref(spec)?;
+ let name = crate::sanitize_ident(&param.name);
+ match &param._in {
+ ParameterIn::Path { param: _ } => (/* do nothing */),
+ ParameterIn::Query { param: _ } => has_query = true,
+ ParameterIn::Header { param: _ } => (), // _has_headers = true,
+ ParameterIn::Body { schema: _ } => {
+ if !body_method.is_empty() {
+ eyre::bail!("cannot have more than one body parameter");
+ }
+ if param_is_string(spec, param)? {
+ body_method = format!(".body({name})");
+ } else {
+ body_method = format!(".json(&{name})");
+ }
+ }
+ ParameterIn::FormData { param: _ } => {
+ if !body_method.is_empty() {
+ eyre::bail!("cannot have more than one body parameter");
+ }
+ body_method = format!(".multipart(reqwest::multipart::Form::new().part(\"attachment\", reqwest::multipart::Part::bytes({name}).file_name(\"file\").mime_str(\"*/*\").unwrap()))");
+ }
+ }
+ }
+ }
+ let mut fmt_str = sanitize_path_arg(path)?;
+ if has_query {
+ fmt_str.push_str("?{query}");
+ }
+ let path_arg = if fmt_str.contains("{") {
+ format!("&format!(\"{fmt_str}\")")
+ } else {
+ format!("\"{fmt_str}\"")
+ };
+
+ let out = format!("let request = self.{method}({path_arg}){body_method}.build()?;");
+ Ok(out)
+}
+
+fn param_is_string(spec: &OpenApiV2, param: &Parameter) -> eyre::Result<bool> {
+ match &param._in {
+ ParameterIn::Body { schema } => crate::schema_is_string(spec, schema),
+ ParameterIn::Path { param }
+ | ParameterIn::Query { param }
+ | ParameterIn::Header { param }
+ | ParameterIn::FormData { param } => {
+ let is_str = match param._type {
+ ParameterType::String => true,
+ _ => false,
+ };
+ Ok(is_str)
+ }
+ }
+}
+
+fn sanitize_path_arg(mut path: &str) -> eyre::Result<String> {
+ let mut out = String::new();
+ loop {
+ let (head, tail) = match path.split_once("{") {
+ Some(i) => i,
+ None => {
+ out.push_str(path);
+ break;
+ }
+ };
+ path = tail;
+ out.push_str(head);
+ out.push('{');
+ let (head, tail) = match path.split_once("}") {
+ Some(i) => i,
+ None => {
+ eyre::bail!("unmatched bracket");
+ }
+ };
+ path = tail;
+ out.push_str(&head.to_snake_case());
+ out.push('}');
+ }
+ if out.starts_with("/") {
+ out.remove(0);
+ }
+ Ok(out)
+}
+
+fn create_method_response(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let mut has_empty = false;
+ let mut only_empty = true;
+ for (code, res) in &op.responses.http_codes {
+ let response = response_ref_type_name(spec, res, op)?;
+ if !code.starts_with("2") {
+ continue;
+ }
+ if matches!(response.body.as_deref(), Some("()") | None) {
+ has_empty = true;
+ } else {
+ only_empty = false;
+ }
+ }
+ let fn_ret = fn_return_from_op(spec, op)?;
+ let optional = has_empty && !only_empty;
+ let mut out = String::new();
+ out.push_str("let response = self.execute(request).await?;\n");
+ out.push_str("match response.status().as_u16() {\n");
+ for (code, res) in &op.responses.http_codes {
+ let res = res.deref(spec)?;
+ if !code.starts_with("2") {
+ continue;
+ }
+ out.push_str(code);
+ out.push_str(" => Ok(");
+ let mut handlers = Vec::new();
+ let header_handler = match &res.headers {
+ Some(_) => {
+ if fn_ret
+ .headers
+ .as_ref()
+ .map(|s| s.starts_with("Option<"))
+ .unwrap()
+ {
+ Some("Some(response.headers().try_into()?)")
+ } else {
+ Some("response.headers().try_into()?")
+ }
+ }
+ None => {
+ if fn_ret.headers.is_some() {
+ Some("None")
+ } else {
+ None
+ }
+ }
+ };
+ handlers.extend(header_handler);
+ let body_handler = match fn_ret.kind {
+ Some(ResponseKind::Text) => {
+ if optional {
+ Some("Some(response.text().await?)")
+ } else {
+ Some("response.text().await?")
+ }
+ }
+ Some(ResponseKind::Json) => {
+ if optional {
+ Some("Some(response.json().await?)")
+ } else {
+ Some("response.json().await?")
+ }
+ }
+ Some(ResponseKind::Bytes) => {
+ if optional {
+ Some("Some(response.bytes().await?[..].to_vec())")
+ } else {
+ Some("response.bytes().await?[..].to_vec()")
+ }
+ }
+ None => {
+ if optional {
+ Some("None")
+ } else {
+ None
+ }
+ }
+ };
+ handlers.extend(body_handler);
+ match handlers[..] {
+ [single] => out.push_str(single),
+ _ => {
+ out.push('(');
+ for (i, item) in handlers.iter().copied().enumerate() {
+ out.push_str(item);
+ if i + 1 < handlers.len() {
+ out.push_str(", ");
+ }
+ }
+ out.push(')');
+ }
+ }
+ out.push_str("),\n");
+ }
+ out.push_str("_ => Err(ForgejoError::UnexpectedStatusCode(response.status()))\n");
+ out.push_str("}\n");
+
+ Ok(out)
+}
+
+#[derive(Debug, Default)]
+struct ResponseType {
+ headers: Option<String>,
+ body: Option<String>,
+ kind: Option<ResponseKind>,
+}
+
+impl ResponseType {
+ fn merge(self, other: Self) -> eyre::Result<Self> {
+ let headers = match (self.headers, other.headers) {
+ (Some(a), Some(b)) if a != b => eyre::bail!("incompatible header types in response"),
+ (Some(a), None) => Some(format!("Option<{a}>")),
+ (None, Some(b)) => Some(format!("Option<{b}>")),
+ (a, b) => a.or(b),
+ };
+ let body = match (self.body.as_deref(), other.body.as_deref()) {
+ (Some(a), Some(b)) if a != b => eyre::bail!("incompatible header types in response"),
+ (Some(a), Some("()") | None) => Some(format!("Option<{a}>")),
+ (Some("()") | None, Some(b)) => Some(format!("Option<{b}>")),
+ (_, _) => self.body.or(other.body),
+ };
+ use ResponseKind::*;
+ let kind = match (self.kind, other.kind) {
+ (a, None) => a,
+ (None, b) => b,
+ (Some(Json), Some(Json)) => Some(Json),
+ (Some(Bytes), Some(Bytes)) => Some(Bytes),
+ (Some(Bytes), Some(Text)) => Some(Bytes),
+ (Some(Text), Some(Bytes)) => Some(Bytes),
+ (Some(Text), Some(Text)) => Some(Text),
+ _ => eyre::bail!("incompatible response kinds"),
+ };
+ let new = Self {
+ headers,
+ body,
+ kind,
+ };
+ Ok(new)
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+enum ResponseKind {
+ Json,
+ Text,
+ Bytes,
+}
+
+impl std::fmt::Display for ResponseType {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut tys = Vec::new();
+ tys.extend(self.headers.as_deref());
+ tys.extend(self.body.as_deref());
+ match tys[..] {
+ [single] => f.write_str(single),
+ _ => {
+ write!(f, "(")?;
+ for (i, item) in tys.iter().copied().enumerate() {
+ f.write_str(item)?;
+ if i + 1 < tys.len() {
+ write!(f, ", ")?;
+ }
+ }
+ write!(f, ")")?;
+ Ok(())
+ }
+ }
+ }
+}
diff --git a/generator/src/openapi.rs b/generator/src/openapi.rs
new file mode 100644
index 0000000..35dd9ba
--- /dev/null
+++ b/generator/src/openapi.rs
@@ -0,0 +1,1447 @@
+use std::collections::{BTreeMap, BTreeSet};
+
+use eyre::WrapErr;
+use url::Url;
+
+trait JsonDeref: std::any::Any {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any>;
+}
+
+impl JsonDeref for bool {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl JsonDeref for u64 {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl JsonDeref for f64 {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl JsonDeref for String {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl JsonDeref for Url {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl<T: JsonDeref> JsonDeref for Option<T> {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ match self {
+ Some(x) => x.deref_any(path),
+ None => Err(eyre::eyre!("not found")),
+ }
+ }
+}
+
+impl<T: JsonDeref> JsonDeref for Box<T> {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ T::deref_any(&**self, path)
+ }
+}
+
+impl<T: JsonDeref> JsonDeref for Vec<T> {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ let idx = head.parse::<usize>().wrap_err("not found")?;
+ let value = self.get(idx).ok_or_else(|| eyre::eyre!("not found"))?;
+ value.deref_any(tail)
+ }
+}
+
+impl<T: JsonDeref> JsonDeref for BTreeMap<String, T> {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ let value = self.get(head).ok_or_else(|| eyre::eyre!("not found"))?;
+ value.deref_any(tail)
+ }
+}
+
+impl JsonDeref for serde_json::Value {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ match self {
+ serde_json::Value::Null => eyre::bail!("not found"),
+ serde_json::Value::Bool(b) => b.deref_any(path),
+ serde_json::Value::Number(x) => x.deref_any(path),
+ serde_json::Value::String(s) => s.deref_any(path),
+ serde_json::Value::Array(list) => list.deref_any(path),
+ serde_json::Value::Object(map) => map.deref_any(path),
+ }
+ }
+}
+
+impl JsonDeref for serde_json::Map<String, serde_json::Value> {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ let value = self.get(head).ok_or_else(|| eyre::eyre!("not found"))?;
+ value.deref_any(tail)
+ }
+}
+
+impl JsonDeref for serde_json::Number {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ eyre::bail!("not found")
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct OpenApiV2 {
+ pub swagger: String,
+ pub info: SpecInfo,
+ pub host: Option<String>,
+ pub base_path: Option<String>,
+ pub schemes: Option<Vec<String>>,
+ pub consumes: Option<Vec<String>>,
+ pub produces: Option<Vec<String>>,
+ pub paths: BTreeMap<String, PathItem>,
+ pub definitions: Option<BTreeMap<String, Schema>>,
+ pub parameters: Option<BTreeMap<String, Parameter>>,
+ pub responses: Option<BTreeMap<String, Response>>,
+ pub security_definitions: Option<BTreeMap<String, SecurityScheme>>,
+ pub security: Option<Vec<BTreeMap<String, Vec<String>>>>,
+ pub tags: Option<Vec<Tag>>,
+ pub external_docs: Option<ExternalDocs>,
+}
+
+impl JsonDeref for OpenApiV2 {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ let path = path
+ .strip_prefix("#/")
+ .ok_or_else(|| eyre::eyre!("invalid ref prefix"))?;
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "swagger" => self.swagger.deref_any(tail),
+ "info" => self.info.deref_any(tail),
+ "host" => self.host.deref_any(tail),
+ "base_path" => self.base_path.deref_any(tail),
+ "schemes" => self.schemes.deref_any(tail),
+ "consumes" => self.consumes.deref_any(tail),
+ "produces" => self.produces.deref_any(tail),
+ "paths" => self.paths.deref_any(tail),
+ "definitions" => self.definitions.deref_any(tail),
+ "parameters" => self.parameters.deref_any(tail),
+ "responses" => self.responses.deref_any(tail),
+ "security_definitions" => self.security_definitions.deref_any(tail),
+ "security" => self.security.deref_any(tail),
+ "tags" => self.tags.deref_any(tail),
+ "external_docs" => self.external_docs.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl OpenApiV2 {
+ pub fn validate(&self) -> eyre::Result<()> {
+ eyre::ensure!(self.swagger == "2.0", "swagger version must be 2.0");
+ if let Some(host) = &self.host {
+ eyre::ensure!(!host.contains("://"), "openapi.host cannot contain scheme");
+ eyre::ensure!(!host.contains("/"), "openapi.host cannot contain path");
+ }
+ if let Some(base_path) = &self.base_path {
+ eyre::ensure!(
+ base_path.starts_with("/"),
+ "openapi.base_path must start with a forward slash"
+ );
+ }
+ if let Some(schemes) = &self.schemes {
+ for scheme in schemes {
+ eyre::ensure!(
+ matches!(&**scheme, "http" | "https" | "ws" | "wss"),
+ "openapi.schemes must only be http, https, ws, or wss"
+ );
+ }
+ }
+ for (path, path_item) in &self.paths {
+ eyre::ensure!(
+ path.starts_with("/"),
+ "members of openapi.paths must start with a forward slash; {path} does not"
+ );
+ let mut operation_ids = BTreeSet::new();
+ path_item
+ .validate(&mut operation_ids)
+ .wrap_err_with(|| format!("OpenApiV2.paths[\"{path}\"]"))?;
+ }
+ if let Some(definitions) = &self.definitions {
+ for (name, schema) in definitions {
+ schema
+ .validate()
+ .wrap_err_with(|| format!("OpenApiV2.definitions[\"{name}\"]"))?;
+ }
+ }
+ if let Some(params) = &self.parameters {
+ for (name, param) in params {
+ param
+ .validate()
+ .wrap_err_with(|| format!("OpenApiV2.parameters[\"{name}\"]"))?;
+ }
+ }
+ if let Some(responses) = &self.responses {
+ for (name, responses) in responses {
+ responses
+ .validate()
+ .wrap_err_with(|| format!("OpenApiV2.responses[\"{name}\"]"))?;
+ }
+ }
+ Ok(())
+ }
+
+ pub fn deref<T: std::any::Any>(&self, path: &str) -> eyre::Result<&T> {
+ self.deref_any(path).and_then(|a| {
+ a.downcast_ref::<T>()
+ .ok_or_else(|| eyre::eyre!("incorrect type found at reference"))
+ })
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct SpecInfo {
+ pub title: String,
+ pub description: Option<String>,
+ pub terms_of_service: Option<String>,
+ pub contact: Option<Contact>,
+ pub license: Option<License>,
+ pub version: String,
+}
+
+impl JsonDeref for SpecInfo {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "title" => self.title.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ "terms_of_service" => self.terms_of_service.deref_any(tail),
+ "contact" => self.contact.deref_any(tail),
+ "license" => self.license.deref_any(tail),
+ "version" => self.version.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Contact {
+ pub name: Option<String>,
+ pub url: Option<String>,
+ pub email: Option<String>,
+}
+
+impl JsonDeref for Contact {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "name" => self.name.deref_any(tail),
+ "url" => self.url.deref_any(tail),
+ "email" => self.email.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct License {
+ pub name: String,
+ pub url: Option<Url>,
+}
+
+impl JsonDeref for License {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "name" => self.name.deref_any(tail),
+ "url" => self.url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct PathItem {
+ #[serde(rename = "$ref")]
+ pub _ref: Option<String>,
+ pub get: Option<Operation>,
+ pub put: Option<Operation>,
+ pub post: Option<Operation>,
+ pub delete: Option<Operation>,
+ pub options: Option<Operation>,
+ pub head: Option<Operation>,
+ pub patch: Option<Operation>,
+ pub parameters: Option<Vec<MaybeRef<Parameter>>>,
+}
+
+impl JsonDeref for PathItem {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "$ref" => self._ref.deref_any(tail),
+ "get" => self.get.deref_any(tail),
+ "put" => self.put.deref_any(tail),
+ "post" => self.post.deref_any(tail),
+ "delete" => self.delete.deref_any(tail),
+ "options" => self.options.deref_any(tail),
+ "head" => self.head.deref_any(tail),
+ "patch" => self.patch.deref_any(tail),
+ "parameters" => self.parameters.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl PathItem {
+ fn validate<'a>(&'a self, ids: &mut BTreeSet<&'a str>) -> eyre::Result<()> {
+ if let Some(op) = &self.get {
+ op.validate(ids).wrap_err("PathItem.get")?;
+ }
+ if let Some(op) = &self.put {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(op) = &self.post {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(op) = &self.delete {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(op) = &self.options {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(op) = &self.head {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(op) = &self.patch {
+ op.validate(ids).wrap_err("PathItem.patch")?;
+ }
+ if let Some(params) = &self.parameters {
+ for param in params {
+ if let MaybeRef::Value { value } = param {
+ value.validate().wrap_err("PathItem.parameters")?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Operation {
+ pub tags: Option<Vec<String>>,
+ pub summary: Option<String>,
+ pub description: Option<String>,
+ pub external_docs: Option<ExternalDocs>,
+ pub operation_id: Option<String>,
+ pub consumes: Option<Vec<String>>,
+ pub produces: Option<Vec<String>>,
+ pub parameters: Option<Vec<MaybeRef<Parameter>>>,
+ pub responses: Responses,
+ pub schemes: Option<Vec<String>>,
+ pub deprecated: Option<bool>,
+ pub security: Option<Vec<BTreeMap<String, Vec<String>>>>,
+}
+
+impl JsonDeref for Operation {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "tags" => self.tags.deref_any(tail),
+ "summary" => self.summary.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ "external_docs" => self.external_docs.deref_any(tail),
+ "operation_id" => self.operation_id.deref_any(tail),
+ "consumes" => self.consumes.deref_any(tail),
+ "produces" => self.produces.deref_any(tail),
+ "parameters" => self.parameters.deref_any(tail),
+ "responses" => self.responses.deref_any(tail),
+ "schemes" => self.schemes.deref_any(tail),
+ "deprecated" => self.deprecated.deref_any(tail),
+ "security" => self.security.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl Operation {
+ fn validate<'a>(&'a self, ids: &mut BTreeSet<&'a str>) -> eyre::Result<()> {
+ if let Some(operation_id) = self.operation_id.as_deref() {
+ let is_new = ids.insert(operation_id);
+ eyre::ensure!(is_new, "duplicate operation id");
+ }
+ if let Some(params) = &self.parameters {
+ for param in params {
+ if let MaybeRef::Value { value } = param {
+ value.validate().wrap_err("Operation.parameters")?;
+ }
+ }
+ }
+ self.responses.validate().wrap_err("operation response")?;
+ if let Some(schemes) = &self.schemes {
+ for scheme in schemes {
+ eyre::ensure!(
+ matches!(&**scheme, "http" | "https" | "ws" | "wss"),
+ "openapi.schemes must only be http, https, ws, or wss"
+ );
+ }
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct ExternalDocs {
+ pub description: Option<String>,
+ pub url: Url,
+}
+
+impl JsonDeref for ExternalDocs {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "description" => self.description.deref_any(tail),
+ "url" => self.url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Parameter {
+ pub name: String,
+ pub description: Option<String>,
+ #[serde(flatten)]
+ pub _in: ParameterIn,
+}
+
+impl JsonDeref for Parameter {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "name" => self.name.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ "in" => {
+ if tail.is_empty() {
+ Ok(match &self._in {
+ ParameterIn::Body { schema: _ } => &"body" as _,
+ ParameterIn::Path { param: _ } => &"path" as _,
+ ParameterIn::Query { param: _ } => &"query" as _,
+ ParameterIn::Header { param: _ } => &"header" as _,
+ ParameterIn::FormData { param: _ } => &"formData" as _,
+ })
+ } else {
+ eyre::bail!("not found")
+ }
+ }
+ _ => self._in.deref_any(path),
+ }
+ }
+}
+
+impl Parameter {
+ fn validate(&self) -> eyre::Result<()> {
+ self._in.validate()
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+#[serde(tag = "in")]
+pub enum ParameterIn {
+ Body {
+ schema: MaybeRef<Schema>,
+ },
+ Path {
+ #[serde(flatten)]
+ param: NonBodyParameter,
+ },
+ Query {
+ #[serde(flatten)]
+ param: NonBodyParameter,
+ },
+ Header {
+ #[serde(flatten)]
+ param: NonBodyParameter,
+ },
+ FormData {
+ #[serde(flatten)]
+ param: NonBodyParameter,
+ },
+}
+
+impl JsonDeref for ParameterIn {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match self {
+ ParameterIn::Body { schema } => match head {
+ "schema" => schema.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ ParameterIn::Path { param }
+ | ParameterIn::Query { param }
+ | ParameterIn::Header { param }
+ | ParameterIn::FormData { param } => param.deref_any(path),
+ }
+ }
+}
+
+impl ParameterIn {
+ fn validate(&self) -> eyre::Result<()> {
+ match self {
+ ParameterIn::Path { param } => {
+ eyre::ensure!(param.required, "path parameters must be required");
+ param.validate().wrap_err("path param")
+ }
+ ParameterIn::Query { param } => param.validate().wrap_err("query param"),
+ ParameterIn::Header { param } => param.validate().wrap_err("header param"),
+ ParameterIn::Body { schema } => {
+ if let MaybeRef::Value { value } = schema {
+ value.validate().wrap_err("body param")
+ } else {
+ Ok(())
+ }
+ }
+ ParameterIn::FormData { param } => param.validate().wrap_err("form param"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct NonBodyParameter {
+ #[serde(default)]
+ pub required: bool,
+ #[serde(rename = "type")]
+ pub _type: ParameterType,
+ pub format: Option<String>,
+ pub allow_empty_value: Option<bool>,
+ pub items: Option<Items>,
+ pub collection_format: Option<CollectionFormat>,
+ pub default: Option<serde_json::Value>,
+ pub maximum: Option<f64>,
+ pub exclusive_maximum: Option<bool>,
+ pub minimum: Option<f64>,
+ pub exclusive_minimum: Option<bool>,
+ pub max_length: Option<u64>,
+ pub min_length: Option<u64>,
+ pub pattern: Option<String>, // should be regex
+ pub max_items: Option<u64>,
+ pub min_items: Option<u64>,
+ pub unique_items: Option<bool>,
+ #[serde(rename = "enum")]
+ pub _enum: Option<Vec<serde_json::Value>>,
+ pub multiple_of: Option<u64>,
+}
+
+impl JsonDeref for NonBodyParameter {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "required" => self.required.deref_any(tail),
+ "type" => self._type.deref_any(tail),
+ "format" => self.format.deref_any(tail),
+ "allow_empty_value" => self.allow_empty_value.deref_any(tail),
+ "items" => self.items.deref_any(tail),
+ "collection_format" => self.collection_format.deref_any(tail),
+ "default" => self.default.deref_any(tail),
+ "maximum" => self.maximum.deref_any(tail),
+ "exclusive_maximum" => self.exclusive_maximum.deref_any(tail),
+ "minimum" => self.minimum.deref_any(tail),
+ "exclusive_minimum" => self.exclusive_minimum.deref_any(tail),
+ "max_length" => self.max_length.deref_any(tail),
+ "min_length" => self.min_length.deref_any(tail),
+ "pattern" => self.pattern.deref_any(tail), // should be regex
+ "max_items" => self.max_items.deref_any(tail),
+ "min_items" => self.min_items.deref_any(tail),
+ "unique_items" => self.unique_items.deref_any(tail),
+ "enum" => self._enum.deref_any(tail),
+ "multiple_of" => self.multiple_of.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl NonBodyParameter {
+ fn validate(&self) -> eyre::Result<()> {
+ if self._type == ParameterType::Array {
+ eyre::ensure!(
+ self.items.is_some(),
+ "array paramters must define their item types"
+ );
+ }
+ if let Some(items) = &self.items {
+ items.validate()?;
+ }
+ if let Some(default) = &self.default {
+ eyre::ensure!(
+ self._type.matches_value(default),
+ "param's default must match its type"
+ );
+ }
+ if let Some(_enum) = &self._enum {
+ for variant in _enum {
+ eyre::ensure!(
+ self._type.matches_value(variant),
+ "header enum variant must match its type"
+ );
+ }
+ }
+ if self.exclusive_maximum.is_some() {
+ eyre::ensure!(
+ self.maximum.is_some(),
+ "presence of `exclusiveMaximum` requires `maximum` be there too"
+ );
+ }
+ if self.exclusive_minimum.is_some() {
+ eyre::ensure!(
+ self.minimum.is_some(),
+ "presence of `exclusiveMinimum` requires `minimum` be there too"
+ );
+ }
+ if let Some(multiple_of) = self.multiple_of {
+ eyre::ensure!(multiple_of > 0, "multipleOf must be greater than 0");
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub enum ParameterType {
+ String,
+ Number,
+ Integer,
+ Boolean,
+ Array,
+ File,
+}
+
+impl JsonDeref for ParameterType {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl ParameterType {
+ fn matches_value(&self, value: &serde_json::Value) -> bool {
+ match (self, value) {
+ (ParameterType::String, serde_json::Value::String(_))
+ | (ParameterType::Number, serde_json::Value::Number(_))
+ | (ParameterType::Integer, serde_json::Value::Number(_))
+ | (ParameterType::Boolean, serde_json::Value::Bool(_))
+ | (ParameterType::Array, serde_json::Value::Array(_)) => true,
+ _ => false,
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq, Clone, Copy)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub enum CollectionFormat {
+ Csv,
+ Ssv,
+ Tsv,
+ Pipes,
+ Multi,
+}
+
+impl JsonDeref for CollectionFormat {
+ fn deref_any<'a>(&'a self, path: &str) -> eyre::Result<&'a dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Items {
+ #[serde(rename = "type")]
+ pub _type: ParameterType,
+ pub format: Option<String>,
+ pub items: Option<Box<Items>>,
+ pub collection_format: Option<CollectionFormat>,
+ pub default: Option<serde_json::Value>,
+ pub maximum: Option<f64>,
+ pub exclusive_maximum: Option<bool>,
+ pub minimum: Option<f64>,
+ pub exclusive_minimum: Option<bool>,
+ pub max_length: Option<u64>,
+ pub min_length: Option<u64>,
+ pub pattern: Option<String>, // should be regex
+ pub max_items: Option<u64>,
+ pub min_items: Option<u64>,
+ pub unique_items: Option<bool>,
+ #[serde(rename = "enum")]
+ pub _enum: Option<Vec<serde_json::Value>>,
+ pub multiple_of: Option<u64>,
+}
+
+impl JsonDeref for Items {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "type" => self._type.deref_any(tail),
+ "format" => self.format.deref_any(tail),
+ "items" => self.items.deref_any(tail),
+ "collection_format" => self.collection_format.deref_any(tail),
+ "default" => self.default.deref_any(tail),
+ "maximum" => self.maximum.deref_any(tail),
+ "exclusive_maximum" => self.exclusive_maximum.deref_any(tail),
+ "minimum" => self.minimum.deref_any(tail),
+ "exclusive_minimum" => self.exclusive_minimum.deref_any(tail),
+ "max_length" => self.max_length.deref_any(tail),
+ "min_length" => self.min_length.deref_any(tail),
+ "pattern" => self.pattern.deref_any(tail), // should be regex
+ "max_items" => self.max_items.deref_any(tail),
+ "min_items" => self.min_items.deref_any(tail),
+ "unique_items" => self.unique_items.deref_any(tail),
+ "enum" => self._enum.deref_any(tail),
+ "multiple_of" => self.multiple_of.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl Items {
+ fn validate(&self) -> eyre::Result<()> {
+ if self._type == ParameterType::Array {
+ eyre::ensure!(
+ self.items.is_some(),
+ "array paramters must define their item types"
+ );
+ }
+ if let Some(items) = &self.items {
+ items.validate()?;
+ }
+ if let Some(default) = &self.default {
+ match (&self._type, default) {
+ (ParameterType::String, serde_json::Value::String(_))
+ | (ParameterType::Number, serde_json::Value::Number(_))
+ | (ParameterType::Integer, serde_json::Value::Number(_))
+ | (ParameterType::Boolean, serde_json::Value::Bool(_))
+ | (ParameterType::Array, serde_json::Value::Array(_)) => (),
+ (ParameterType::File, _) => eyre::bail!("file params cannot have default value"),
+ _ => eyre::bail!("param's default must match its type"),
+ };
+ }
+ if let Some(_enum) = &self._enum {
+ for variant in _enum {
+ eyre::ensure!(
+ self._type.matches_value(variant),
+ "header enum variant must match its type"
+ );
+ }
+ }
+ if self.exclusive_maximum.is_some() {
+ eyre::ensure!(
+ self.maximum.is_some(),
+ "presence of `exclusiveMaximum` requires `maximum` be there too"
+ );
+ }
+ if self.exclusive_minimum.is_some() {
+ eyre::ensure!(
+ self.minimum.is_some(),
+ "presence of `exclusiveMinimum` requires `minimum` be there too"
+ );
+ }
+ if let Some(multiple_of) = self.multiple_of {
+ eyre::ensure!(multiple_of > 0, "multipleOf must be greater than 0");
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Responses {
+ pub default: Option<MaybeRef<Response>>,
+ #[serde(flatten)]
+ pub http_codes: BTreeMap<String, MaybeRef<Response>>,
+}
+
+impl JsonDeref for Responses {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "default" => self.default.deref_any(tail),
+ code => self
+ .http_codes
+ .get(code)
+ .map(|r| r as _)
+ .ok_or_else(|| eyre::eyre!("not found")),
+ }
+ }
+}
+
+impl Responses {
+ fn validate(&self) -> eyre::Result<()> {
+ if self.default.is_none() && self.http_codes.is_empty() {
+ eyre::bail!("must have at least one response");
+ }
+ if let Some(MaybeRef::Value { value }) = &self.default {
+ value.validate().wrap_err("default response")?;
+ }
+ for (code, response) in &self.http_codes {
+ let code_int = code.parse::<u16>().wrap_err("http code must be a number")?;
+ eyre::ensure!(
+ code_int >= 100 && code_int < 1000,
+ "invalid http status code"
+ );
+ if let MaybeRef::Value { value } = response {
+ value.validate().wrap_err_with(|| code.to_string())?;
+ }
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Response {
+ pub description: String,
+ pub schema: Option<MaybeRef<Schema>>,
+ pub headers: Option<BTreeMap<String, Header>>,
+ pub examples: Option<BTreeMap<String, serde_json::Value>>,
+}
+
+impl JsonDeref for Response {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "description" => self.description.deref_any(tail),
+ "schema" => self.schema.deref_any(tail),
+ "headers" => self.headers.deref_any(tail),
+ "examples" => self.examples.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl Response {
+ fn validate(&self) -> eyre::Result<()> {
+ if let Some(headers) = &self.headers {
+ for (_, value) in headers {
+ value.validate().wrap_err("response header")?;
+ }
+ }
+ if let Some(MaybeRef::Value { value }) = &self.schema {
+ value.validate().wrap_err("response")?;
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Header {
+ pub description: Option<String>,
+ #[serde(rename = "type")]
+ pub _type: ParameterType,
+ pub format: Option<String>,
+ pub items: Option<Items>,
+ pub collection_format: Option<CollectionFormat>,
+ pub default: Option<serde_json::Value>,
+ pub maximum: Option<f64>,
+ pub exclusive_maximum: Option<bool>,
+ pub minimum: Option<f64>,
+ pub exclusive_minimum: Option<bool>,
+ pub max_length: Option<u64>,
+ pub min_length: Option<u64>,
+ pub pattern: Option<String>, // should be regex
+ pub max_items: Option<u64>,
+ pub min_items: Option<u64>,
+ pub unique_items: Option<bool>,
+ #[serde(rename = "enum")]
+ pub _enum: Option<Vec<serde_json::Value>>,
+ pub multiple_of: Option<u64>,
+}
+
+impl JsonDeref for Header {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "description" => self.description.deref_any(tail),
+ "type" => self._type.deref_any(tail),
+ "format" => self.format.deref_any(tail),
+ "items" => self.items.deref_any(tail),
+ "collection_format" => self.collection_format.deref_any(tail),
+ "default" => self.default.deref_any(tail),
+ "maximum" => self.maximum.deref_any(tail),
+ "exclusive_maximum" => self.exclusive_maximum.deref_any(tail),
+ "minimum" => self.minimum.deref_any(tail),
+ "exclusive_minimum" => self.exclusive_minimum.deref_any(tail),
+ "max_length" => self.max_length.deref_any(tail),
+ "min_length" => self.min_length.deref_any(tail),
+ "pattern" => self.pattern.deref_any(tail), // should be regex
+ "max_items" => self.max_items.deref_any(tail),
+ "min_items" => self.min_items.deref_any(tail),
+ "unique_items" => self.unique_items.deref_any(tail),
+ "enum" => self._enum.deref_any(tail),
+ "multiple_of" => self.multiple_of.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl Header {
+ fn validate(&self) -> eyre::Result<()> {
+ if self._type == ParameterType::Array {
+ eyre::ensure!(
+ self.items.is_some(),
+ "array paramters must define their item types"
+ );
+ }
+ if let Some(default) = &self.default {
+ match (&self._type, default) {
+ (ParameterType::String, serde_json::Value::String(_))
+ | (ParameterType::Number, serde_json::Value::Number(_))
+ | (ParameterType::Integer, serde_json::Value::Number(_))
+ | (ParameterType::Boolean, serde_json::Value::Bool(_))
+ | (ParameterType::Array, serde_json::Value::Array(_)) => (),
+ (ParameterType::File, _) => eyre::bail!("file params cannot have default value"),
+ _ => eyre::bail!("param's default must match its type"),
+ };
+ }
+ if let Some(_enum) = &self._enum {
+ for variant in _enum {
+ eyre::ensure!(
+ self._type.matches_value(variant),
+ "header enum variant must match its type"
+ );
+ }
+ }
+ if self.exclusive_maximum.is_some() {
+ eyre::ensure!(
+ self.maximum.is_some(),
+ "presence of `exclusiveMaximum` requires `maximum` be there too"
+ );
+ }
+ if self.exclusive_minimum.is_some() {
+ eyre::ensure!(
+ self.minimum.is_some(),
+ "presence of `exclusiveMinimum` requires `minimum` be there too"
+ );
+ }
+ if let Some(multiple_of) = self.multiple_of {
+ eyre::ensure!(multiple_of > 0, "multipleOf must be greater than 0");
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Tag {
+ pub name: String,
+ pub description: Option<String>,
+ pub external_docs: Option<ExternalDocs>,
+}
+
+impl JsonDeref for Tag {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "name" => self.name.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ "external_docs" => self.external_docs.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Schema {
+ pub format: Option<String>,
+ pub title: Option<String>,
+ pub description: Option<String>,
+ pub default: Option<serde_json::Value>,
+ pub multiple_of: Option<u64>,
+ pub maximum: Option<f64>,
+ pub exclusive_maximum: Option<bool>,
+ pub minimum: Option<f64>,
+ pub exclusive_minimum: Option<bool>,
+ pub max_length: Option<u64>,
+ pub min_length: Option<u64>,
+ pub pattern: Option<String>, // should be regex
+ pub max_items: Option<u64>,
+ pub min_items: Option<u64>,
+ pub unique_items: Option<bool>,
+ pub max_properties: Option<u64>,
+ pub min_properties: Option<u64>,
+ pub required: Option<Vec<String>>,
+ #[serde(rename = "enum")]
+ pub _enum: Option<Vec<serde_json::Value>>,
+ #[serde(rename = "type")]
+ pub _type: Option<SchemaType>,
+ pub properties: Option<BTreeMap<String, MaybeRef<Schema>>>,
+ pub additional_properties: Option<Box<MaybeRef<Schema>>>,
+ pub items: Option<Box<MaybeRef<Schema>>>,
+
+ pub discriminator: Option<String>,
+ pub read_only: Option<bool>,
+ pub xml: Option<Xml>,
+ pub external_docs: Option<ExternalDocs>,
+ pub example: Option<serde_json::Value>,
+}
+
+impl JsonDeref for Schema {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "format" => self.format.deref_any(tail),
+ "title" => self.title.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ "default" => self.default.deref_any(tail),
+ "multiple_of" => self.multiple_of.deref_any(tail),
+ "maximum" => self.maximum.deref_any(tail),
+ "exclusive_maximum" => self.exclusive_maximum.deref_any(tail),
+ "minimum" => self.minimum.deref_any(tail),
+ "exclusive_minimum" => self.exclusive_minimum.deref_any(tail),
+ "max_length" => self.max_length.deref_any(tail),
+ "min_length" => self.min_length.deref_any(tail),
+ "pattern" => self.pattern.deref_any(tail), // should be regex
+ "max_items" => self.max_items.deref_any(tail),
+ "min_items" => self.min_items.deref_any(tail),
+ "unique_items" => self.unique_items.deref_any(tail),
+ "max_properties" => self.max_properties.deref_any(tail),
+ "min_properties" => self.min_properties.deref_any(tail),
+ "required" => self.required.deref_any(tail),
+ "enum" => self._enum.deref_any(tail),
+ "type" => self._type.deref_any(tail),
+ "properties" => self.properties.deref_any(tail),
+ "additional_properties" => self.additional_properties.deref_any(tail),
+ "items" => self.items.deref_any(tail),
+ "discriminator" => self.discriminator.deref_any(tail),
+ "read_only" => self.read_only.deref_any(tail),
+ "xml" => self.xml.deref_any(tail),
+ "external_docs" => self.external_docs.deref_any(tail),
+ "example" => self.example.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+impl Schema {
+ fn validate(&self) -> eyre::Result<()> {
+ if let Some(_type) = &self._type {
+ match _type {
+ SchemaType::One(_type) => {
+ if _type == &Primitive::Array {
+ eyre::ensure!(
+ self.items.is_some(),
+ "array paramters must define their item types"
+ );
+ }
+ if let Some(default) = &self.default {
+ eyre::ensure!(
+ _type.matches_value(default),
+ "param's default must match its type"
+ );
+ }
+ if let Some(_enum) = &self._enum {
+ for variant in _enum {
+ eyre::ensure!(
+ _type.matches_value(variant),
+ "schema enum variant must match its type"
+ );
+ }
+ }
+ }
+ SchemaType::List(_) => {
+ eyre::bail!("sum types not supported");
+ }
+ }
+ } else {
+ eyre::ensure!(
+ self.default.is_none(),
+ "cannot have default when no type is specified"
+ );
+ }
+ if let Some(items) = &self.items {
+ if let MaybeRef::Value { value } = &**items {
+ value.validate()?;
+ }
+ }
+ if let Some(required) = &self.required {
+ let properties = self.properties.as_ref().ok_or_else(|| {
+ eyre::eyre!("required properties listed but no properties present")
+ })?;
+ for i in required {
+ eyre::ensure!(
+ properties.contains_key(i),
+ "property \"{i}\" required, but is not defined"
+ );
+ }
+ }
+ if let Some(properties) = &self.properties {
+ for (_, schema) in properties {
+ if let MaybeRef::Value { value } = schema {
+ value.validate().wrap_err("schema properties")?;
+ }
+ }
+ }
+ if let Some(additional_properties) = &self.additional_properties {
+ if let MaybeRef::Value { value } = &**additional_properties {
+ value.validate().wrap_err("schema additional properties")?;
+ }
+ }
+ if self.exclusive_maximum.is_some() {
+ eyre::ensure!(
+ self.maximum.is_some(),
+ "presence of `exclusiveMaximum` requires `maximum` be there too"
+ );
+ }
+ if self.exclusive_minimum.is_some() {
+ eyre::ensure!(
+ self.minimum.is_some(),
+ "presence of `exclusiveMinimum` requires `minimum` be there too"
+ );
+ }
+ if let Some(multiple_of) = self.multiple_of {
+ eyre::ensure!(multiple_of > 0, "multipleOf must be greater than 0");
+ }
+ Ok(())
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(untagged)]
+pub enum SchemaType {
+ One(Primitive),
+ List(Vec<Primitive>),
+}
+
+impl JsonDeref for SchemaType {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ match self {
+ SchemaType::One(i) => i.deref_any(path),
+ SchemaType::List(list) => list.deref_any(path),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub enum Primitive {
+ Array,
+ Boolean,
+ Integer,
+ Number,
+ Null,
+ Object,
+ String,
+}
+
+impl JsonDeref for Primitive {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ Err(eyre::eyre!("not found"))
+ }
+ }
+}
+
+impl Primitive {
+ fn matches_value(&self, value: &serde_json::Value) -> bool {
+ match (self, value) {
+ (Primitive::String, serde_json::Value::String(_))
+ | (Primitive::Number, serde_json::Value::Number(_))
+ | (Primitive::Integer, serde_json::Value::Number(_))
+ | (Primitive::Boolean, serde_json::Value::Bool(_))
+ | (Primitive::Array, serde_json::Value::Array(_)) => true,
+ _ => false,
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct Xml {
+ pub name: Option<String>,
+ pub namespace: Option<Url>,
+ pub prefix: Option<String>,
+ pub attribute: Option<bool>,
+ pub wrapped: Option<bool>,
+}
+
+impl JsonDeref for Xml {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "name" => self.name.deref_any(tail),
+ "namespace" => self.namespace.deref_any(tail),
+ "prefix" => self.prefix.deref_any(tail),
+ "attribute" => self.attribute.deref_any(tail),
+ "wrapped" => self.wrapped.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub struct SecurityScheme {
+ #[serde(flatten)]
+ pub _type: SecurityType,
+ pub description: Option<String>,
+}
+
+impl JsonDeref for SecurityScheme {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match head {
+ "type" => self._type.deref_any(tail),
+ "description" => self.description.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"), tag = "type")]
+pub enum SecurityType {
+ Basic,
+ ApiKey {
+ name: String,
+ #[serde(rename = "in")]
+ _in: KeyIn,
+ },
+ OAuth2 {
+ #[serde(flatten)]
+ flow: OAuth2Flow,
+ scopes: BTreeMap<String, String>,
+ },
+}
+
+impl JsonDeref for SecurityType {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match self {
+ SecurityType::Basic => eyre::bail!("not found: {head}"),
+ SecurityType::ApiKey { name, _in } => match head {
+ "name" => name.deref_any(tail),
+ "in" => _in.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ SecurityType::OAuth2 { flow, scopes } => match head {
+ "flow" => flow.deref_any(tail),
+ "scopes" => scopes.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"))]
+pub enum KeyIn {
+ Query,
+ Header,
+}
+
+impl JsonDeref for KeyIn {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ Ok(self)
+ } else {
+ eyre::bail!("not found")
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(rename_all(deserialize = "camelCase"), tag = "flow")]
+pub enum OAuth2Flow {
+ Implicit {
+ authorization_url: Url,
+ },
+ Password {
+ token_url: Url,
+ },
+ Application {
+ token_url: Url,
+ },
+ AccessCode {
+ authorization_url: Url,
+ token_url: Url,
+ },
+}
+
+impl JsonDeref for OAuth2Flow {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match self {
+ OAuth2Flow::Implicit { authorization_url } => match head {
+ "authorizationUrl" => authorization_url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ OAuth2Flow::Password { token_url } => match head {
+ "tokenUrl" => token_url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ OAuth2Flow::Application { token_url } => match head {
+ "tokenUrl" => token_url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ OAuth2Flow::AccessCode {
+ authorization_url,
+ token_url,
+ } => match head {
+ "authorizationUrl" => authorization_url.deref_any(tail),
+ "tokenUrl" => token_url.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ }
+ }
+}
+
+#[derive(serde::Deserialize, Debug, PartialEq)]
+#[serde(untagged)]
+pub enum MaybeRef<T> {
+ Ref {
+ #[serde(rename = "$ref")]
+ _ref: String,
+ },
+ Value {
+ #[serde(flatten)]
+ value: T,
+ },
+}
+
+impl<T: JsonDeref> JsonDeref for MaybeRef<T> {
+ fn deref_any(&self, path: &str) -> eyre::Result<&dyn std::any::Any> {
+ if path.is_empty() {
+ return Ok(self);
+ }
+ let (head, tail) = path.split_once("/").unwrap_or((path, ""));
+ match self {
+ MaybeRef::Ref { _ref } => match head {
+ "$ref" => _ref.deref_any(tail),
+ _ => eyre::bail!("not found: {head}"),
+ },
+ MaybeRef::Value { value } => value.deref_any(path),
+ }
+ }
+}
+
+impl<T: std::any::Any> MaybeRef<T> {
+ pub fn deref<'a>(&'a self, spec: &'a OpenApiV2) -> eyre::Result<&'a T> {
+ match self {
+ MaybeRef::Ref { _ref } => spec.deref(_ref),
+ MaybeRef::Value { value } => Ok(value),
+ }
+ }
+}
diff --git a/generator/src/structs.rs b/generator/src/structs.rs
new file mode 100644
index 0000000..0b4de08
--- /dev/null
+++ b/generator/src/structs.rs
@@ -0,0 +1,654 @@
+use crate::openapi::*;
+use eyre::WrapErr;
+use heck::ToPascalCase;
+use std::fmt::Write;
+
+pub fn create_structs(spec: &OpenApiV2) -> eyre::Result<String> {
+ let mut s = String::new();
+ s.push_str("use crate::StructureError;");
+ s.push_str("use std::collections::BTreeMap;");
+ if let Some(definitions) = &spec.definitions {
+ for (name, schema) in definitions {
+ let strukt = create_struct_for_definition(&spec, name, schema)?;
+ s.push_str(&strukt);
+ }
+ }
+ if let Some(responses) = &spec.responses {
+ for (name, response) in responses {
+ if let Some(headers) = &response.headers {
+ let strukt = create_header_struct(name, headers)?;
+ s.push_str(&strukt);
+ }
+
+ let tys = create_response_struct(spec, name, response)?;
+ s.push_str(&tys);
+ }
+ }
+ for (_, item) in &spec.paths {
+ let strukt = create_query_structs_for_path(spec, item)?;
+ s.push_str(&strukt);
+
+ let strukt = create_response_structs(spec, item)?;
+ s.push_str(&strukt);
+ }
+ Ok(s)
+}
+
+pub fn create_struct_for_definition(
+ spec: &OpenApiV2,
+ name: &str,
+ schema: &Schema,
+) -> eyre::Result<String> {
+ if matches!(schema._type, Some(SchemaType::One(Primitive::Array))) {
+ return Ok(String::new());
+ }
+
+ if schema._type == Some(SchemaType::One(Primitive::String)) {
+ if let Some(_enum) = &schema._enum {
+ return create_enum(name, schema.description.as_deref(), _enum, false);
+ }
+ }
+
+ let mut subtypes = Vec::new();
+
+ let docs = create_struct_docs(schema)?;
+ let mut fields = String::new();
+ let required = schema.required.as_deref().unwrap_or_default();
+ if let Some(properties) = &schema.properties {
+ for (prop_name, prop_schema) in properties {
+ let prop_ty = crate::schema_ref_type_name(spec, prop_schema)?;
+ let field_name = crate::sanitize_ident(prop_name);
+ let mut field_ty = prop_ty.clone();
+ if let MaybeRef::Value { value } = &prop_schema {
+ crate::schema_subtype_name(spec, name, prop_name, value, &mut field_ty)?;
+ crate::schema_subtypes(spec, name, prop_name, value, &mut subtypes)?;
+ }
+ if field_name.ends_with("url") && field_name != "ssh_url" && field_ty == "String" {
+ field_ty = "url::Url".into()
+ }
+ if field_ty == name {
+ field_ty = format!("Box<{field_ty}>")
+ }
+ if !required.contains(prop_name) {
+ field_ty = format!("Option<{field_ty}>")
+ }
+ if field_ty == "Option<url::Url>" {
+ fields.push_str("#[serde(deserialize_with = \"crate::none_if_blank_url\")]\n");
+ }
+ if field_ty == "time::OffsetDateTime" {
+ fields.push_str("#[serde(with = \"time::serde::rfc3339\")]\n");
+ }
+ if field_ty == "Option<time::OffsetDateTime>" {
+ fields.push_str("#[serde(with = \"time::serde::rfc3339::option\")]\n");
+ }
+ if let MaybeRef::Value { value } = &prop_schema {
+ if let Some(desc) = &value.description {
+ for line in desc.lines() {
+ fields.push_str("/// ");
+ fields.push_str(line);
+ fields.push_str("\n/// \n");
+ }
+ if fields.ends_with("/// \n") {
+ fields.truncate(fields.len() - 5);
+ }
+ }
+ }
+ if &field_name != prop_name {
+ fields.push_str("#[serde(rename = \"");
+ fields.push_str(prop_name);
+ fields.push_str("\")]\n");
+ }
+ fields.push_str("pub ");
+ fields.push_str(&field_name);
+ fields.push_str(": ");
+ fields.push_str(&field_ty);
+ fields.push_str(",\n");
+ }
+ }
+
+ if let Some(additonal_schema) = &schema.additional_properties {
+ let prop_ty = crate::schema_ref_type_name(spec, additonal_schema)?;
+ fields.push_str("#[serde(flatten)]\n");
+ fields.push_str("pub additional: BTreeMap<String, ");
+ fields.push_str(&prop_ty);
+ fields.push_str(">,\n");
+ }
+
+ let mut out = format!("{docs}#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]\npub struct {name} {{\n{fields}}}\n\n");
+ for subtype in subtypes {
+ out.push_str(&subtype);
+ }
+ Ok(out)
+}
+
+pub fn create_enum(
+ name: &str,
+ desc: Option<&str>,
+ _enum: &[serde_json::Value],
+ imp_as_str: bool,
+) -> eyre::Result<String> {
+ let mut variants = String::new();
+ let mut imp = String::new();
+ imp.push_str("match self {");
+ let docs = create_struct_docs_str(desc)?;
+ for variant in _enum {
+ match variant {
+ serde_json::Value::String(s) => {
+ let variant_name = s.to_pascal_case();
+ variants.push_str("#[serde(rename = \"");
+ variants.push_str(s);
+ variants.push_str("\")]");
+ variants.push_str(&variant_name);
+ variants.push_str(",\n");
+
+ writeln!(&mut imp, "{name}::{variant_name} => \"{s}\",")?;
+ }
+ x => eyre::bail!("cannot create enum variant. expected string, got {x:?}"),
+ }
+ }
+ imp.push_str("}");
+
+ let strukt = format!(
+ "
+{docs}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum {name} {{
+ {variants}
+}}"
+ );
+ let out = if imp_as_str {
+ let imp = format!(
+ "\n\nimpl {name} {{
+ fn as_str(&self) -> &'static str {{
+ {imp}
+ }}
+ }}"
+ );
+ format!("{strukt} {imp}")
+ } else {
+ strukt
+ };
+ Ok(out)
+}
+
+fn create_struct_docs(schema: &Schema) -> eyre::Result<String> {
+ create_struct_docs_str(schema.description.as_deref())
+}
+
+fn create_struct_docs_str(description: Option<&str>) -> eyre::Result<String> {
+ let doc = match description {
+ Some(desc) => {
+ let mut out = String::new();
+ for line in desc.lines() {
+ out.push_str("/// ");
+ out.push_str(line);
+ out.push_str("\n/// \n");
+ }
+ if out.ends_with("/// \n") {
+ out.truncate(out.len() - 5);
+ }
+ out
+ }
+ None => String::new(),
+ };
+ Ok(doc)
+}
+
+pub fn create_query_structs_for_path(spec: &OpenApiV2, item: &PathItem) -> eyre::Result<String> {
+ let mut s = String::new();
+ if let Some(op) = &item.get {
+ s.push_str(&create_query_struct(spec, op).wrap_err("GET")?);
+ }
+ if let Some(op) = &item.put {
+ s.push_str(&create_query_struct(spec, op).wrap_err("PUT")?);
+ }
+ if let Some(op) = &item.post {
+ s.push_str(&create_query_struct(spec, op).wrap_err("POST")?);
+ }
+ if let Some(op) = &item.delete {
+ s.push_str(&create_query_struct(spec, op).wrap_err("DELETE")?);
+ }
+ if let Some(op) = &item.options {
+ s.push_str(&create_query_struct(spec, op).wrap_err("OPTIONS")?);
+ }
+ if let Some(op) = &item.head {
+ s.push_str(&create_query_struct(spec, op).wrap_err("HEAD")?);
+ }
+ if let Some(op) = &item.patch {
+ s.push_str(&create_query_struct(spec, op).wrap_err("PATCH")?);
+ }
+ Ok(s)
+}
+
+pub fn query_struct_name(op: &Operation) -> eyre::Result<String> {
+ let mut ty = op
+ .operation_id
+ .as_deref()
+ .ok_or_else(|| eyre::eyre!("operation did not have id"))?
+ .to_pascal_case()
+ .replace("o_auth2", "oauth2");
+ ty.push_str("Query");
+ Ok(ty)
+}
+
+fn create_query_struct(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let params = match &op.parameters {
+ Some(params) => params,
+ None => return Ok(String::new()),
+ };
+
+ let op_name = query_struct_name(op)?;
+ let mut enums = Vec::new();
+ let mut fields = String::new();
+ let mut imp = String::new();
+ for param in params {
+ let param = param.deref(spec)?;
+ if let ParameterIn::Query { param: query_param } = &param._in {
+ let field_name = crate::sanitize_ident(&param.name);
+ let ty = match &query_param {
+ NonBodyParameter {
+ _type: ParameterType::String,
+ _enum: Some(_enum),
+ ..
+ } => {
+ let name = format!("{op_name}{}", param.name.to_pascal_case());
+ let enum_def = create_enum(&name, None, _enum, true)?;
+ enums.push(enum_def);
+ name
+ }
+ NonBodyParameter {
+ _type: ParameterType::Array,
+ items:
+ Some(Items {
+ _type: ParameterType::String,
+ _enum: Some(_enum),
+ ..
+ }),
+ ..
+ } => {
+ let name = format!("{op_name}{}", param.name.to_pascal_case());
+ let enum_def = create_enum(&name, None, _enum, true)?;
+ enums.push(enum_def);
+ format!("Vec<{name}>")
+ }
+ _ => crate::methods::param_type(query_param, true)?,
+ };
+ if let Some(desc) = &param.description {
+ for line in desc.lines() {
+ fields.push_str("/// ");
+ fields.push_str(line);
+ fields.push_str("\n/// \n");
+ }
+ if fields.ends_with("/// \n") {
+ fields.truncate(fields.len() - 5);
+ }
+ }
+ fields.push_str("pub ");
+ fields.push_str(&field_name);
+ fields.push_str(": ");
+ if query_param.required {
+ fields.push_str(&ty);
+ } else {
+ fields.push_str("Option<");
+ fields.push_str(&ty);
+ fields.push_str(">");
+ }
+ fields.push_str(",\n");
+
+ let mut handler = String::new();
+ if query_param.required {
+ writeln!(&mut handler, "let {field_name} = &self.{field_name};")?;
+ } else {
+ writeln!(
+ &mut handler,
+ "if let Some({field_name}) = &self.{field_name} {{"
+ )?;
+ }
+ match &query_param._type {
+ ParameterType::String => {
+ if let Some(_enum) = &query_param._enum {
+ writeln!(
+ &mut handler,
+ "write!(f, \"{}={{}}&\", {}.as_str())?;",
+ param.name, field_name,
+ )?;
+ } else {
+ match query_param.format.as_deref() {
+ Some("date-time" | "date") => {
+ writeln!(
+ &mut handler,
+ "write!(f, \"{}={{field_name}}&\", field_name = {field_name}.format(&time::format_description::well_known::Rfc3339).unwrap())?;",
+ param.name)?;
+ }
+ _ => {
+ writeln!(
+ &mut handler,
+ "write!(f, \"{}={{{}}}&\")?;",
+ param.name,
+ field_name.strip_prefix("r#").unwrap_or(&field_name)
+ )?;
+ }
+ }
+ }
+ }
+ ParameterType::Number | ParameterType::Integer | ParameterType::Boolean => {
+ writeln!(
+ &mut handler,
+ "write!(f, \"{}={{{}}}&\")?;",
+ param.name,
+ field_name.strip_prefix("r#").unwrap_or(&field_name)
+ )?;
+ }
+ ParameterType::Array => {
+ let format = query_param
+ .collection_format
+ .unwrap_or(CollectionFormat::Csv);
+ let item = query_param
+ .items
+ .as_ref()
+ .ok_or_else(|| eyre::eyre!("array must have item type defined"))?;
+ let item_pusher = match item._type {
+ ParameterType::String => {
+ if let Some(_enum) = &item._enum {
+ "write!(f, \"{}\", item.as_str())?;"
+ } else {
+ match query_param.format.as_deref() {
+ Some("date-time" | "date") => {
+ "write!(f, \"{{date}}\", item.format(&time::format_description::well_known::Rfc3339).unwrap())?;"
+ },
+ _ => {
+ "write!(f, \"{item}\")?;"
+ }
+ }
+ }
+ }
+ ParameterType::Number | ParameterType::Integer | ParameterType::Boolean => {
+ "write!(f, \"{item}\")?;"
+ }
+ ParameterType::Array => {
+ eyre::bail!("nested arrays not supported in query");
+ }
+ ParameterType::File => eyre::bail!("cannot send file in query"),
+ };
+ match format {
+ CollectionFormat::Csv => {
+ handler.push_str(&simple_query_array(
+ param,
+ item_pusher,
+ &field_name,
+ ",",
+ )?);
+ }
+ CollectionFormat::Ssv => {
+ handler.push_str(&simple_query_array(
+ param,
+ item_pusher,
+ &field_name,
+ " ",
+ )?);
+ }
+ CollectionFormat::Tsv => {
+ handler.push_str(&simple_query_array(
+ param,
+ item_pusher,
+ &field_name,
+ "\\t",
+ )?);
+ }
+ CollectionFormat::Pipes => {
+ handler.push_str(&simple_query_array(
+ param,
+ item_pusher,
+ &field_name,
+ "|",
+ )?);
+ }
+ CollectionFormat::Multi => {
+ writeln!(&mut handler)?;
+ writeln!(&mut handler, "if !{field_name}.is_empty() {{")?;
+ writeln!(&mut handler, "for item in {field_name} {{")?;
+ writeln!(&mut handler, "write!(f, \"{}=\")?;", param.name)?;
+ handler.push_str(item_pusher);
+ handler.push('\n');
+ writeln!(&mut handler, "write!(f, \"&\")?;")?;
+ writeln!(&mut handler, "}}")?;
+ writeln!(&mut handler, "}}")?;
+ }
+ }
+ }
+ ParameterType::File => eyre::bail!("cannot send file in query"),
+ }
+ if !query_param.required {
+ writeln!(&mut handler, "}}")?;
+ }
+ imp.push_str(&handler);
+ }
+ }
+
+ let result = if fields.is_empty() {
+ String::new()
+ } else {
+ let mut out = format!(
+ "
+pub struct {op_name} {{
+ {fields}
+}}
+
+impl std::fmt::Display for {op_name} {{
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{
+ {imp}
+ Ok(())
+ }}
+}}
+"
+ );
+
+ for _enum in enums {
+ out.push_str(&_enum);
+ }
+
+ out
+ };
+
+ Ok(result)
+}
+
+fn simple_query_array(
+ param: &Parameter,
+ item_pusher: &str,
+ name: &str,
+ sep: &str,
+) -> eyre::Result<String> {
+ let mut out = String::new();
+
+ writeln!(
+ &mut out,
+ "
+if !{name}.is_empty() {{
+ write!(f, \"{}=\")?;
+ for (item, i) in {name}.iter().enumerate() {{
+ {item_pusher}
+ if i < {name}.len() - 1 {{
+ write!(f, \"{sep}\")?;
+ }}
+ }}
+ write!(f, \"&\")?;
+}}",
+ param.name
+ )?;
+
+ Ok(out)
+}
+
+fn create_header_struct(
+ name: &str,
+ headers: &std::collections::BTreeMap<String, Header>,
+) -> eyre::Result<String> {
+ let ty_name = format!("{name}Headers").to_pascal_case();
+ let mut fields = String::new();
+ let mut imp = String::new();
+ let mut imp_ret = String::new();
+ for (header_name, header) in headers {
+ let ty = header_type(header)?;
+ let field_name = crate::sanitize_ident(header_name);
+ fields.push_str("pub ");
+ fields.push_str(&field_name);
+ fields.push_str(": Option<");
+ fields.push_str(&ty);
+ fields.push_str(">,\n");
+
+ write!(
+ &mut imp,
+ "
+ let {field_name} = map.get(\"{header_name}\").map(|s| -> Result<_, _> {{
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ "
+ )
+ .unwrap();
+ match &header._type {
+ ParameterType::String => imp.push_str("Ok(s.to_string())"),
+ ParameterType::Number => match header.format.as_deref() {
+ Some("float") => {
+ imp.push_str("s.parse::<f32>().map_err(|_| StructureError::HeaderParseFailed)")
+ }
+ Some("double") | _ => {
+ imp.push_str("s.parse::<f64>()).map_err(|_| StructureError::HeaderParseFailed)")
+ }
+ },
+ ParameterType::Integer => match header.format.as_deref() {
+ Some("int64") => {
+ imp.push_str("s.parse::<u64>().map_err(|_| StructureError::HeaderParseFailed)")
+ }
+ Some("int32") | _ => {
+ imp.push_str("s.parse::<u32>().map_err(|_| StructureError::HeaderParseFailed)")
+ }
+ },
+ ParameterType::Boolean => {
+ imp.push_str("s.parse::<bool>().map_err(|_| StructureError::HeaderParseFailed)")
+ }
+ ParameterType::Array => {
+ let sep = match header.collection_format {
+ Some(CollectionFormat::Csv) | None => ",",
+ Some(CollectionFormat::Ssv) => " ",
+ Some(CollectionFormat::Tsv) => "\\t",
+ Some(CollectionFormat::Pipes) => "|",
+ Some(CollectionFormat::Multi) => {
+ eyre::bail!("multi format not supported in headers")
+ }
+ };
+ let items = header
+ .items
+ .as_ref()
+ .ok_or_else(|| eyre::eyre!("items property must be set for arrays"))?;
+ if items._type == ParameterType::String {
+ imp.push_str("Ok(");
+ }
+ imp.push_str("s.split(\"");
+ imp.push_str(sep);
+ imp.push_str("\").map(|s| ");
+ imp.push_str(match items._type {
+ ParameterType::String => "s.to_string()).collect::<Vec<_>>())",
+ ParameterType::Number => match items.format.as_deref() {
+ Some("float") => "s.parse::<f32>()).collect::<Result<Vec<_>, _>>().map_err(|_| StructureError::HeaderParseFailed)",
+ Some("double") | _ => "s.parse::<f64>()).collect::<Result<Vec<_>, _>>().map_err(|_| StructureError::HeaderParseFailed)",
+ },
+ ParameterType::Integer => match items.format.as_deref() {
+ Some("int64") => "s.parse::<u64>()).collect::<Result<Vec<_>, _>>().map_err(|_| StructureError::HeaderParseFailed)",
+ Some("int32") | _ => "s.parse::<u32>()).collect::<Result<Vec<_>, _>>().map_err(|_| StructureError::HeaderParseFailed)",
+ },
+ ParameterType::Boolean => "s.parse::<bool>()).collect::<Result<Vec<_>, _>>().map_err(|_| StructureError::HeaderParseFailed)",
+ ParameterType::Array => eyre::bail!("nested arrays not supported in headers"),
+ ParameterType::File => eyre::bail!("files not supported in headers"),
+ });
+ }
+ ParameterType::File => eyre::bail!("files not supported in headers"),
+ }
+ imp.push_str("}).transpose()?;");
+
+ imp_ret.push_str(&field_name);
+ imp_ret.push_str(", ");
+ }
+
+ Ok(format!(
+ "
+pub struct {ty_name} {{
+ {fields}
+}}
+
+impl TryFrom<&reqwest::header::HeaderMap> for {ty_name} {{
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {{
+ {imp}
+ Ok(Self {{ {imp_ret} }})
+ }}
+}}
+"
+ ))
+}
+
+pub fn header_type(header: &Header) -> eyre::Result<String> {
+ crate::methods::param_type_inner(
+ &header._type,
+ header.format.as_deref(),
+ header.items.as_ref(),
+ true,
+ )
+}
+
+pub fn create_response_structs(spec: &OpenApiV2, item: &PathItem) -> eyre::Result<String> {
+ let mut s = String::new();
+ if let Some(op) = &item.get {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("GET")?);
+ }
+ if let Some(op) = &item.put {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("PUT")?);
+ }
+ if let Some(op) = &item.post {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("POST")?);
+ }
+ if let Some(op) = &item.delete {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("DELETE")?);
+ }
+ if let Some(op) = &item.options {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("OPTIONS")?);
+ }
+ if let Some(op) = &item.head {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("HEAD")?);
+ }
+ if let Some(op) = &item.patch {
+ s.push_str(&create_response_structs_for_op(spec, op).wrap_err("PATCH")?);
+ }
+ Ok(s)
+}
+
+pub fn create_response_structs_for_op(spec: &OpenApiV2, op: &Operation) -> eyre::Result<String> {
+ let mut out = String::new();
+ let op_name = op
+ .operation_id
+ .as_deref()
+ .ok_or_else(|| eyre::eyre!("no operation id"))?
+ .to_pascal_case();
+ for (_, response) in &op.responses.http_codes {
+ let response = response.deref(spec)?;
+ let tys = create_response_struct(spec, &op_name, response)?;
+ out.push_str(&tys);
+ }
+ Ok(out)
+}
+
+pub fn create_response_struct(
+ spec: &OpenApiV2,
+ name: &str,
+ res: &Response,
+) -> eyre::Result<String> {
+ let mut types = Vec::new();
+ if let Some(MaybeRef::Value { value }) = &res.schema {
+ crate::schema_subtypes(spec, name, "Response", value, &mut types)?;
+ }
+ let mut out = String::new();
+ for ty in types {
+ out.push_str(&ty);
+ }
+ Ok(out)
+}
diff --git a/src/admin.rs b/src/admin.rs
deleted file mode 100644
index 560d6c6..0000000
--- a/src/admin.rs
+++ /dev/null
@@ -1,502 +0,0 @@
-use super::*;
-
-use std::collections::BTreeMap;
-use std::fmt::Write;
-
-impl Forgejo {
- pub async fn admin_get_crons(&self, query: CronQuery) -> Result<Vec<Cron>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_run_cron(&self, name: &str) -> Result<(), ForgejoError> {
- self.post_unit(&format!("admin/cron/{name}"), &()).await
- }
-
- pub async fn admin_get_emails(
- &self,
- query: EmailListQuery,
- ) -> Result<Vec<Email>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_search_emails(
- &self,
- query: EmailSearchQuery,
- ) -> Result<Vec<Email>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_get_hooks(&self, query: HookQuery) -> Result<Vec<Hook>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_create_hook(&self, opt: CreateHookOption) -> Result<Hook, ForgejoError> {
- self.post("admin/hooks", &opt).await
- }
-
- pub async fn admin_get_hook(&self, id: u64) -> Result<Option<Hook>, ForgejoError> {
- self.get_opt(&format!("admin/hooks/{id}")).await
- }
-
- pub async fn admin_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
- self.delete(&format!("admin/hooks/{id}")).await
- }
-
- pub async fn admin_edit_hook(
- &self,
- id: u64,
- opt: EditHookOption,
- ) -> Result<Hook, ForgejoError> {
- self.patch(&format!("admin/hooks/{id}"), &opt).await
- }
-
- pub async fn admin_get_orgs(
- &self,
- query: AdminOrganizationQuery,
- ) -> Result<Vec<Organization>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_unadopted_repos(
- &self,
- query: UnadoptedRepoQuery,
- ) -> Result<Vec<String>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_adopt(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
- self.post(&format!("admin/unadopted/{owner}/{repo}"), &())
- .await
- }
-
- pub async fn admin_delete_unadopted(
- &self,
- owner: &str,
- repo: &str,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!("admin/unadopted/{owner}/{repo}"))
- .await
- }
-
- pub async fn admin_users(&self, query: AdminUserQuery) -> Result<Vec<User>, ForgejoError> {
- self.get(&query.path()).await
- }
-
- pub async fn admin_create_user(&self, opt: CreateUserOption) -> Result<User, ForgejoError> {
- self.post("admin/users", &opt).await
- }
-
- pub async fn admin_delete_user(&self, user: &str, purge: bool) -> Result<(), ForgejoError> {
- self.delete(&format!("admin/users/{user}?purge={purge}"))
- .await
- }
-
- pub async fn admin_edit_user(
- &self,
- user: &str,
- opt: CreateUserOption,
- ) -> Result<User, ForgejoError> {
- self.patch(&format!("admin/users/{user}"), &opt).await
- }
-
- pub async fn admin_add_key(
- &self,
- user: &str,
- opt: CreateKeyOption,
- ) -> Result<PublicKey, ForgejoError> {
- self.post(&format!("admin/users/{user}/keys"), &opt).await
- }
-
- pub async fn admin_delete_key(&self, user: &str, id: u64) -> Result<(), ForgejoError> {
- self.delete(&format!("admin/users/{user}/keys/{id}")).await
- }
-
- pub async fn admin_create_org(
- &self,
- owner: &str,
- opt: CreateOrgOption,
- ) -> Result<Organization, ForgejoError> {
- self.post(&format!("admin/users/{owner}/orgs"), &opt).await
- }
-
- pub async fn admin_rename_user(
- &self,
- user: &str,
- opt: RenameUserOption,
- ) -> Result<(), ForgejoError> {
- self.post_unit(&format!("admin/users/{user}/rename"), &opt)
- .await
- }
-
- pub async fn admin_create_repo(
- &self,
- owner: &str,
- opt: CreateRepoOption,
- ) -> Result<Repository, ForgejoError> {
- self.post(&format!("admin/users/{owner}/repos"), &opt).await
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Cron {
- pub exec_times: u64,
- pub name: String,
- #[serde(with = "time::serde::rfc3339")]
- pub next: time::OffsetDateTime,
- #[serde(with = "time::serde::rfc3339")]
- pub prev: time::OffsetDateTime,
- pub schedule: String,
-}
-
-#[derive(Default, Debug)]
-pub struct CronQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl CronQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/cron?");
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Email {
- pub email: String,
- pub primary: bool,
- pub user_id: u64,
- pub username: String,
- pub verified: bool,
-}
-
-#[derive(Default, Debug)]
-pub struct EmailListQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl EmailListQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/emails?");
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(Default, Debug)]
-pub struct EmailSearchQuery {
- pub query: String,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl EmailSearchQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/emails/search?");
- if !self.query.is_empty() {
- s.push_str("q=");
- s.push_str(&self.query);
- s.push('&');
- }
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Hook {
- pub active: bool,
- pub authorization_header: String,
- pub branch_filter: String,
- pub config: std::collections::BTreeMap<String, String>,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub events: Vec<String>,
- pub id: u64,
- #[serde(rename = "type")]
- pub _type: HookType,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
-}
-
-#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
-#[non_exhaustive]
-#[serde(rename_all = "lowercase")]
-pub enum HookType {
- Forgejo,
- Dingtalk,
- Discord,
- Gitea,
- Gogs,
- Msteams,
- Slack,
- Telegram,
- Feishu,
- Wechatwork,
- Packagist,
-}
-
-#[derive(Default, Debug)]
-pub struct HookQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl HookQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/hooks?");
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateHookOption {
- pub active: Option<bool>,
- pub authorization_header: Option<String>,
- pub branch_filter: Option<String>,
- pub config: CreateHookOptionConfig,
- pub events: Vec<String>,
- #[serde(rename = "type")]
- pub _type: HookType,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateHookOptionConfig {
- pub content_type: String,
- pub url: Url,
- #[serde(flatten)]
- pub other: BTreeMap<String, String>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditHookOption {
- pub active: Option<bool>,
- pub authorization_header: Option<String>,
- pub branch_filter: Option<String>,
- pub config: Option<BTreeMap<String, String>>,
- pub events: Option<Vec<String>>,
-}
-
-#[derive(Default, Debug)]
-pub struct AdminOrganizationQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl AdminOrganizationQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/orgs?");
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(Default, Debug)]
-pub struct UnadoptedRepoQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
- pub pattern: String,
-}
-
-impl UnadoptedRepoQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/unadopted?");
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if !self.pattern.is_empty() {
- s.push_str("pattern=");
- s.push_str(&self.pattern);
- s.push('&');
- }
- s
- }
-}
-
-#[derive(Default, Debug)]
-pub struct AdminUserQuery {
- pub source_id: Option<u64>,
- pub login_name: String,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl AdminUserQuery {
- fn path(&self) -> String {
- let mut s = String::from("admin/users?");
- if let Some(source_id) = self.source_id {
- s.push_str("source_id=");
- s.write_fmt(format_args!("{source_id}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if !self.login_name.is_empty() {
- s.push_str("login_name=");
- s.push_str(&self.login_name);
- s.push('&');
- }
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateUserOption {
- #[serde(with = "time::serde::rfc3339::option")]
- pub created_at: Option<time::OffsetDateTime>,
- pub email: String,
- pub full_name: Option<String>,
- pub login_name: Option<String>,
- pub must_change_password: bool,
- pub password: String,
- pub restricted: bool,
- pub send_notify: bool,
- pub source_id: Option<u64>,
- pub username: String,
- pub visibility: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditUserOption {
- pub active: Option<bool>,
- pub admin: Option<bool>,
- pub allow_create_organization: Option<bool>,
- pub allow_git_hook: Option<bool>,
- pub allow_import_local: Option<bool>,
- pub description: Option<String>,
- pub email: Option<String>,
- pub full_name: Option<String>,
- pub location: Option<String>,
- pub login_name: Option<String>,
- pub max_repo_creation: Option<u64>,
- pub must_change_password: Option<bool>,
- pub password: Option<String>,
- pub prohibit_login: Option<bool>,
- pub restricted: Option<bool>,
- pub source_id: Option<u64>,
- pub visibility: Option<String>,
- pub website: Option<String>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateKeyOption {
- pub key: String,
- pub read_only: Option<bool>,
- pub title: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct PublicKey {
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub fingerprint: String,
- pub id: u64,
- pub key: String,
- pub key_type: String,
- pub read_only: Option<bool>,
- pub title: String,
- pub url: Option<Url>,
- pub user: User,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateOrgOption {
- pub description: Option<String>,
- pub full_name: Option<String>,
- pub location: Option<String>,
- pub repo_admin_change_team_access: Option<bool>,
- pub username: String,
- pub visibility: OrgVisibility,
- pub website: Option<Url>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-#[serde(rename_all = "lowercase")]
-pub enum OrgVisibility {
- Public,
- Limited,
- Private,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct RenameUserOption {
- pub new_username: String,
-}
diff --git a/src/generated/methods.rs b/src/generated/methods.rs
new file mode 100644
index 0000000..0f6a97b
--- /dev/null
+++ b/src/generated/methods.rs
@@ -0,0 +1,7226 @@
+use super::structs::*;
+use crate::ForgejoError;
+use std::collections::BTreeMap;
+
+impl crate::Forgejo {
+ /// Returns the Person actor for a user
+ ///
+ /// - `user-id`: user ID of the user
+ pub async fn activitypub_person(&self, user_id: u32) -> Result<ActivityPub, ForgejoError> {
+ let request = self
+ .get(&format!("activitypub/user-id/{user_id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Send to the inbox
+ ///
+ /// - `user-id`: user ID of the user
+ pub async fn activitypub_person_inbox(&self, user_id: u32) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("activitypub/user-id/{user_id}/inbox"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List cron tasks
+ ///
+ pub async fn admin_cron_list(
+ &self,
+ query: AdminCronListQuery,
+ ) -> Result<Vec<Cron>, ForgejoError> {
+ let request = self.get(&format!("admin/cron?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Run cron task
+ ///
+ /// - `task`: task to run
+ pub async fn admin_cron_run(&self, task: &str) -> Result<(), ForgejoError> {
+ let request = self.post(&format!("admin/cron/{task}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all emails
+ ///
+ pub async fn admin_get_all_emails(
+ &self,
+ query: AdminGetAllEmailsQuery,
+ ) -> Result<Vec<Email>, ForgejoError> {
+ let request = self.get(&format!("admin/emails?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search all emails
+ ///
+ pub async fn admin_search_emails(
+ &self,
+ query: AdminSearchEmailsQuery,
+ ) -> Result<Vec<Email>, ForgejoError> {
+ let request = self.get(&format!("admin/emails/search?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List system's webhooks
+ ///
+ pub async fn admin_list_hooks(
+ &self,
+ query: AdminListHooksQuery,
+ ) -> Result<Vec<Hook>, ForgejoError> {
+ let request = self.get(&format!("admin/hooks?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a hook
+ ///
+ /// - `body`: See [`CreateHookOption`]
+ pub async fn admin_create_hook(&self, body: CreateHookOption) -> Result<Hook, ForgejoError> {
+ let request = self.post("admin/hooks").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a hook
+ ///
+ /// - `id`: id of the hook to get
+ pub async fn admin_get_hook(&self, id: u64) -> Result<Hook, ForgejoError> {
+ let request = self.get(&format!("admin/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a hook
+ ///
+ /// - `id`: id of the hook to delete
+ pub async fn admin_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("admin/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a hook
+ ///
+ /// - `id`: id of the hook to update
+ /// - `body`: See [`EditHookOption`]
+ pub async fn admin_edit_hook(
+ &self,
+ id: u64,
+ body: EditHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .patch(&format!("admin/hooks/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all organizations
+ ///
+ pub async fn admin_get_all_orgs(
+ &self,
+ query: AdminGetAllOrgsQuery,
+ ) -> Result<Vec<Organization>, ForgejoError> {
+ let request = self.get(&format!("admin/orgs?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List unadopted repositories
+ ///
+ pub async fn admin_unadopted_list(
+ &self,
+ query: AdminUnadoptedListQuery,
+ ) -> Result<Vec<String>, ForgejoError> {
+ let request = self.get(&format!("admin/unadopted?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Adopt unadopted files as a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn admin_adopt_repository(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("admin/unadopted/{owner}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete unadopted files
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn admin_delete_unadopted_repository(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("admin/unadopted/{owner}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search users according filter conditions
+ ///
+ pub async fn admin_search_users(
+ &self,
+ query: AdminSearchUsersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self.get(&format!("admin/users?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a user
+ ///
+ /// - `body`: See [`CreateUserOption`]
+ pub async fn admin_create_user(&self, body: CreateUserOption) -> Result<User, ForgejoError> {
+ let request = self.post("admin/users").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a user
+ ///
+ /// - `username`: username of user to delete
+ pub async fn admin_delete_user(
+ &self,
+ username: &str,
+ query: AdminDeleteUserQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("admin/users/{username}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit an existing user
+ ///
+ /// - `username`: username of user to edit
+ /// - `body`: See [`EditUserOption`]
+ pub async fn admin_edit_user(
+ &self,
+ username: &str,
+ body: EditUserOption,
+ ) -> Result<User, ForgejoError> {
+ let request = self
+ .patch(&format!("admin/users/{username}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a public key on behalf of a user
+ ///
+ /// - `username`: username of the user
+ /// - `key`: See [`CreateKeyOption`]
+ pub async fn admin_create_public_key(
+ &self,
+ username: &str,
+ key: CreateKeyOption,
+ ) -> Result<PublicKey, ForgejoError> {
+ let request = self
+ .post(&format!("admin/users/{username}/keys"))
+ .json(&key)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a user's public key
+ ///
+ /// - `username`: username of user
+ /// - `id`: id of the key to delete
+ pub async fn admin_delete_user_public_key(
+ &self,
+ username: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("admin/users/{username}/keys/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create an organization
+ ///
+ /// - `username`: username of the user that will own the created organization
+ /// - `organization`: See [`CreateOrgOption`]
+ pub async fn admin_create_org(
+ &self,
+ username: &str,
+ organization: CreateOrgOption,
+ ) -> Result<Organization, ForgejoError> {
+ let request = self
+ .post(&format!("admin/users/{username}/orgs"))
+ .json(&organization)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Rename a user
+ ///
+ /// - `username`: existing username of user
+ /// - `body`: See [`RenameUserOption`]
+ pub async fn admin_rename_user(
+ &self,
+ username: &str,
+ body: RenameUserOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("admin/users/{username}/rename"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a repository on behalf of a user
+ ///
+ /// - `username`: username of the user. This user will own the created repository
+ /// - `repository`: See [`CreateRepoOption`]
+ pub async fn admin_create_repo(
+ &self,
+ username: &str,
+ repository: CreateRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("admin/users/{username}/repos"))
+ .json(&repository)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns a list of all gitignore templates
+ pub async fn list_gitignores_templates(&self) -> Result<Vec<String>, ForgejoError> {
+ let request = self.get("gitignore/templates").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns information about a gitignore template
+ ///
+ /// - `name`: name of the template
+ pub async fn get_gitignore_template_info(
+ &self,
+ name: &str,
+ ) -> Result<GitignoreTemplateInfo, ForgejoError> {
+ let request = self.get(&format!("gitignore/templates/{name}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns a list of all label templates
+ pub async fn list_label_templates(&self) -> Result<Vec<String>, ForgejoError> {
+ let request = self.get("label/templates").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns all labels in a template
+ ///
+ /// - `name`: name of the template
+ pub async fn get_label_template_info(
+ &self,
+ name: &str,
+ ) -> Result<Vec<LabelTemplate>, ForgejoError> {
+ let request = self.get(&format!("label/templates/{name}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns a list of all license templates
+ pub async fn list_license_templates(
+ &self,
+ ) -> Result<Vec<LicensesTemplateListEntry>, ForgejoError> {
+ let request = self.get("licenses").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns information about a license template
+ ///
+ /// - `name`: name of the license
+ pub async fn get_license_template_info(
+ &self,
+ name: &str,
+ ) -> Result<LicenseTemplateInfo, ForgejoError> {
+ let request = self.get(&format!("licenses/{name}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Render a markdown document as HTML
+ ///
+ /// - `body`: See [`MarkdownOption`]
+ pub async fn render_markdown(&self, body: MarkdownOption) -> Result<String, ForgejoError> {
+ let request = self.post("markdown").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Render raw markdown as HTML
+ ///
+ /// - `body`: Request body to render
+
+ /// See [`String`]
+ pub async fn render_markdown_raw(&self, body: String) -> Result<String, ForgejoError> {
+ let request = self.post("markdown/raw").body(body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Render a markup document as HTML
+ ///
+ /// - `body`: See [`MarkupOption`]
+ pub async fn render_markup(&self, body: MarkupOption) -> Result<String, ForgejoError> {
+ let request = self.post("markup").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns the nodeinfo of the Gitea application
+ pub async fn get_node_info(&self) -> Result<NodeInfo, ForgejoError> {
+ let request = self.get("nodeinfo").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List users's notification threads
+ ///
+ pub async fn notify_get_list(
+ &self,
+ query: NotifyGetListQuery,
+ ) -> Result<Vec<NotificationThread>, ForgejoError> {
+ let request = self.get(&format!("notifications?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Mark notification threads as read, pinned or unread
+ ///
+ pub async fn notify_read_list(
+ &self,
+ query: NotifyReadListQuery,
+ ) -> Result<Vec<NotificationThread>, ForgejoError> {
+ let request = self.put(&format!("notifications?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 205 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if unread notifications exist
+ pub async fn notify_new_available(&self) -> Result<NotificationCount, ForgejoError> {
+ let request = self.get("notifications/new").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get notification thread by ID
+ ///
+ /// - `id`: id of notification thread
+ pub async fn notify_get_thread(&self, id: &str) -> Result<NotificationThread, ForgejoError> {
+ let request = self.get(&format!("notifications/threads/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Mark notification thread as read by ID
+ ///
+ /// - `id`: id of notification thread
+ pub async fn notify_read_thread(
+ &self,
+ id: &str,
+ query: NotifyReadThreadQuery,
+ ) -> Result<NotificationThread, ForgejoError> {
+ let request = self
+ .patch(&format!("notifications/threads/{id}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 205 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a repository in an organization
+ ///
+ /// - `org`: name of organization
+ /// - `body`: See [`CreateRepoOption`]
+ pub async fn create_org_repo_deprecated(
+ &self,
+ org: &str,
+ body: CreateRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self.post(&format!("org/{org}/repos")).json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get list of organizations
+ ///
+ pub async fn org_get_all(
+ &self,
+ query: OrgGetAllQuery,
+ ) -> Result<Vec<Organization>, ForgejoError> {
+ let request = self.get(&format!("orgs?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create an organization
+ ///
+ /// - `organization`: See [`CreateOrgOption`]
+ pub async fn org_create(
+ &self,
+ organization: CreateOrgOption,
+ ) -> Result<Organization, ForgejoError> {
+ let request = self.post("orgs").json(&organization).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get an organization
+ ///
+ /// - `org`: name of the organization to get
+ pub async fn org_get(&self, org: &str) -> Result<Organization, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete an organization
+ ///
+ /// - `org`: organization that is to be deleted
+ pub async fn org_delete(&self, org: &str) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("orgs/{org}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit an organization
+ ///
+ /// - `org`: name of the organization to edit
+ /// - `body`: See [`EditOrgOption`]
+ pub async fn org_edit(
+ &self,
+ org: &str,
+ body: EditOrgOption,
+ ) -> Result<Organization, ForgejoError> {
+ let request = self.patch(&format!("orgs/{org}")).json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's actions secrets
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_actions_secrets(
+ &self,
+ org: &str,
+ query: OrgListActionsSecretsQuery,
+ ) -> Result<Vec<Secret>, ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/actions/secrets?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create or Update a secret value in an organization
+ ///
+ /// - `org`: name of organization
+ /// - `secretname`: name of the secret
+ /// - `body`: See [`CreateOrUpdateSecretOption`]
+ pub async fn update_org_secret(
+ &self,
+ org: &str,
+ secretname: &str,
+ body: CreateOrUpdateSecretOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("orgs/{org}/actions/secrets/{secretname}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(()),
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a secret in an organization
+ ///
+ /// - `org`: name of organization
+ /// - `secretname`: name of the secret
+ pub async fn delete_org_secret(&self, org: &str, secretname: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("orgs/{org}/actions/secrets/{secretname}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's activity feeds
+ ///
+ /// - `org`: name of the org
+ pub async fn org_list_activity_feeds(
+ &self,
+ org: &str,
+ query: OrgListActivityFeedsQuery,
+ ) -> Result<Vec<Activity>, ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/activities/feeds?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update Avatar
+ ///
+ /// - `org`: name of the organization
+ /// - `body`: See [`UpdateUserAvatarOption`]
+ pub async fn org_update_avatar(
+ &self,
+ org: &str,
+ body: UpdateUserAvatarOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("orgs/{org}/avatar"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete Avatar
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_delete_avatar(&self, org: &str) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("orgs/{org}/avatar")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Blocks a user from the organization
+ ///
+ /// - `org`: name of the org
+ /// - `username`: username of the user
+ pub async fn org_block_user(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
+ let request = self.put(&format!("orgs/{org}/block/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's webhooks
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_hooks(
+ &self,
+ org: &str,
+ query: OrgListHooksQuery,
+ ) -> Result<Vec<Hook>, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/hooks?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a hook
+ ///
+ /// - `org`: name of the organization
+ /// - `body`: See [`CreateHookOption`]
+ pub async fn org_create_hook(
+ &self,
+ org: &str,
+ body: CreateHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .post(&format!("orgs/{org}/hooks"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a hook
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the hook to get
+ pub async fn org_get_hook(&self, org: &str, id: u64) -> Result<Hook, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a hook
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the hook to delete
+ pub async fn org_delete_hook(&self, org: &str, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("orgs/{org}/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a hook
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the hook to update
+ /// - `body`: See [`EditHookOption`]
+ pub async fn org_edit_hook(
+ &self,
+ org: &str,
+ id: u64,
+ body: EditHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .patch(&format!("orgs/{org}/hooks/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's labels
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_labels(
+ &self,
+ org: &str,
+ query: OrgListLabelsQuery,
+ ) -> Result<Vec<Label>, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/labels?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a label for an organization
+ ///
+ /// - `org`: name of the organization
+ /// - `body`: See [`CreateLabelOption`]
+ pub async fn org_create_label(
+ &self,
+ org: &str,
+ body: CreateLabelOption,
+ ) -> Result<Label, ForgejoError> {
+ let request = self
+ .post(&format!("orgs/{org}/labels"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a single label
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the label to get
+ pub async fn org_get_label(&self, org: &str, id: u64) -> Result<Label, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/labels/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a label
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the label to delete
+ pub async fn org_delete_label(&self, org: &str, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("orgs/{org}/labels/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a label
+ ///
+ /// - `org`: name of the organization
+ /// - `id`: id of the label to edit
+ /// - `body`: See [`EditLabelOption`]
+ pub async fn org_edit_label(
+ &self,
+ org: &str,
+ id: u64,
+ body: EditLabelOption,
+ ) -> Result<Label, ForgejoError> {
+ let request = self
+ .patch(&format!("orgs/{org}/labels/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the organization's blocked users
+ ///
+ /// - `org`: name of the org
+ pub async fn org_list_blocked_users(
+ &self,
+ org: &str,
+ query: OrgListBlockedUsersQuery,
+ ) -> Result<Vec<BlockedUser>, ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/list_blocked?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's members
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_members(
+ &self,
+ org: &str,
+ query: OrgListMembersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/members?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if a user is a member of an organization
+ ///
+ /// - `org`: name of the organization
+ /// - `username`: username of the user
+ pub async fn org_is_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a member from an organization
+ ///
+ /// - `org`: name of the organization
+ /// - `username`: username of the user
+ pub async fn org_delete_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("orgs/{org}/members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's public members
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_public_members(
+ &self,
+ org: &str,
+ query: OrgListPublicMembersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/public_members?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if a user is a public member of an organization
+ ///
+ /// - `org`: name of the organization
+ /// - `username`: username of the user
+ pub async fn org_is_public_member(
+ &self,
+ org: &str,
+ username: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/public_members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Publicize a user's membership
+ ///
+ /// - `org`: name of the organization
+ /// - `username`: username of the user
+ pub async fn org_publicize_member(
+ &self,
+ org: &str,
+ username: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("orgs/{org}/public_members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Conceal a user's membership
+ ///
+ /// - `org`: name of the organization
+ /// - `username`: username of the user
+ pub async fn org_conceal_member(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("orgs/{org}/public_members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's repos
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_repos(
+ &self,
+ org: &str,
+ query: OrgListReposQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/repos?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a repository in an organization
+ ///
+ /// - `org`: name of organization
+ /// - `body`: See [`CreateRepoOption`]
+ pub async fn create_org_repo(
+ &self,
+ org: &str,
+ body: CreateRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("orgs/{org}/repos"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an organization's teams
+ ///
+ /// - `org`: name of the organization
+ pub async fn org_list_teams(
+ &self,
+ org: &str,
+ query: OrgListTeamsQuery,
+ ) -> Result<Vec<Team>, ForgejoError> {
+ let request = self.get(&format!("orgs/{org}/teams?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a team
+ ///
+ /// - `org`: name of the organization
+ /// - `body`: See [`CreateTeamOption`]
+ pub async fn org_create_team(
+ &self,
+ org: &str,
+ body: CreateTeamOption,
+ ) -> Result<Team, ForgejoError> {
+ let request = self
+ .post(&format!("orgs/{org}/teams"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search for teams within an organization
+ ///
+ /// - `org`: name of the organization
+ pub async fn team_search(
+ &self,
+ org: &str,
+ query: TeamSearchQuery,
+ ) -> Result<TeamSearchResponse, ForgejoError> {
+ let request = self
+ .get(&format!("orgs/{org}/teams/search?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unblock a user from the organization
+ ///
+ /// - `org`: name of the org
+ /// - `username`: username of the user
+ pub async fn org_unblock_user(&self, org: &str, username: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("orgs/{org}/unblock/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets all packages of an owner
+ ///
+ /// - `owner`: owner of the packages
+ pub async fn list_packages(
+ &self,
+ owner: &str,
+ query: ListPackagesQuery,
+ ) -> Result<Vec<Package>, ForgejoError> {
+ let request = self.get(&format!("packages/{owner}?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets a package
+ ///
+ /// - `owner`: owner of the package
+ /// - `type`: type of the package
+ /// - `name`: name of the package
+ /// - `version`: version of the package
+ pub async fn get_package(
+ &self,
+ owner: &str,
+ r#type: &str,
+ name: &str,
+ version: &str,
+ ) -> Result<Package, ForgejoError> {
+ let request = self
+ .get(&format!("packages/{owner}/{type}/{name}/{version}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a package
+ ///
+ /// - `owner`: owner of the package
+ /// - `type`: type of the package
+ /// - `name`: name of the package
+ /// - `version`: version of the package
+ pub async fn delete_package(
+ &self,
+ owner: &str,
+ r#type: &str,
+ name: &str,
+ version: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("packages/{owner}/{type}/{name}/{version}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets all files of a package
+ ///
+ /// - `owner`: owner of the package
+ /// - `type`: type of the package
+ /// - `name`: name of the package
+ /// - `version`: version of the package
+ pub async fn list_package_files(
+ &self,
+ owner: &str,
+ r#type: &str,
+ name: &str,
+ version: &str,
+ ) -> Result<Vec<PackageFile>, ForgejoError> {
+ let request = self
+ .get(&format!("packages/{owner}/{type}/{name}/{version}/files"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search for issues across the repositories that the user has access to
+ ///
+ pub async fn issue_search_issues(
+ &self,
+ query: IssueSearchIssuesQuery,
+ ) -> Result<Vec<Issue>, ForgejoError> {
+ let request = self.get(&format!("repos/issues/search?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Migrate a remote git repository
+ ///
+ /// - `body`: See [`MigrateRepoOptions`]
+ pub async fn repo_migrate(&self, body: MigrateRepoOptions) -> Result<Repository, ForgejoError> {
+ let request = self.post("repos/migrate").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search for repositories
+ ///
+ pub async fn repo_search(&self, query: RepoSearchQuery) -> Result<SearchResults, ForgejoError> {
+ let request = self.get(&format!("repos/search?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get(&self, owner: &str, repo: &str) -> Result<Repository, ForgejoError> {
+ let request = self.get(&format!("repos/{owner}/{repo}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a repository
+ ///
+ /// - `owner`: owner of the repo to delete
+ /// - `repo`: name of the repo to delete
+ pub async fn repo_delete(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("repos/{owner}/{repo}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a repository's properties. Only fields that are set will be changed.
+ ///
+ /// - `owner`: owner of the repo to edit
+ /// - `repo`: name of the repo to edit
+ /// - `body`: Properties of a repo that you can edit
+
+ /// See [`EditRepoOption`]
+ pub async fn repo_edit(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: EditRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create or Update a secret value in a repository
+ ///
+ /// - `owner`: owner of the repository
+ /// - `repo`: name of the repository
+ /// - `secretname`: name of the secret
+ /// - `body`: See [`CreateOrUpdateSecretOption`]
+ pub async fn update_repo_secret(
+ &self,
+ owner: &str,
+ repo: &str,
+ secretname: &str,
+ body: CreateOrUpdateSecretOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!(
+ "repos/{owner}/{repo}/actions/secrets/{secretname}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(()),
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a secret in a repository
+ ///
+ /// - `owner`: owner of the repository
+ /// - `repo`: name of the repository
+ /// - `secretname`: name of the secret
+ pub async fn delete_repo_secret(
+ &self,
+ owner: &str,
+ repo: &str,
+ secretname: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/actions/secrets/{secretname}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's activity feeds
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_activity_feeds(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListActivityFeedsQuery,
+ ) -> Result<Vec<Activity>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/activities/feeds?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get an archive of a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `archive`: the git reference for download with attached archive format (e.g. master.zip)
+ pub async fn repo_get_archive(
+ &self,
+ owner: &str,
+ repo: &str,
+ archive: &str,
+ ) -> Result<Vec<u8>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/archive/{archive}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.bytes().await?[..].to_vec()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Return all users that have write access and can be assigned to issues
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_assignees(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/assignees"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update avatar
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`UpdateRepoAvatarOption`]
+ pub async fn repo_update_avatar(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: UpdateRepoAvatarOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/avatar"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete avatar
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_delete_avatar(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/avatar"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List branch protections for a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_branch_protection(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<BranchProtection>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/branch_protections"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a branch protections for a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateBranchProtectionOption`]
+ pub async fn repo_create_branch_protection(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateBranchProtectionOption,
+ ) -> Result<BranchProtection, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/branch_protections"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a specific branch protection for the repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `name`: name of protected branch
+ pub async fn repo_get_branch_protection(
+ &self,
+ owner: &str,
+ repo: &str,
+ name: &str,
+ ) -> Result<BranchProtection, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a specific branch protection for the repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `name`: name of protected branch
+ pub async fn repo_delete_branch_protection(
+ &self,
+ owner: &str,
+ repo: &str,
+ name: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a branch protections for a repository. Only fields that are set will be changed
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `name`: name of protected branch
+ /// - `body`: See [`EditBranchProtectionOption`]
+ pub async fn repo_edit_branch_protection(
+ &self,
+ owner: &str,
+ repo: &str,
+ name: &str,
+ body: EditBranchProtectionOption,
+ ) -> Result<BranchProtection, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/branch_protections/{name}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's branches
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_branches(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListBranchesQuery,
+ ) -> Result<Vec<Branch>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/branches?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a branch
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateBranchRepoOption`]
+ pub async fn repo_create_branch(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateBranchRepoOption,
+ ) -> Result<Branch, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/branches"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Retrieve a specific branch from a repository, including its effective branch protection
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `branch`: branch to get
+ pub async fn repo_get_branch(
+ &self,
+ owner: &str,
+ repo: &str,
+ branch: &str,
+ ) -> Result<Branch, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/branches/{branch}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a specific branch from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `branch`: branch to delete
+ pub async fn repo_delete_branch(
+ &self,
+ owner: &str,
+ repo: &str,
+ branch: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/branches/{branch}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's collaborators
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_collaborators(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListCollaboratorsQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/collaborators?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if a user is a collaborator of a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `collaborator`: username of the collaborator
+ pub async fn repo_check_collaborator(
+ &self,
+ owner: &str,
+ repo: &str,
+ collaborator: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/collaborators/{collaborator}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a collaborator to a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `collaborator`: username of the collaborator to add
+ /// - `body`: See [`AddCollaboratorOption`]
+ pub async fn repo_add_collaborator(
+ &self,
+ owner: &str,
+ repo: &str,
+ collaborator: &str,
+ body: AddCollaboratorOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!(
+ "repos/{owner}/{repo}/collaborators/{collaborator}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a collaborator from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `collaborator`: username of the collaborator to delete
+ pub async fn repo_delete_collaborator(
+ &self,
+ owner: &str,
+ repo: &str,
+ collaborator: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/collaborators/{collaborator}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get repository permissions for a user
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `collaborator`: username of the collaborator
+ pub async fn repo_get_repo_permissions(
+ &self,
+ owner: &str,
+ repo: &str,
+ collaborator: &str,
+ ) -> Result<RepoCollaboratorPermission, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/collaborators/{collaborator}/permission"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a list of all commits from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_all_commits(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoGetAllCommitsQuery,
+ ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/commits?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok((response.headers().try_into()?, response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a commit's combined status, by branch/tag/commit reference
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `ref`: name of branch/tag/commit
+ pub async fn repo_get_combined_status_by_ref(
+ &self,
+ owner: &str,
+ repo: &str,
+ r#ref: &str,
+ query: RepoGetCombinedStatusByRefQuery,
+ ) -> Result<CombinedStatus, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/commits/{ref}/status?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a commit's statuses, by branch/tag/commit reference
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `ref`: name of branch/tag/commit
+ pub async fn repo_list_statuses_by_ref(
+ &self,
+ owner: &str,
+ repo: &str,
+ r#ref: &str,
+ query: RepoListStatusesByRefQuery,
+ ) -> Result<Vec<CommitStatus>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/commits/{ref}/statuses?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the metadata of all the entries of the root dir
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_contents_list(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoGetContentsListQuery,
+ ) -> Result<Vec<ContentsResponse>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/contents?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Modify multiple files in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`ChangeFilesOptions`]
+ pub async fn repo_change_files(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: ChangeFilesOptions,
+ ) -> Result<FilesResponse, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/contents"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: path of the dir, file, symlink or submodule in the repo
+ pub async fn repo_get_contents(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ query: RepoGetContentsQuery,
+ ) -> Result<ContentsResponse, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/contents/{filepath}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a file in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: path of the file to update
+ /// - `body`: See [`UpdateFileOptions`]
+ pub async fn repo_update_file(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ body: UpdateFileOptions,
+ ) -> Result<FileResponse, ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/contents/{filepath}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a file in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: path of the file to create
+ /// - `body`: See [`CreateFileOptions`]
+ pub async fn repo_create_file(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ body: CreateFileOptions,
+ ) -> Result<FileResponse, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/contents/{filepath}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a file in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: path of the file to delete
+ /// - `body`: See [`DeleteFileOptions`]
+ pub async fn repo_delete_file(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ body: DeleteFileOptions,
+ ) -> Result<FileDeleteResponse, ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/contents/{filepath}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Apply diff patch to repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`UpdateFileOptions`]
+ pub async fn repo_apply_diff_patch(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: UpdateFileOptions,
+ ) -> Result<FileResponse, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/diffpatch"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get the EditorConfig definitions of a file in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: filepath of file to get
+ pub async fn repo_get_editor_config(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ query: RepoGetEditorConfigQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/editorconfig/{filepath}?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's forks
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn list_forks(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: ListForksQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/forks?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Fork a repository
+ ///
+ /// - `owner`: owner of the repo to fork
+ /// - `repo`: name of the repo to fork
+ /// - `body`: See [`CreateForkOption`]
+ pub async fn create_fork(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateForkOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/forks"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 202 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the blob of a repository.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: sha of the commit
+ pub async fn get_blob(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ ) -> Result<GitBlobResponse, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/blobs/{sha}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a single commit from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: a git ref or commit sha
+ pub async fn repo_get_single_commit(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ query: RepoGetSingleCommitQuery,
+ ) -> Result<Commit, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/commits/{sha}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a commit's diff or patch
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: SHA of the commit to get
+ /// - `diffType`: whether the output is diff or patch
+ pub async fn repo_download_commit_diff_or_patch(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ diff_type: &str,
+ ) -> Result<String, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/git/commits/{sha}.{diff_type}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a note corresponding to a single commit from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: a git ref or commit sha
+ pub async fn repo_get_note(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ query: RepoGetNoteQuery,
+ ) -> Result<Note, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/notes/{sha}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get specified ref or filtered repository's refs
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_all_git_refs(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<Reference>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/refs"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get specified ref or filtered repository's refs
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `ref`: part or full name of the ref
+ pub async fn repo_list_git_refs(
+ &self,
+ owner: &str,
+ repo: &str,
+ r#ref: &str,
+ ) -> Result<Vec<Reference>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/refs/{ref}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the tag object of an annotated tag (not lightweight tags)
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: sha of the tag. The Git tags API only supports annotated tag objects, not lightweight tags.
+ pub async fn get_annotated_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ ) -> Result<AnnotatedTag, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/tags/{sha}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the tree of a repository.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: sha of the commit
+ pub async fn get_tree(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ query: GetTreeQuery,
+ ) -> Result<GitTreeResponse, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/git/trees/{sha}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the hooks in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_hooks(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListHooksQuery,
+ ) -> Result<Vec<Hook>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/hooks?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a hook
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateHookOption`]
+ pub async fn repo_create_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/hooks"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the Git hooks in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_git_hooks(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<GitHook>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/hooks/git"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a Git hook
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to get
+ pub async fn repo_get_git_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ ) -> Result<GitHook, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a Git hook in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to get
+ pub async fn repo_delete_git_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a Git hook in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to get
+ /// - `body`: See [`EditGitHookOption`]
+ pub async fn repo_edit_git_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ body: EditGitHookOption,
+ ) -> Result<GitHook, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/hooks/git/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a hook
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to get
+ pub async fn repo_get_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/hooks/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a hook in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to delete
+ pub async fn repo_delete_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/hooks/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a hook in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: index of the hook
+ /// - `body`: See [`EditHookOption`]
+ pub async fn repo_edit_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ body: EditHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/hooks/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Test a push webhook
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the hook to test
+ pub async fn repo_test_hook(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ query: RepoTestHookQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/hooks/{id}/tests?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns the issue config for a repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_issue_config(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<IssueConfig, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issue_config"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns the validation information for a issue config
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_validate_issue_config(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<IssueConfigValidation, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issue_config/validate"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get available issue templates for a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_issue_templates(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<IssueTemplate>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issue_templates"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's issues
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn issue_list_issues(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: IssueListIssuesQuery,
+ ) -> Result<Vec<Issue>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create an issue. If using deadline only the date will be taken into account, and time of day ignored.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateIssueOption`]
+ pub async fn issue_create_issue(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateIssueOption,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all comments in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn issue_get_repo_comments(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: IssueGetRepoCommentsQuery,
+ ) -> Result<Vec<Comment>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/comments?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a comment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ pub async fn issue_get_comment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Option<Comment>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(Some(response.json().await?)),
+ 204 => Ok(Some(response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a comment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of comment to delete
+ pub async fn issue_delete_comment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a comment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment to edit
+ /// - `body`: See [`EditIssueCommentOption`]
+ pub async fn issue_edit_comment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ body: EditIssueCommentOption,
+ ) -> Result<Option<Comment>, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(Some(response.json().await?)),
+ 204 => Ok(Some(response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List comment's attachments
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ pub async fn issue_list_issue_comment_attachments(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Vec<Attachment>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/comments/{id}/assets"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a comment attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ /// - `attachment`: attachment to upload
+ pub async fn issue_create_issue_comment_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment: Vec<u8>,
+ query: IssueCreateIssueCommentAttachmentQuery,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/assets?{query}"
+ ))
+ .multipart(
+ reqwest::multipart::Form::new().part(
+ "attachment",
+ reqwest::multipart::Part::bytes(attachment)
+ .file_name("file")
+ .mime_str("*/*")
+ .unwrap(),
+ ),
+ )
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a comment attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ /// - `attachment_id`: id of the attachment to get
+ pub async fn issue_get_issue_comment_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a comment attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ /// - `attachment_id`: id of the attachment to delete
+ pub async fn issue_delete_issue_comment_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a comment attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment
+ /// - `attachment_id`: id of the attachment to edit
+ /// - `body`: See [`EditAttachmentOptions`]
+ pub async fn issue_edit_issue_comment_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ body: EditAttachmentOptions,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .patch(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a list of reactions from a comment of an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment to edit
+ pub async fn issue_get_comment_reactions(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Vec<Reaction>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/reactions"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a reaction to a comment of an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment to edit
+ /// - `content`: See [`EditReactionOption`]
+ pub async fn issue_post_comment_reaction(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ content: EditReactionOption,
+ ) -> Result<Reaction, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/reactions"
+ ))
+ .json(&content)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a reaction from a comment of an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the comment to edit
+ /// - `content`: See [`EditReactionOption`]
+ pub async fn issue_delete_comment_reaction(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ content: EditReactionOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/comments/{id}/reactions"
+ ))
+ .json(&content)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's pinned issues
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_pinned_issues(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<Issue>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/pinned"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to get
+ pub async fn issue_get_issue(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/{index}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of issue to delete
+ pub async fn issue_delete(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit an issue. If using deadline only the date will be taken into account, and time of day ignored.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to edit
+ /// - `body`: See [`EditIssueOption`]
+ pub async fn issue_edit_issue(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: EditIssueOption,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/issues/{index}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List issue's attachments
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_list_issue_attachments(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<Vec<Attachment>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/{index}/assets"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create an issue attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `attachment`: attachment to upload
+ pub async fn issue_create_issue_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ attachment: Vec<u8>,
+ query: IssueCreateIssueAttachmentQuery,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/issues/{index}/assets?{query}"
+ ))
+ .multipart(
+ reqwest::multipart::Form::new().part(
+ "attachment",
+ reqwest::multipart::Part::bytes(attachment)
+ .file_name("file")
+ .mime_str("*/*")
+ .unwrap(),
+ ),
+ )
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get an issue attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `attachment_id`: id of the attachment to get
+ pub async fn issue_get_issue_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ attachment_id: u64,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete an issue attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `attachment_id`: id of the attachment to delete
+ pub async fn issue_delete_issue_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ attachment_id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit an issue attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `attachment_id`: id of the attachment to edit
+ /// - `body`: See [`EditAttachmentOptions`]
+ pub async fn issue_edit_issue_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ attachment_id: u64,
+ body: EditAttachmentOptions,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .patch(&format!(
+ "repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List issues that are blocked by this issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_list_blocks(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ query: IssueListBlocksQuery,
+ ) -> Result<Vec<Issue>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/blocks?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Block the issue given in the body by the issue in path
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueMeta`]
+ pub async fn issue_create_issue_blocking(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ body: IssueMeta,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/blocks"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unblock the issue given in the body by the issue in path
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueMeta`]
+ pub async fn issue_remove_issue_blocking(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ body: IssueMeta,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/blocks"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all comments on an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_get_comments(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: IssueGetCommentsQuery,
+ ) -> Result<Vec<Comment>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/comments?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a comment to an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`CreateIssueCommentOption`]
+ pub async fn issue_create_comment(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: CreateIssueCommentOption,
+ ) -> Result<Comment, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/comments"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a comment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: this parameter is ignored
+ /// - `id`: id of comment to delete
+ pub async fn issue_delete_comment_deprecated(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u32,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/{index}/comments/{id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a comment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: this parameter is ignored
+ /// - `id`: id of the comment to edit
+ /// - `body`: See [`EditIssueCommentOption`]
+ pub async fn issue_edit_comment_deprecated(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u32,
+ id: u64,
+ body: EditIssueCommentOption,
+ ) -> Result<Option<Comment>, ForgejoError> {
+ let request = self
+ .patch(&format!(
+ "repos/{owner}/{repo}/issues/{index}/comments/{id}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(Some(response.json().await?)),
+ 204 => Ok(Some(response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Set an issue deadline. If set to null, the deadline is deleted. If using deadline only the date will be taken into account, and time of day ignored.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to create or update a deadline on
+ /// - `body`: See [`EditDeadlineOption`]
+ pub async fn issue_edit_issue_deadline(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: EditDeadlineOption,
+ ) -> Result<IssueDeadline, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/deadline"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an issue's dependencies, i.e all issues that block this issue.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_list_issue_dependencies(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ query: IssueListIssueDependenciesQuery,
+ ) -> Result<Vec<Issue>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/dependencies?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Make the issue in the url depend on the issue in the form.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueMeta`]
+ pub async fn issue_create_issue_dependencies(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ body: IssueMeta,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/dependencies"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove an issue dependency
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueMeta`]
+ pub async fn issue_remove_issue_dependencies(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: &str,
+ body: IssueMeta,
+ ) -> Result<Issue, ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/dependencies"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get an issue's labels
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_get_labels(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<Vec<Label>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Replace an issue's labels
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueLabelsOption`]
+ pub async fn issue_replace_labels(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: IssueLabelsOption,
+ ) -> Result<Vec<Label>, ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a label to an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`IssueLabelsOption`]
+ pub async fn issue_add_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: IssueLabelsOption,
+ ) -> Result<Vec<Label>, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove all labels from an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`DeleteLabelsOption`]
+ pub async fn issue_clear_labels(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: DeleteLabelsOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/labels"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a label from an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `id`: id of the label to remove
+ /// - `body`: See [`DeleteLabelsOption`]
+ pub async fn issue_remove_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ body: DeleteLabelsOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/labels/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Pin an Issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of issue to pin
+ pub async fn pin_issue(&self, owner: &str, repo: &str, index: u64) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/pin"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unpin an Issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of issue to unpin
+ pub async fn unpin_issue(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/pin"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Moves the Pin to the given Position
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of issue
+ /// - `position`: the new position
+ pub async fn move_issue_pin(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ position: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .patch(&format!(
+ "repos/{owner}/{repo}/issues/{index}/pin/{position}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a list reactions of an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_get_issue_reactions(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: IssueGetIssueReactionsQuery,
+ ) -> Result<Vec<Reaction>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/reactions?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a reaction to an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `content`: See [`EditReactionOption`]
+ pub async fn issue_post_issue_reaction(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ content: EditReactionOption,
+ ) -> Result<Reaction, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/reactions"))
+ .json(&content)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a reaction from an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `content`: See [`EditReactionOption`]
+ pub async fn issue_delete_issue_reaction(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ content: EditReactionOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/reactions"))
+ .json(&content)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete an issue's existing stopwatch.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to stop the stopwatch on
+ pub async fn issue_delete_stop_watch(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/{index}/stopwatch/delete"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Start stopwatch on an issue.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to create the stopwatch on
+ pub async fn issue_start_stop_watch(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/issues/{index}/stopwatch/start"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Stop an issue's existing stopwatch.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to stop the stopwatch on
+ pub async fn issue_stop_stop_watch(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/issues/{index}/stopwatch/stop"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get users who subscribed on an issue.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_subscriptions(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: IssueSubscriptionsQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/subscriptions?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if user is subscribed to an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_check_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<WatchInfo, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/subscriptions/check"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Subscribe user to issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `user`: user to subscribe
+ pub async fn issue_add_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ user: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!(
+ "repos/{owner}/{repo}/issues/{index}/subscriptions/{user}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ 201 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unsubscribe user from issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `user`: user witch unsubscribe
+ pub async fn issue_delete_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ user: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/issues/{index}/subscriptions/{user}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ 201 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all comments and events on an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_get_comments_and_timeline(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: IssueGetCommentsAndTimelineQuery,
+ ) -> Result<Vec<TimelineComment>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/timeline?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List an issue's tracked times
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ pub async fn issue_tracked_times(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: IssueTrackedTimesQuery,
+ ) -> Result<Vec<TrackedTime>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/issues/{index}/times?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add tracked time to a issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `body`: See [`AddTimeOption`]
+ pub async fn issue_add_time(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: AddTimeOption,
+ ) -> Result<TrackedTime, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/issues/{index}/times"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Reset a tracked time of an issue
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue to add tracked time to
+ pub async fn issue_reset_time(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/times"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete specific tracked time
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the issue
+ /// - `id`: id of time to delete
+ pub async fn issue_delete_time(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/issues/{index}/times/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's keys
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_keys(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListKeysQuery,
+ ) -> Result<Vec<DeployKey>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/keys?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a key to a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateKeyOption`]
+ pub async fn repo_create_key(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateKeyOption,
+ ) -> Result<DeployKey, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/keys"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a repository's key by id
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the key to get
+ pub async fn repo_get_key(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<DeployKey, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/keys/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a key from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the key to delete
+ pub async fn repo_delete_key(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/keys/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get all of a repository's labels
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn issue_list_labels(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: IssueListLabelsQuery,
+ ) -> Result<Vec<Label>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/labels?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a label
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateLabelOption`]
+ pub async fn issue_create_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateLabelOption,
+ ) -> Result<Label, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/labels"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a single label
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the label to get
+ pub async fn issue_get_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Label, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/labels/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a label
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the label to delete
+ pub async fn issue_delete_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/labels/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a label
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the label to edit
+ /// - `body`: See [`EditLabelOption`]
+ pub async fn issue_edit_label(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ body: EditLabelOption,
+ ) -> Result<Label, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/labels/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get languages and number of bytes of code written
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_languages(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<BTreeMap<String, u64>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/languages"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a file or it's LFS object from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: filepath of the file to get
+ pub async fn repo_get_raw_file_or_lfs(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ query: RepoGetRawFileOrLfsQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/media/{filepath}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get all of a repository's opened milestones
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn issue_get_milestones_list(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: IssueGetMilestonesListQuery,
+ ) -> Result<Vec<Milestone>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/milestones?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a milestone
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateMilestoneOption`]
+ pub async fn issue_create_milestone(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateMilestoneOption,
+ ) -> Result<Milestone, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/milestones"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a milestone
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: the milestone to get, identified by ID and if not available by name
+ pub async fn issue_get_milestone(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ ) -> Result<Milestone, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/milestones/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a milestone
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: the milestone to delete, identified by ID and if not available by name
+ pub async fn issue_delete_milestone(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/milestones/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a milestone
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: the milestone to edit, identified by ID and if not available by name
+ /// - `body`: See [`EditMilestoneOption`]
+ pub async fn issue_edit_milestone(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: &str,
+ body: EditMilestoneOption,
+ ) -> Result<Milestone, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/milestones/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Sync a mirrored repository
+ ///
+ /// - `owner`: owner of the repo to sync
+ /// - `repo`: name of the repo to sync
+ pub async fn repo_mirror_sync(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/mirror-sync"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns if new Issue Pins are allowed
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_new_pin_allowed(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<NewIssuePinsAllowed, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/new_pin_allowed"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List users's notification threads on a specific repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn notify_get_repo_list(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: NotifyGetRepoListQuery,
+ ) -> Result<Vec<NotificationThread>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/notifications?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Mark notification threads as read, pinned or unread on a specific repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn notify_read_repo_list(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: NotifyReadRepoListQuery,
+ ) -> Result<Vec<NotificationThread>, ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/notifications?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 205 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's pull requests
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_pull_requests(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListPullRequestsQuery,
+ ) -> Result<Vec<PullRequest>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreatePullRequestOption`]
+ pub async fn repo_create_pull_request(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreatePullRequestOption,
+ ) -> Result<PullRequest, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/pulls"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's pinned pull requests
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_pinned_pull_requests(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<PullRequest>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls/pinned"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to get
+ pub async fn repo_get_pull_request(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<PullRequest, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls/{index}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a pull request. If using deadline only the date will be taken into account, and time of day ignored.
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to edit
+ /// - `body`: See [`EditPullRequestOption`]
+ pub async fn repo_edit_pull_request(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: EditPullRequestOption,
+ ) -> Result<PullRequest, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/pulls/{index}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a pull request diff or patch
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to get
+ /// - `diffType`: whether the output is diff or patch
+ pub async fn repo_download_pull_diff_or_patch(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ diff_type: &str,
+ query: RepoDownloadPullDiffOrPatchQuery,
+ ) -> Result<String, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/pulls/{index}.{diff_type}?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get commits for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to get
+ pub async fn repo_get_pull_request_commits(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: RepoGetPullRequestCommitsQuery,
+ ) -> Result<(CommitListHeaders, Vec<Commit>), ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/commits?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok((response.headers().try_into()?, response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get changed files for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to get
+ pub async fn repo_get_pull_request_files(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: RepoGetPullRequestFilesQuery,
+ ) -> Result<(ChangedFileListHeaders, Vec<ChangedFile>), ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls/{index}/files?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok((response.headers().try_into()?, response.json().await?)),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if a pull request has been merged
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ pub async fn repo_pull_request_is_merged(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Merge a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to merge
+ /// - `body`: See [`MergePullRequestOption`]
+ pub async fn repo_merge_pull_request(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: MergePullRequestOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Cancel the scheduled auto merge for the given pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to merge
+ pub async fn repo_cancel_scheduled_auto_merge(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/pulls/{index}/merge"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// create review requests for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `body`: See [`PullReviewRequestOptions`]
+ pub async fn repo_create_pull_review_requests(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: PullReviewRequestOptions,
+ ) -> Result<Vec<PullReview>, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/requested_reviewers"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// cancel review requests for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `body`: See [`PullReviewRequestOptions`]
+ pub async fn repo_delete_pull_review_requests(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: PullReviewRequestOptions,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/requested_reviewers"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all reviews for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ pub async fn repo_list_pull_reviews(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: RepoListPullReviewsQuery,
+ ) -> Result<Vec<PullReview>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/reviews?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a review to an pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `body`: See [`CreatePullReviewOptions`]
+ pub async fn repo_create_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ body: CreatePullReviewOptions,
+ ) -> Result<PullReview, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/pulls/{index}/reviews"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a specific review for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ pub async fn repo_get_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ ) -> Result<PullReview, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Submit a pending review to an pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ /// - `body`: See [`SubmitPullReviewOptions`]
+ pub async fn repo_submit_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ body: SubmitPullReviewOptions,
+ ) -> Result<PullReview, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a specific review from a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ pub async fn repo_delete_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/pulls/{index}/reviews/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a specific review for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ pub async fn repo_get_pull_review_comments(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ ) -> Result<Vec<PullReviewComment>, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Dismiss a review for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ /// - `body`: See [`DismissPullReviewOptions`]
+ pub async fn repo_dismiss_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ body: DismissPullReviewOptions,
+ ) -> Result<PullReview, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Cancel to dismiss a review for a pull request
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request
+ /// - `id`: id of the review
+ pub async fn repo_un_dismiss_pull_review(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ id: u64,
+ ) -> Result<PullReview, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/reviews/{id}/undismissals"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Merge PR's baseBranch into headBranch
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `index`: index of the pull request to get
+ pub async fn repo_update_pull_request(
+ &self,
+ owner: &str,
+ repo: &str,
+ index: u64,
+ query: RepoUpdatePullRequestQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/pulls/{index}/update?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get all push mirrors of the repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_push_mirrors(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListPushMirrorsQuery,
+ ) -> Result<Vec<PushMirror>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/push_mirrors?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// add a push mirror to the repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreatePushMirrorOption`]
+ pub async fn repo_add_push_mirror(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreatePushMirrorOption,
+ ) -> Result<PushMirror, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/push_mirrors"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Sync all push mirrored repository
+ ///
+ /// - `owner`: owner of the repo to sync
+ /// - `repo`: name of the repo to sync
+ pub async fn repo_push_mirror_sync(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/push_mirrors-sync"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get push mirror of the repository by remoteName
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `name`: remote name of push mirror
+ pub async fn repo_get_push_mirror_by_remote_name(
+ &self,
+ owner: &str,
+ repo: &str,
+ name: &str,
+ ) -> Result<PushMirror, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/push_mirrors/{name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// deletes a push mirror from a repository by remoteName
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `name`: remote name of the pushMirror
+ pub async fn repo_delete_push_mirror(
+ &self,
+ owner: &str,
+ repo: &str,
+ name: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/push_mirrors/{name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a file from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `filepath`: filepath of the file to get
+ pub async fn repo_get_raw_file(
+ &self,
+ owner: &str,
+ repo: &str,
+ filepath: &str,
+ query: RepoGetRawFileQuery,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/raw/{filepath}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's releases
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_releases(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListReleasesQuery,
+ ) -> Result<Vec<Release>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/releases?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a release
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateReleaseOption`]
+ pub async fn repo_create_release(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateReleaseOption,
+ ) -> Result<Release, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/releases"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Gets the most recent non-prerelease, non-draft release of a repository, sorted by created_at
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_latest_release(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Release, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/releases/latest"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a release by tag name
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `tag`: tag name of the release to get
+ pub async fn repo_get_release_by_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ tag: &str,
+ ) -> Result<Release, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a release by tag name
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `tag`: tag name of the release to delete
+ pub async fn repo_delete_release_by_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ tag: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a release
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release to get
+ pub async fn repo_get_release(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Release, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/releases/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a release
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release to delete
+ pub async fn repo_delete_release(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/releases/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a release
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release to edit
+ /// - `body`: See [`EditReleaseOption`]
+ pub async fn repo_edit_release(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ body: EditReleaseOption,
+ ) -> Result<Release, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/releases/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List release's attachments
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release
+ pub async fn repo_list_release_attachments(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ ) -> Result<Vec<Attachment>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/releases/{id}/assets"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a release attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release
+ /// - `attachment`: attachment to upload
+ pub async fn repo_create_release_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment: Vec<u8>,
+ query: RepoCreateReleaseAttachmentQuery,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .post(&format!(
+ "repos/{owner}/{repo}/releases/{id}/assets?{query}"
+ ))
+ .multipart(
+ reqwest::multipart::Form::new().part(
+ "attachment",
+ reqwest::multipart::Part::bytes(attachment)
+ .file_name("file")
+ .mime_str("*/*")
+ .unwrap(),
+ ),
+ )
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a release attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release
+ /// - `attachment_id`: id of the attachment to get
+ pub async fn repo_get_release_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a release attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release
+ /// - `attachment_id`: id of the attachment to delete
+ pub async fn repo_delete_release_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!(
+ "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a release attachment
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `id`: id of the release
+ /// - `attachment_id`: id of the attachment to edit
+ /// - `body`: See [`EditAttachmentOptions`]
+ pub async fn repo_edit_release_attachment(
+ &self,
+ owner: &str,
+ repo: &str,
+ id: u64,
+ attachment_id: u64,
+ body: EditAttachmentOptions,
+ ) -> Result<Attachment, ForgejoError> {
+ let request = self
+ .patch(&format!(
+ "repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}"
+ ))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Return all users that can be requested to review in this repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_reviewers(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/reviewers"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get signing-key.gpg for given repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_signing_key(&self, owner: &str, repo: &str) -> Result<String, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/signing-key.gpg"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's stargazers
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_stargazers(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListStargazersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/stargazers?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a commit's statuses
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: sha of the commit
+ pub async fn repo_list_statuses(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ query: RepoListStatusesQuery,
+ ) -> Result<Vec<CommitStatus>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/statuses/{sha}?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a commit status
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `sha`: sha of the commit
+ /// - `body`: See [`CreateStatusOption`]
+ pub async fn repo_create_status(
+ &self,
+ owner: &str,
+ repo: &str,
+ sha: &str,
+ body: CreateStatusOption,
+ ) -> Result<CommitStatus, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/statuses/{sha}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's watchers
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_subscribers(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListSubscribersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/subscribers?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if the current user is watching a repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn user_current_check_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<WatchInfo, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/subscription"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Watch a repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn user_current_put_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<WatchInfo, ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/subscription"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unwatch a repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn user_current_delete_subscription(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/subscription"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's tags
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_tags(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListTagsQuery,
+ ) -> Result<Vec<Tag>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/tags?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a new git tag in a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateTagOption`]
+ pub async fn repo_create_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateTagOption,
+ ) -> Result<Tag, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/tags"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get the tag of a repository by tag name
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `tag`: name of tag
+ pub async fn repo_get_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ tag: &str,
+ ) -> Result<Tag, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/tags/{tag}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a repository's tag by name
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `tag`: name of tag to delete
+ pub async fn repo_delete_tag(
+ &self,
+ owner: &str,
+ repo: &str,
+ tag: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/tags/{tag}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repository's teams
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_teams(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Vec<Team>, ForgejoError> {
+ let request = self.get(&format!("repos/{owner}/{repo}/teams")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if a team is assigned to a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `team`: team name
+ pub async fn repo_check_team(
+ &self,
+ owner: &str,
+ repo: &str,
+ team: &str,
+ ) -> Result<Team, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/teams/{team}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a team to a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `team`: team name
+ pub async fn repo_add_team(
+ &self,
+ owner: &str,
+ repo: &str,
+ team: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/teams/{team}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a team from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `team`: team name
+ pub async fn repo_delete_team(
+ &self,
+ owner: &str,
+ repo: &str,
+ team: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/teams/{team}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a repo's tracked times
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_tracked_times(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoTrackedTimesQuery,
+ ) -> Result<Vec<TrackedTime>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/times?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a user's tracked times in a repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `user`: username of user
+ pub async fn user_tracked_times(
+ &self,
+ owner: &str,
+ repo: &str,
+ user: &str,
+ ) -> Result<Vec<TrackedTime>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/times/{user}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get list of topics that a repository has
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_list_topics(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoListTopicsQuery,
+ ) -> Result<TopicName, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/topics?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Replace list of topics for a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`RepoTopicOptions`]
+ pub async fn repo_update_topics(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: RepoTopicOptions,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/topics"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a topic to a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `topic`: name of the topic to add
+ pub async fn repo_add_topic(
+ &self,
+ owner: &str,
+ repo: &str,
+ topic: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("repos/{owner}/{repo}/topics/{topic}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a topic from a repository
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `topic`: name of the topic to delete
+ pub async fn repo_delete_topic(
+ &self,
+ owner: &str,
+ repo: &str,
+ topic: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/topics/{topic}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Transfer a repo ownership
+ ///
+ /// - `owner`: owner of the repo to transfer
+ /// - `repo`: name of the repo to transfer
+ /// - `body`: Transfer Options
+
+ /// See [`TransferRepoOption`]
+ pub async fn repo_transfer(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: TransferRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/transfer"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 202 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Accept a repo transfer
+ ///
+ /// - `owner`: owner of the repo to transfer
+ /// - `repo`: name of the repo to transfer
+ pub async fn accept_repo_transfer(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/transfer/accept"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 202 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Reject a repo transfer
+ ///
+ /// - `owner`: owner of the repo to transfer
+ /// - `repo`: name of the repo to transfer
+ pub async fn reject_repo_transfer(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/transfer/reject"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a wiki page
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `body`: See [`CreateWikiPageOptions`]
+ pub async fn repo_create_wiki_page(
+ &self,
+ owner: &str,
+ repo: &str,
+ body: CreateWikiPageOptions,
+ ) -> Result<WikiPage, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{owner}/{repo}/wiki/new"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a wiki page
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `pageName`: name of the page
+ pub async fn repo_get_wiki_page(
+ &self,
+ owner: &str,
+ repo: &str,
+ page_name: &str,
+ ) -> Result<WikiPage, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a wiki page
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `pageName`: name of the page
+ pub async fn repo_delete_wiki_page(
+ &self,
+ owner: &str,
+ repo: &str,
+ page_name: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a wiki page
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `pageName`: name of the page
+ /// - `body`: See [`CreateWikiPageOptions`]
+ pub async fn repo_edit_wiki_page(
+ &self,
+ owner: &str,
+ repo: &str,
+ page_name: &str,
+ body: CreateWikiPageOptions,
+ ) -> Result<WikiPage, ForgejoError> {
+ let request = self
+ .patch(&format!("repos/{owner}/{repo}/wiki/page/{page_name}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get all wiki pages
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn repo_get_wiki_pages(
+ &self,
+ owner: &str,
+ repo: &str,
+ query: RepoGetWikiPagesQuery,
+ ) -> Result<Vec<WikiPageMetaData>, ForgejoError> {
+ let request = self
+ .get(&format!("repos/{owner}/{repo}/wiki/pages?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get revisions of a wiki page
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ /// - `pageName`: name of the page
+ pub async fn repo_get_wiki_page_revisions(
+ &self,
+ owner: &str,
+ repo: &str,
+ page_name: &str,
+ query: RepoGetWikiPageRevisionsQuery,
+ ) -> Result<WikiCommitList, ForgejoError> {
+ let request = self
+ .get(&format!(
+ "repos/{owner}/{repo}/wiki/revisions/{page_name}?{query}"
+ ))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a repository using a template
+ ///
+ /// - `template_owner`: name of the template repository owner
+ /// - `template_repo`: name of the template repository
+ /// - `body`: See [`GenerateRepoOption`]
+ pub async fn generate_repo(
+ &self,
+ template_owner: &str,
+ template_repo: &str,
+ body: GenerateRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .post(&format!("repos/{template_owner}/{template_repo}/generate"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a repository by id
+ ///
+ /// - `id`: id of the repo to get
+ pub async fn repo_get_by_id(&self, id: u64) -> Result<Repository, ForgejoError> {
+ let request = self.get(&format!("repositories/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get instance's global settings for api
+ pub async fn get_general_api_settings(&self) -> Result<GeneralAPISettings, ForgejoError> {
+ let request = self.get("settings/api").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get instance's global settings for Attachment
+ pub async fn get_general_attachment_settings(
+ &self,
+ ) -> Result<GeneralAttachmentSettings, ForgejoError> {
+ let request = self.get("settings/attachment").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get instance's global settings for repositories
+ pub async fn get_general_repository_settings(
+ &self,
+ ) -> Result<GeneralRepoSettings, ForgejoError> {
+ let request = self.get("settings/repository").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get instance's global settings for ui
+ pub async fn get_general_ui_settings(&self) -> Result<GeneralUISettings, ForgejoError> {
+ let request = self.get("settings/ui").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get default signing-key.gpg
+ pub async fn get_signing_key(&self) -> Result<String, ForgejoError> {
+ let request = self.get("signing-key.gpg").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a team
+ ///
+ /// - `id`: id of the team to get
+ pub async fn org_get_team(&self, id: u64) -> Result<Team, ForgejoError> {
+ let request = self.get(&format!("teams/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a team
+ ///
+ /// - `id`: id of the team to delete
+ pub async fn org_delete_team(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("teams/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Edit a team
+ ///
+ /// - `id`: id of the team to edit
+ /// - `body`: See [`EditTeamOption`]
+ pub async fn org_edit_team(&self, id: u32, body: EditTeamOption) -> Result<Team, ForgejoError> {
+ let request = self.patch(&format!("teams/{id}")).json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a team's activity feeds
+ ///
+ /// - `id`: id of the team
+ pub async fn org_list_team_activity_feeds(
+ &self,
+ id: u64,
+ query: OrgListTeamActivityFeedsQuery,
+ ) -> Result<Vec<Activity>, ForgejoError> {
+ let request = self
+ .get(&format!("teams/{id}/activities/feeds?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a team's members
+ ///
+ /// - `id`: id of the team
+ pub async fn org_list_team_members(
+ &self,
+ id: u64,
+ query: OrgListTeamMembersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self.get(&format!("teams/{id}/members?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a particular member of team
+ ///
+ /// - `id`: id of the team
+ /// - `username`: username of the member to list
+ pub async fn org_list_team_member(
+ &self,
+ id: u64,
+ username: &str,
+ ) -> Result<User, ForgejoError> {
+ let request = self
+ .get(&format!("teams/{id}/members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a team member
+ ///
+ /// - `id`: id of the team
+ /// - `username`: username of the user to add
+ pub async fn org_add_team_member(&self, id: u64, username: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("teams/{id}/members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a team member
+ ///
+ /// - `id`: id of the team
+ /// - `username`: username of the user to remove
+ pub async fn org_remove_team_member(
+ &self,
+ id: u64,
+ username: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("teams/{id}/members/{username}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a team's repos
+ ///
+ /// - `id`: id of the team
+ pub async fn org_list_team_repos(
+ &self,
+ id: u64,
+ query: OrgListTeamReposQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self.get(&format!("teams/{id}/repos?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a particular repo of team
+ ///
+ /// - `id`: id of the team
+ /// - `org`: organization that owns the repo to list
+ /// - `repo`: name of the repo to list
+ pub async fn org_list_team_repo(
+ &self,
+ id: u64,
+ org: &str,
+ repo: &str,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self
+ .get(&format!("teams/{id}/repos/{org}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add a repository to a team
+ ///
+ /// - `id`: id of the team
+ /// - `org`: organization that owns the repo to add
+ /// - `repo`: name of the repo to add
+ pub async fn org_add_team_repository(
+ &self,
+ id: u64,
+ org: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("teams/{id}/repos/{org}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a repository from a team
+ ///
+ /// - `id`: id of the team
+ /// - `org`: organization that owns the repo to remove
+ /// - `repo`: name of the repo to remove
+ pub async fn org_remove_team_repository(
+ &self,
+ id: u64,
+ org: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("teams/{id}/repos/{org}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// search topics via keyword
+ ///
+ pub async fn topic_search(
+ &self,
+ query: TopicSearchQuery,
+ ) -> Result<Vec<TopicResponse>, ForgejoError> {
+ let request = self.get(&format!("topics/search?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get the authenticated user
+ pub async fn user_get_current(&self) -> Result<User, ForgejoError> {
+ let request = self.get("user").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create or Update a secret value in a user scope
+ ///
+ /// - `secretname`: name of the secret
+ /// - `body`: See [`CreateOrUpdateSecretOption`]
+ pub async fn update_user_secret(
+ &self,
+ secretname: &str,
+ body: CreateOrUpdateSecretOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .put(&format!("user/actions/secrets/{secretname}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(()),
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a secret in a user scope
+ ///
+ /// - `secretname`: name of the secret
+ pub async fn delete_user_secret(&self, secretname: &str) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("user/actions/secrets/{secretname}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's oauth2 applications
+ ///
+ pub async fn user_get_oauth2_applications(
+ &self,
+ query: UserGetOAuth2ApplicationsQuery,
+ ) -> Result<Vec<OAuth2Application>, ForgejoError> {
+ let request = self
+ .get(&format!("user/applications/oauth2?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// creates a new OAuth2 application
+ ///
+ /// - `body`: See [`CreateOAuth2ApplicationOptions`]
+ pub async fn user_create_oauth2_application(
+ &self,
+ body: CreateOAuth2ApplicationOptions,
+ ) -> Result<OAuth2Application, ForgejoError> {
+ let request = self.post("user/applications/oauth2").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// get an OAuth2 Application
+ ///
+ /// - `id`: Application ID to be found
+ pub async fn user_get_oauth2_application(
+ &self,
+ id: u64,
+ ) -> Result<OAuth2Application, ForgejoError> {
+ let request = self
+ .get(&format!("user/applications/oauth2/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// delete an OAuth2 Application
+ ///
+ /// - `id`: token to be deleted
+ pub async fn user_delete_oauth2_application(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("user/applications/oauth2/{id}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// update an OAuth2 Application, this includes regenerating the client secret
+ ///
+ /// - `id`: application to be updated
+ /// - `body`: See [`CreateOAuth2ApplicationOptions`]
+ pub async fn user_update_oauth2_application(
+ &self,
+ id: u64,
+ body: CreateOAuth2ApplicationOptions,
+ ) -> Result<OAuth2Application, ForgejoError> {
+ let request = self
+ .patch(&format!("user/applications/oauth2/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update Avatar
+ ///
+ /// - `body`: See [`UpdateUserAvatarOption`]
+ pub async fn user_update_avatar(
+ &self,
+ body: UpdateUserAvatarOption,
+ ) -> Result<(), ForgejoError> {
+ let request = self.post("user/avatar").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete Avatar
+ pub async fn user_delete_avatar(&self) -> Result<(), ForgejoError> {
+ let request = self.delete("user/avatar").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Blocks a user from the doer.
+ ///
+ /// - `username`: username of the user
+ pub async fn user_block_user(&self, username: &str) -> Result<(), ForgejoError> {
+ let request = self.put(&format!("user/block/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's email addresses
+ pub async fn user_list_emails(&self) -> Result<Vec<Email>, ForgejoError> {
+ let request = self.get("user/emails").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Add email addresses
+ ///
+ /// - `body`: See [`CreateEmailOption`]
+ pub async fn user_add_email(
+ &self,
+ body: CreateEmailOption,
+ ) -> Result<Vec<Email>, ForgejoError> {
+ let request = self.post("user/emails").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete email addresses
+ ///
+ /// - `body`: See [`DeleteEmailOption`]
+ pub async fn user_delete_email(&self, body: DeleteEmailOption) -> Result<(), ForgejoError> {
+ let request = self.delete("user/emails").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's followers
+ ///
+ pub async fn user_current_list_followers(
+ &self,
+ query: UserCurrentListFollowersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self.get(&format!("user/followers?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the users that the authenticated user is following
+ ///
+ pub async fn user_current_list_following(
+ &self,
+ query: UserCurrentListFollowingQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self.get(&format!("user/following?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check whether a user is followed by the authenticated user
+ ///
+ /// - `username`: username of followed user
+ pub async fn user_current_check_following(&self, username: &str) -> Result<(), ForgejoError> {
+ let request = self.get(&format!("user/following/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Follow a user
+ ///
+ /// - `username`: username of user to follow
+ pub async fn user_current_put_follow(&self, username: &str) -> Result<(), ForgejoError> {
+ let request = self.put(&format!("user/following/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unfollow a user
+ ///
+ /// - `username`: username of user to unfollow
+ pub async fn user_current_delete_follow(&self, username: &str) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("user/following/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a Token to verify
+ pub async fn get_verification_token(&self) -> Result<String, ForgejoError> {
+ let request = self.get("user/gpg_key_token").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.text().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Verify a GPG key
+ pub async fn user_verify_gpg_key(&self) -> Result<GPGKey, ForgejoError> {
+ let request = self.post("user/gpg_key_verify").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's GPG keys
+ ///
+ pub async fn user_current_list_gpg_keys(
+ &self,
+ query: UserCurrentListGpgKeysQuery,
+ ) -> Result<Vec<GPGKey>, ForgejoError> {
+ let request = self.get(&format!("user/gpg_keys?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a GPG key
+ ///
+ /// - `Form`: See [`CreateGPGKeyOption`]
+ pub async fn user_current_post_gpg_key(
+ &self,
+ form: CreateGPGKeyOption,
+ ) -> Result<GPGKey, ForgejoError> {
+ let request = self.post("user/gpg_keys").json(&form).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a GPG key
+ ///
+ /// - `id`: id of key to get
+ pub async fn user_current_get_gpg_key(&self, id: u64) -> Result<GPGKey, ForgejoError> {
+ let request = self.get(&format!("user/gpg_keys/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Remove a GPG key
+ ///
+ /// - `id`: id of key to delete
+ pub async fn user_current_delete_gpg_key(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("user/gpg_keys/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's webhooks
+ ///
+ pub async fn user_list_hooks(
+ &self,
+ query: UserListHooksQuery,
+ ) -> Result<Vec<Hook>, ForgejoError> {
+ let request = self.get(&format!("user/hooks?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a hook
+ ///
+ /// - `body`: See [`CreateHookOption`]
+ pub async fn user_create_hook(&self, body: CreateHookOption) -> Result<Hook, ForgejoError> {
+ let request = self.post("user/hooks").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a hook
+ ///
+ /// - `id`: id of the hook to get
+ pub async fn user_get_hook(&self, id: u64) -> Result<Hook, ForgejoError> {
+ let request = self.get(&format!("user/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a hook
+ ///
+ /// - `id`: id of the hook to delete
+ pub async fn user_delete_hook(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("user/hooks/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update a hook
+ ///
+ /// - `id`: id of the hook to update
+ /// - `body`: See [`EditHookOption`]
+ pub async fn user_edit_hook(
+ &self,
+ id: u64,
+ body: EditHookOption,
+ ) -> Result<Hook, ForgejoError> {
+ let request = self
+ .patch(&format!("user/hooks/{id}"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's public keys
+ ///
+ pub async fn user_current_list_keys(
+ &self,
+ query: UserCurrentListKeysQuery,
+ ) -> Result<Vec<PublicKey>, ForgejoError> {
+ let request = self.get(&format!("user/keys?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a public key
+ ///
+ /// - `body`: See [`CreateKeyOption`]
+ pub async fn user_current_post_key(
+ &self,
+ body: CreateKeyOption,
+ ) -> Result<PublicKey, ForgejoError> {
+ let request = self.post("user/keys").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a public key
+ ///
+ /// - `id`: id of key to get
+ pub async fn user_current_get_key(&self, id: u64) -> Result<PublicKey, ForgejoError> {
+ let request = self.get(&format!("user/keys/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Delete a public key
+ ///
+ /// - `id`: id of key to delete
+ pub async fn user_current_delete_key(&self, id: u64) -> Result<(), ForgejoError> {
+ let request = self.delete(&format!("user/keys/{id}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's blocked users
+ ///
+ pub async fn user_list_blocked_users(
+ &self,
+ query: UserListBlockedUsersQuery,
+ ) -> Result<Vec<BlockedUser>, ForgejoError> {
+ let request = self.get(&format!("user/list_blocked?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the current user's organizations
+ ///
+ pub async fn org_list_current_user_orgs(
+ &self,
+ query: OrgListCurrentUserOrgsQuery,
+ ) -> Result<Vec<Organization>, ForgejoError> {
+ let request = self.get(&format!("user/orgs?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the repos that the authenticated user owns
+ ///
+ pub async fn user_current_list_repos(
+ &self,
+ query: UserCurrentListReposQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self.get(&format!("user/repos?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create a repository
+ ///
+ /// - `body`: See [`CreateRepoOption`]
+ pub async fn create_current_user_repo(
+ &self,
+ body: CreateRepoOption,
+ ) -> Result<Repository, ForgejoError> {
+ let request = self.post("user/repos").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get user settings
+ pub async fn get_user_settings(&self) -> Result<Vec<UserSettings>, ForgejoError> {
+ let request = self.get("user/settings").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Update user settings
+ ///
+ /// - `body`: See [`UserSettingsOptions`]
+ pub async fn update_user_settings(
+ &self,
+ body: UserSettingsOptions,
+ ) -> Result<Vec<UserSettings>, ForgejoError> {
+ let request = self.patch("user/settings").json(&body).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// The repos that the authenticated user has starred
+ ///
+ pub async fn user_current_list_starred(
+ &self,
+ query: UserCurrentListStarredQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self.get(&format!("user/starred?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Whether the authenticated is starring the repo
+ ///
+ /// - `owner`: owner of the repo
+ /// - `repo`: name of the repo
+ pub async fn user_current_check_starring(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self.get(&format!("user/starred/{owner}/{repo}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Star the given repo
+ ///
+ /// - `owner`: owner of the repo to star
+ /// - `repo`: name of the repo to star
+ pub async fn user_current_put_star(&self, owner: &str, repo: &str) -> Result<(), ForgejoError> {
+ let request = self.put(&format!("user/starred/{owner}/{repo}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unstar the given repo
+ ///
+ /// - `owner`: owner of the repo to unstar
+ /// - `repo`: name of the repo to unstar
+ pub async fn user_current_delete_star(
+ &self,
+ owner: &str,
+ repo: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("user/starred/{owner}/{repo}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get list of all existing stopwatches
+ ///
+ pub async fn user_get_stop_watches(
+ &self,
+ query: UserGetStopWatchesQuery,
+ ) -> Result<Vec<StopWatch>, ForgejoError> {
+ let request = self.get(&format!("user/stopwatches?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List repositories watched by the authenticated user
+ ///
+ pub async fn user_current_list_subscriptions(
+ &self,
+ query: UserCurrentListSubscriptionsQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self.get(&format!("user/subscriptions?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List all the teams a user belongs to
+ ///
+ pub async fn user_list_teams(
+ &self,
+ query: UserListTeamsQuery,
+ ) -> Result<Vec<Team>, ForgejoError> {
+ let request = self.get(&format!("user/teams?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the current user's tracked times
+ ///
+ pub async fn user_current_tracked_times(
+ &self,
+ query: UserCurrentTrackedTimesQuery,
+ ) -> Result<Vec<TrackedTime>, ForgejoError> {
+ let request = self.get(&format!("user/times?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Unblocks a user from the doer.
+ ///
+ /// - `username`: username of the user
+ pub async fn user_unblock_user(&self, username: &str) -> Result<(), ForgejoError> {
+ let request = self.put(&format!("user/unblock/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Search for users
+ ///
+ pub async fn user_search(
+ &self,
+ query: UserSearchQuery,
+ ) -> Result<UserSearchResponse, ForgejoError> {
+ let request = self.get(&format!("users/search?{query}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a user
+ ///
+ /// - `username`: username of user to get
+ pub async fn user_get(&self, username: &str) -> Result<User, ForgejoError> {
+ let request = self.get(&format!("users/{username}")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a user's activity feeds
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_activity_feeds(
+ &self,
+ username: &str,
+ query: UserListActivityFeedsQuery,
+ ) -> Result<Vec<Activity>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/activities/feeds?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the given user's followers
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_followers(
+ &self,
+ username: &str,
+ query: UserListFollowersQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/followers?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the users that the given user is following
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_following(
+ &self,
+ username: &str,
+ query: UserListFollowingQuery,
+ ) -> Result<Vec<User>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/following?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Check if one user is following another user
+ ///
+ /// - `username`: username of following user
+ /// - `target`: username of followed user
+ pub async fn user_check_following(
+ &self,
+ username: &str,
+ target: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/following/{target}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the given user's GPG keys
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_gpg_keys(
+ &self,
+ username: &str,
+ query: UserListGpgKeysQuery,
+ ) -> Result<Vec<GPGKey>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/gpg_keys?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get a user's heatmap
+ ///
+ /// - `username`: username of user to get
+ pub async fn user_get_heatmap_data(
+ &self,
+ username: &str,
+ ) -> Result<Vec<UserHeatmapData>, ForgejoError> {
+ let request = self.get(&format!("users/{username}/heatmap")).build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the given user's public keys
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_keys(
+ &self,
+ username: &str,
+ query: UserListKeysQuery,
+ ) -> Result<Vec<PublicKey>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/keys?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List a user's organizations
+ ///
+ /// - `username`: username of user
+ pub async fn org_list_user_orgs(
+ &self,
+ username: &str,
+ query: OrgListUserOrgsQuery,
+ ) -> Result<Vec<Organization>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/orgs?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Get user permissions in organization
+ ///
+ /// - `username`: username of user
+ /// - `org`: name of the organization
+ pub async fn org_get_user_permissions(
+ &self,
+ username: &str,
+ org: &str,
+ ) -> Result<OrganizationPermissions, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/orgs/{org}/permissions"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the repos owned by the given user
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_repos(
+ &self,
+ username: &str,
+ query: UserListReposQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/repos?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// The repos that the given user has starred
+ ///
+ /// - `username`: username of user
+ pub async fn user_list_starred(
+ &self,
+ username: &str,
+ query: UserListStarredQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/starred?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the repositories watched by a user
+ ///
+ /// - `username`: username of the user
+ pub async fn user_list_subscriptions(
+ &self,
+ username: &str,
+ query: UserListSubscriptionsQuery,
+ ) -> Result<Vec<Repository>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/subscriptions?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// List the authenticated user's access tokens
+ ///
+ /// - `username`: username of user
+ pub async fn user_get_tokens(
+ &self,
+ username: &str,
+ query: UserGetTokensQuery,
+ ) -> Result<Vec<AccessToken>, ForgejoError> {
+ let request = self
+ .get(&format!("users/{username}/tokens?{query}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Create an access token
+ ///
+ /// - `username`: username of user
+ /// - `body`: See [`CreateAccessTokenOption`]
+ pub async fn user_create_token(
+ &self,
+ username: &str,
+ body: CreateAccessTokenOption,
+ ) -> Result<AccessToken, ForgejoError> {
+ let request = self
+ .post(&format!("users/{username}/tokens"))
+ .json(&body)
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 201 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// delete an access token
+ ///
+ /// - `username`: username of user
+ /// - `token`: token to be deleted, identified by ID and if not available by name
+ pub async fn user_delete_access_token(
+ &self,
+ username: &str,
+ token: &str,
+ ) -> Result<(), ForgejoError> {
+ let request = self
+ .delete(&format!("users/{username}/tokens/{token}"))
+ .build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 204 => Ok(()),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+
+ /// Returns the version of the Gitea application
+ pub async fn get_version(&self) -> Result<ServerVersion, ForgejoError> {
+ let request = self.get("version").build()?;
+ let response = self.execute(request).await?;
+ match response.status().as_u16() {
+ 200 => Ok(response.json().await?),
+ _ => Err(ForgejoError::UnexpectedStatusCode(response.status())),
+ }
+ }
+}
diff --git a/src/generated/mod.rs b/src/generated/mod.rs
new file mode 100644
index 0000000..fb6927b
--- /dev/null
+++ b/src/generated/mod.rs
@@ -0,0 +1,2 @@
+pub mod methods;
+pub mod structs;
diff --git a/src/generated/structs.rs b/src/generated/structs.rs
new file mode 100644
index 0000000..7b8b25f
--- /dev/null
+++ b/src/generated/structs.rs
@@ -0,0 +1,5959 @@
+use crate::StructureError;
+use std::collections::BTreeMap;
+/// APIError is an api error with a message
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct APIError {
+ pub message: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct AccessToken {
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub scopes: Option<Vec<String>>,
+ pub sha1: Option<String>,
+ pub token_last_eight: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Activity {
+ pub act_user: Option<User>,
+ pub act_user_id: Option<u64>,
+ pub comment: Option<Comment>,
+ pub comment_id: Option<u64>,
+ pub content: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub is_private: Option<bool>,
+ pub op_type: Option<String>,
+ pub ref_name: Option<String>,
+ pub repo: Option<Repository>,
+ pub repo_id: Option<u64>,
+ pub user_id: Option<u64>,
+}
+
+/// ActivityPub type
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ActivityPub {
+ #[serde(rename = "@context")]
+ pub context: Option<String>,
+}
+
+/// AddCollaboratorOption options when adding a user as a collaborator of a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct AddCollaboratorOption {
+ pub permission: Option<String>,
+}
+
+/// AddTimeOption options for adding time to an issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct AddTimeOption {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ /// time in seconds
+ pub time: u64,
+ /// User who spent the time (optional)
+ pub user_name: Option<String>,
+}
+
+/// AnnotatedTag represents an annotated tag
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct AnnotatedTag {
+ pub message: Option<String>,
+ pub object: Option<AnnotatedTagObject>,
+ pub sha: Option<String>,
+ pub tag: Option<String>,
+ pub tagger: Option<CommitUser>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// AnnotatedTagObject contains meta information of the tag object
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct AnnotatedTagObject {
+ pub sha: Option<String>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// Attachment a generic attachment
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Attachment {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub browser_download_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub download_count: Option<u64>,
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub size: Option<u64>,
+ pub uuid: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct BlockedUser {
+ pub block_id: Option<u64>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+}
+
+/// Branch represents a repository branch
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Branch {
+ pub commit: Option<PayloadCommit>,
+ pub effective_branch_protection_name: Option<String>,
+ pub enable_status_check: Option<bool>,
+ pub name: Option<String>,
+ pub protected: Option<bool>,
+ pub required_approvals: Option<u64>,
+ pub status_check_contexts: Option<Vec<String>>,
+ pub user_can_merge: Option<bool>,
+ pub user_can_push: Option<bool>,
+}
+
+/// BranchProtection represents a branch protection for a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct BranchProtection {
+ pub approvals_whitelist_teams: Option<Vec<String>>,
+ pub approvals_whitelist_username: Option<Vec<String>>,
+ pub block_on_official_review_requests: Option<bool>,
+ pub block_on_outdated_branch: Option<bool>,
+ pub block_on_rejected_reviews: Option<bool>,
+ /// Deprecated: true
+ pub branch_name: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub dismiss_stale_approvals: Option<bool>,
+ pub enable_approvals_whitelist: Option<bool>,
+ pub enable_merge_whitelist: Option<bool>,
+ pub enable_push: Option<bool>,
+ pub enable_push_whitelist: Option<bool>,
+ pub enable_status_check: Option<bool>,
+ pub merge_whitelist_teams: Option<Vec<String>>,
+ pub merge_whitelist_usernames: Option<Vec<String>>,
+ pub protected_file_patterns: Option<String>,
+ pub push_whitelist_deploy_keys: Option<bool>,
+ pub push_whitelist_teams: Option<Vec<String>>,
+ pub push_whitelist_usernames: Option<Vec<String>>,
+ pub require_signed_commits: Option<bool>,
+ pub required_approvals: Option<u64>,
+ pub rule_name: Option<String>,
+ pub status_check_contexts: Option<Vec<String>>,
+ pub unprotected_file_patterns: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// ChangeFileOperation for creating, updating or deleting a file
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ChangeFileOperation {
+ /// new or updated file content, must be base64 encoded
+ pub content: Option<String>,
+ /// old path of the file to move
+ pub from_path: Option<String>,
+ /// indicates what to do with the file
+ pub operation: ChangeFileOperationOperation,
+ /// path to the existing or new file
+ pub path: String,
+ /// sha is the SHA for the file that already exists, required for update or delete
+ pub sha: Option<String>,
+}
+
+/// indicates what to do with the file
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum ChangeFileOperationOperation {
+ #[serde(rename = "create")]
+ Create,
+ #[serde(rename = "update")]
+ Update,
+ #[serde(rename = "delete")]
+ Delete,
+}
+/// ChangeFilesOptions options for creating, updating or deleting multiple 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)
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ChangeFilesOptions {
+ pub author: Option<Identity>,
+ /// branch (optional) to base this file from. if not given, the default branch is used
+ pub branch: Option<String>,
+ pub committer: Option<Identity>,
+ pub dates: Option<CommitDateOptions>,
+ /// list of file operations
+ pub files: Vec<ChangeFileOperation>,
+ /// message (optional) for the commit of this file. if not supplied, a default message will be used
+ pub message: Option<String>,
+ /// new_branch (optional) will make a new branch from `branch` before creating the file
+ pub new_branch: Option<String>,
+ /// Add a Signed-off-by trailer by the committer at the end of the commit log message.
+ pub signoff: Option<bool>,
+}
+
+/// ChangedFile store information about files affected by the pull request
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ChangedFile {
+ pub additions: Option<u64>,
+ pub changes: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub contents_url: Option<url::Url>,
+ pub deletions: Option<u64>,
+ pub filename: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub previous_filename: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub raw_url: Option<url::Url>,
+ pub status: Option<String>,
+}
+
+/// CombinedStatus holds the combined state of several statuses for a single commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CombinedStatus {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub commit_url: Option<url::Url>,
+ pub repository: Option<Repository>,
+ pub sha: Option<String>,
+ pub state: Option<String>,
+ pub statuses: Option<Vec<CommitStatus>>,
+ pub total_count: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// Comment represents a comment on a commit or issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Comment {
+ pub assets: Option<Vec<Attachment>>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub issue_url: Option<url::Url>,
+ pub original_author: Option<String>,
+ pub original_author_id: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub pull_request_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ pub user: Option<User>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Commit {
+ pub author: Option<User>,
+ pub commit: Option<RepoCommit>,
+ pub committer: Option<User>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub files: Option<Vec<CommitAffectedFiles>>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub parents: Option<Vec<CommitMeta>>,
+ pub sha: Option<String>,
+ pub stats: Option<CommitStats>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// CommitAffectedFiles store information about files affected by the commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitAffectedFiles {
+ pub filename: Option<String>,
+ pub status: Option<String>,
+}
+
+/// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitDateOptions {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub author: Option<time::OffsetDateTime>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub committer: Option<time::OffsetDateTime>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitMeta {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub sha: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// CommitStats is statistics for a RepoCommit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitStats {
+ pub additions: Option<u64>,
+ pub deletions: Option<u64>,
+ pub total: Option<u64>,
+}
+
+/// CommitStatus holds a single status of a single Commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitStatus {
+ pub context: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub creator: Option<User>,
+ pub description: Option<String>,
+ pub id: Option<u64>,
+ pub status: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub target_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// CommitStatusState holds the state of a CommitStatus
+///
+/// It can be "pending", "success", "error" and "failure"
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitStatusState {}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CommitUser {
+ pub date: Option<String>,
+ pub email: Option<String>,
+ pub name: Option<String>,
+}
+
+/// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ContentsResponse {
+ #[serde(rename = "_links")]
+ pub links: Option<FileLinksResponse>,
+ /// `content` is populated when `type` is `file`, otherwise null
+ pub content: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub download_url: Option<url::Url>,
+ /// `encoding` is populated when `type` is `file`, otherwise null
+ pub encoding: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub git_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub last_commit_sha: Option<String>,
+ pub name: Option<String>,
+ pub path: Option<String>,
+ pub sha: Option<String>,
+ pub size: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ /// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
+ pub submodule_git_url: Option<url::Url>,
+ /// `target` is populated when `type` is `symlink`, otherwise null
+ pub target: Option<String>,
+ /// `type` will be `file`, `dir`, `symlink`, or `submodule`
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// CreateAccessTokenOption options when create access token
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateAccessTokenOption {
+ pub name: String,
+ pub scopes: Option<Vec<String>>,
+}
+
+/// CreateBranchProtectionOption options for creating a branch protection
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateBranchProtectionOption {
+ pub approvals_whitelist_teams: Option<Vec<String>>,
+ pub approvals_whitelist_username: Option<Vec<String>>,
+ pub block_on_official_review_requests: Option<bool>,
+ pub block_on_outdated_branch: Option<bool>,
+ pub block_on_rejected_reviews: Option<bool>,
+ /// Deprecated: true
+ pub branch_name: Option<String>,
+ pub dismiss_stale_approvals: Option<bool>,
+ pub enable_approvals_whitelist: Option<bool>,
+ pub enable_merge_whitelist: Option<bool>,
+ pub enable_push: Option<bool>,
+ pub enable_push_whitelist: Option<bool>,
+ pub enable_status_check: Option<bool>,
+ pub merge_whitelist_teams: Option<Vec<String>>,
+ pub merge_whitelist_usernames: Option<Vec<String>>,
+ pub protected_file_patterns: Option<String>,
+ pub push_whitelist_deploy_keys: Option<bool>,
+ pub push_whitelist_teams: Option<Vec<String>>,
+ pub push_whitelist_usernames: Option<Vec<String>>,
+ pub require_signed_commits: Option<bool>,
+ pub required_approvals: Option<u64>,
+ pub rule_name: Option<String>,
+ pub status_check_contexts: Option<Vec<String>>,
+ pub unprotected_file_patterns: Option<String>,
+}
+
+/// CreateBranchRepoOption options when creating a branch in a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateBranchRepoOption {
+ /// Name of the branch to create
+ pub new_branch_name: String,
+ /// Deprecated: true
+ ///
+ /// Name of the old branch to create from
+ pub old_branch_name: Option<String>,
+ /// Name of the old branch/tag/commit to create from
+ pub old_ref_name: Option<String>,
+}
+
+/// CreateEmailOption options when creating email addresses
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateEmailOption {
+ /// email addresses to add
+ pub emails: Option<Vec<String>>,
+}
+
+/// 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)
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateFileOptions {
+ pub author: Option<Identity>,
+ /// branch (optional) to base this file from. if not given, the default branch is used
+ pub branch: Option<String>,
+ pub committer: Option<Identity>,
+ /// content must be base64 encoded
+ pub content: String,
+ pub dates: Option<CommitDateOptions>,
+ /// message (optional) for the commit of this file. if not supplied, a default message will be used
+ pub message: Option<String>,
+ /// new_branch (optional) will make a new branch from `branch` before creating the file
+ pub new_branch: Option<String>,
+ /// Add a Signed-off-by trailer by the committer at the end of the commit log message.
+ pub signoff: Option<bool>,
+}
+
+/// CreateForkOption options for creating a fork
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateForkOption {
+ /// name of the forked repository
+ pub name: Option<String>,
+ /// organization name, if forking into an organization
+ pub organization: Option<String>,
+}
+
+/// CreateGPGKeyOption options create user GPG key
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateGPGKeyOption {
+ /// An armored GPG key to add
+ pub armored_public_key: String,
+ pub armored_signature: Option<String>,
+}
+
+/// CreateHookOption options when create a hook
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateHookOption {
+ pub active: Option<bool>,
+ pub authorization_header: Option<String>,
+ pub branch_filter: Option<String>,
+ pub config: CreateHookOptionConfig,
+ pub events: Option<Vec<String>>,
+ #[serde(rename = "type")]
+ pub r#type: CreateHookOptionType,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum CreateHookOptionType {
+ #[serde(rename = "forgejo")]
+ Forgejo,
+ #[serde(rename = "dingtalk")]
+ Dingtalk,
+ #[serde(rename = "discord")]
+ Discord,
+ #[serde(rename = "gitea")]
+ Gitea,
+ #[serde(rename = "gogs")]
+ Gogs,
+ #[serde(rename = "msteams")]
+ Msteams,
+ #[serde(rename = "slack")]
+ Slack,
+ #[serde(rename = "telegram")]
+ Telegram,
+ #[serde(rename = "feishu")]
+ Feishu,
+ #[serde(rename = "wechatwork")]
+ Wechatwork,
+ #[serde(rename = "packagist")]
+ Packagist,
+}
+/// CreateHookOptionConfig has all config options in it
+///
+/// required are "content_type" and "url" Required
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateHookOptionConfig {
+ #[serde(flatten)]
+ pub additional: BTreeMap<String, String>,
+}
+
+/// CreateIssueCommentOption options for creating a comment on an issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateIssueCommentOption {
+ pub body: String,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// CreateIssueOption options to create one issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateIssueOption {
+ /// deprecated
+ pub assignee: Option<String>,
+ pub assignees: Option<Vec<String>>,
+ pub body: Option<String>,
+ pub closed: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ /// list of label ids
+ pub labels: Option<Vec<u64>>,
+ /// milestone id
+ pub milestone: Option<u64>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ pub title: String,
+}
+
+/// CreateKeyOption options when creating a key
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateKeyOption {
+ /// An armored SSH key to add
+ pub key: String,
+ /// Describe if the key has only read access or read/write
+ pub read_only: Option<bool>,
+ /// Title of the key to add
+ pub title: String,
+}
+
+/// CreateLabelOption options for creating a label
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateLabelOption {
+ pub color: String,
+ pub description: Option<String>,
+ pub exclusive: Option<bool>,
+ pub is_archived: Option<bool>,
+ pub name: String,
+}
+
+/// CreateMilestoneOption options for creating a milestone
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateMilestoneOption {
+ pub description: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_on: Option<time::OffsetDateTime>,
+ pub state: Option<CreateMilestoneOptionState>,
+ pub title: Option<String>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum CreateMilestoneOptionState {
+ #[serde(rename = "open")]
+ Open,
+ #[serde(rename = "closed")]
+ Closed,
+}
+/// CreateOAuth2ApplicationOptions holds options to create an oauth2 application
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateOAuth2ApplicationOptions {
+ pub confidential_client: Option<bool>,
+ pub name: Option<String>,
+ pub redirect_uris: Option<Vec<String>>,
+}
+
+/// CreateOrUpdateSecretOption options when creating or updating secret
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateOrUpdateSecretOption {
+ /// Data of the secret to update
+ pub data: String,
+}
+
+/// CreateOrgOption options for creating an organization
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateOrgOption {
+ pub description: Option<String>,
+ pub email: Option<String>,
+ pub full_name: Option<String>,
+ pub location: Option<String>,
+ pub repo_admin_change_team_access: Option<bool>,
+ pub username: String,
+ /// possible values are `public` (default), `limited` or `private`
+ pub visibility: Option<CreateOrgOptionVisibility>,
+ pub website: Option<String>,
+}
+
+/// possible values are `public` (default), `limited` or `private`
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum CreateOrgOptionVisibility {
+ #[serde(rename = "public")]
+ Public,
+ #[serde(rename = "limited")]
+ Limited,
+ #[serde(rename = "private")]
+ Private,
+}
+/// CreatePullRequestOption options when creating a pull request
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreatePullRequestOption {
+ pub assignee: Option<String>,
+ pub assignees: Option<Vec<String>>,
+ pub base: Option<String>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ pub head: Option<String>,
+ pub labels: Option<Vec<u64>>,
+ pub milestone: Option<u64>,
+ pub title: Option<String>,
+}
+
+/// CreatePullReviewComment represent a review comment for creation api
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreatePullReviewComment {
+ pub body: Option<String>,
+ /// if comment to new file line or 0
+ pub new_position: Option<u64>,
+ /// if comment to old file line or 0
+ pub old_position: Option<u64>,
+ /// the tree path
+ pub path: Option<String>,
+}
+
+/// CreatePullReviewOptions are options to create a pull review
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreatePullReviewOptions {
+ pub body: Option<String>,
+ pub comments: Option<Vec<CreatePullReviewComment>>,
+ pub commit_id: Option<String>,
+ pub event: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreatePushMirrorOption {
+ pub interval: Option<String>,
+ pub remote_address: Option<String>,
+ pub remote_password: Option<String>,
+ pub remote_username: Option<String>,
+ pub sync_on_commit: Option<bool>,
+}
+
+/// CreateReleaseOption options when creating a release
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateReleaseOption {
+ pub body: Option<String>,
+ pub draft: Option<bool>,
+ pub name: Option<String>,
+ pub prerelease: Option<bool>,
+ pub tag_name: String,
+ pub target_commitish: Option<String>,
+}
+
+/// CreateRepoOption options when creating repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateRepoOption {
+ /// Whether the repository should be auto-initialized?
+ pub auto_init: Option<bool>,
+ /// DefaultBranch of the repository (used when initializes and in template)
+ pub default_branch: Option<String>,
+ /// Description of the repository to create
+ pub description: Option<String>,
+ /// Gitignores to use
+ pub gitignores: Option<String>,
+ /// Label-Set to use
+ pub issue_labels: Option<String>,
+ /// License to use
+ pub license: Option<String>,
+ /// Name of the repository to create
+ pub name: String,
+ /// Whether the repository is private
+ pub private: Option<bool>,
+ /// Readme of the repository to create
+ pub readme: Option<String>,
+ /// Whether the repository is template
+ pub template: Option<bool>,
+ /// TrustModel of the repository
+ pub trust_model: Option<CreateRepoOptionTrustModel>,
+}
+
+/// TrustModel of the repository
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum CreateRepoOptionTrustModel {
+ #[serde(rename = "default")]
+ Default,
+ #[serde(rename = "collaborator")]
+ Collaborator,
+ #[serde(rename = "committer")]
+ Committer,
+ #[serde(rename = "collaboratorcommitter")]
+ Collaboratorcommitter,
+}
+/// CreateStatusOption holds the information needed to create a new CommitStatus for a Commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateStatusOption {
+ pub context: Option<String>,
+ pub description: Option<String>,
+ pub state: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub target_url: Option<url::Url>,
+}
+
+/// CreateTagOption options when creating a tag
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateTagOption {
+ pub message: Option<String>,
+ pub tag_name: String,
+ pub target: Option<String>,
+}
+
+/// CreateTeamOption options for creating a team
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateTeamOption {
+ pub can_create_org_repo: Option<bool>,
+ pub description: Option<String>,
+ pub includes_all_repositories: Option<bool>,
+ pub name: String,
+ pub permission: Option<CreateTeamOptionPermission>,
+ pub units: Option<Vec<String>>,
+ pub units_map: Option<BTreeMap<String, String>>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum CreateTeamOptionPermission {
+ #[serde(rename = "read")]
+ Read,
+ #[serde(rename = "write")]
+ Write,
+ #[serde(rename = "admin")]
+ Admin,
+}
+/// CreateUserOption create user options
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateUserOption {
+ #[serde(with = "time::serde::rfc3339::option")]
+ /// For explicitly setting the user creation timestamp. Useful when users are
+ ///
+ /// migrated from other systems. When omitted, the user's creation timestamp
+ ///
+ /// will be set to "now".
+ pub created_at: Option<time::OffsetDateTime>,
+ pub email: String,
+ pub full_name: Option<String>,
+ pub login_name: Option<String>,
+ pub must_change_password: Option<bool>,
+ pub password: Option<String>,
+ pub restricted: Option<bool>,
+ pub send_notify: Option<bool>,
+ pub source_id: Option<u64>,
+ pub username: String,
+ pub visibility: Option<String>,
+}
+
+/// CreateWikiPageOptions form for creating wiki
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct CreateWikiPageOptions {
+ /// content must be base64 encoded
+ pub content_base64: Option<String>,
+ /// optional commit message summarizing the change
+ pub message: Option<String>,
+ /// page title. leave empty to keep unchanged
+ pub title: Option<String>,
+}
+
+/// Cron represents a Cron task
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Cron {
+ pub exec_times: Option<u64>,
+ pub name: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub next: Option<time::OffsetDateTime>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub prev: Option<time::OffsetDateTime>,
+ pub schedule: Option<String>,
+}
+
+/// DeleteEmailOption options when deleting email addresses
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct DeleteEmailOption {
+ /// email addresses to delete
+ pub emails: Option<Vec<String>>,
+}
+
+/// DeleteFileOptions options for deleting files (used for other File structs below)
+///
+/// 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)
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct DeleteFileOptions {
+ pub author: Option<Identity>,
+ /// branch (optional) to base this file from. if not given, the default branch is used
+ pub branch: Option<String>,
+ pub committer: Option<Identity>,
+ pub dates: Option<CommitDateOptions>,
+ /// message (optional) for the commit of this file. if not supplied, a default message will be used
+ pub message: Option<String>,
+ /// new_branch (optional) will make a new branch from `branch` before creating the file
+ pub new_branch: Option<String>,
+ /// sha is the SHA for the file that already exists
+ pub sha: String,
+ /// Add a Signed-off-by trailer by the committer at the end of the commit log message.
+ pub signoff: Option<bool>,
+}
+
+/// DeleteLabelOption options for deleting a label
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct DeleteLabelsOption {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// DeployKey a deploy key
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct DeployKey {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub fingerprint: Option<String>,
+ pub id: Option<u64>,
+ pub key: Option<String>,
+ pub key_id: Option<u64>,
+ pub read_only: Option<bool>,
+ pub repository: Option<Repository>,
+ pub title: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// DismissPullReviewOptions are options to dismiss a pull review
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct DismissPullReviewOptions {
+ pub message: Option<String>,
+ pub priors: Option<bool>,
+}
+
+/// EditAttachmentOptions options for editing attachments
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditAttachmentOptions {
+ pub name: Option<String>,
+}
+
+/// EditBranchProtectionOption options for editing a branch protection
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditBranchProtectionOption {
+ pub approvals_whitelist_teams: Option<Vec<String>>,
+ pub approvals_whitelist_username: Option<Vec<String>>,
+ pub block_on_official_review_requests: Option<bool>,
+ pub block_on_outdated_branch: Option<bool>,
+ pub block_on_rejected_reviews: Option<bool>,
+ pub dismiss_stale_approvals: Option<bool>,
+ pub enable_approvals_whitelist: Option<bool>,
+ pub enable_merge_whitelist: Option<bool>,
+ pub enable_push: Option<bool>,
+ pub enable_push_whitelist: Option<bool>,
+ pub enable_status_check: Option<bool>,
+ pub merge_whitelist_teams: Option<Vec<String>>,
+ pub merge_whitelist_usernames: Option<Vec<String>>,
+ pub protected_file_patterns: Option<String>,
+ pub push_whitelist_deploy_keys: Option<bool>,
+ pub push_whitelist_teams: Option<Vec<String>>,
+ pub push_whitelist_usernames: Option<Vec<String>>,
+ pub require_signed_commits: Option<bool>,
+ pub required_approvals: Option<u64>,
+ pub status_check_contexts: Option<Vec<String>>,
+ pub unprotected_file_patterns: Option<String>,
+}
+
+/// EditDeadlineOption options for creating a deadline
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditDeadlineOption {
+ #[serde(with = "time::serde::rfc3339")]
+ pub due_date: time::OffsetDateTime,
+}
+
+/// EditGitHookOption options when modifying one Git hook
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditGitHookOption {
+ pub content: Option<String>,
+}
+
+/// EditHookOption options when modify one hook
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditHookOption {
+ pub active: Option<bool>,
+ pub authorization_header: Option<String>,
+ pub branch_filter: Option<String>,
+ pub config: Option<BTreeMap<String, String>>,
+ pub events: Option<Vec<String>>,
+}
+
+/// EditIssueCommentOption options for editing a comment
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditIssueCommentOption {
+ pub body: String,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// EditIssueOption options for editing an issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditIssueOption {
+ /// deprecated
+ pub assignee: Option<String>,
+ pub assignees: Option<Vec<String>>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ pub milestone: Option<u64>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ pub unset_due_date: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// EditLabelOption options for editing a label
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditLabelOption {
+ pub color: Option<String>,
+ pub description: Option<String>,
+ pub exclusive: Option<bool>,
+ pub is_archived: Option<bool>,
+ pub name: Option<String>,
+}
+
+/// EditMilestoneOption options for editing a milestone
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditMilestoneOption {
+ pub description: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_on: Option<time::OffsetDateTime>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+}
+
+/// EditOrgOption options for editing an organization
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditOrgOption {
+ pub description: Option<String>,
+ pub email: Option<String>,
+ pub full_name: Option<String>,
+ pub location: Option<String>,
+ pub repo_admin_change_team_access: Option<bool>,
+ /// possible values are `public`, `limited` or `private`
+ pub visibility: Option<EditOrgOptionVisibility>,
+ pub website: Option<String>,
+}
+
+/// possible values are `public`, `limited` or `private`
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum EditOrgOptionVisibility {
+ #[serde(rename = "public")]
+ Public,
+ #[serde(rename = "limited")]
+ Limited,
+ #[serde(rename = "private")]
+ Private,
+}
+/// EditPullRequestOption options when modify pull request
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditPullRequestOption {
+ pub allow_maintainer_edit: Option<bool>,
+ pub assignee: Option<String>,
+ pub assignees: Option<Vec<String>>,
+ pub base: Option<String>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ pub labels: Option<Vec<u64>>,
+ pub milestone: Option<u64>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ pub unset_due_date: Option<bool>,
+}
+
+/// EditReactionOption contain the reaction type
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditReactionOption {
+ pub content: Option<String>,
+}
+
+/// EditReleaseOption options when editing a release
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditReleaseOption {
+ pub body: Option<String>,
+ pub draft: Option<bool>,
+ pub name: Option<String>,
+ pub prerelease: Option<bool>,
+ pub tag_name: Option<String>,
+ pub target_commitish: Option<String>,
+}
+
+/// EditRepoOption options when editing a repository's properties
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditRepoOption {
+ /// either `true` to allow mark pr as merged manually, or `false` to prevent it.
+ pub allow_manual_merge: Option<bool>,
+ /// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.
+ pub allow_merge_commits: Option<bool>,
+ /// either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.
+ pub allow_rebase: Option<bool>,
+ /// either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits.
+ pub allow_rebase_explicit: Option<bool>,
+ /// either `true` to allow updating pull request branch by rebase, or `false` to prevent it.
+ pub allow_rebase_update: Option<bool>,
+ /// either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.
+ pub allow_squash_merge: Option<bool>,
+ /// set to `true` to archive this repository.
+ pub archived: Option<bool>,
+ /// either `true` to enable AutodetectManualMerge, or `false` to prevent it. Note: In some special cases, misjudgments can occur.
+ pub autodetect_manual_merge: Option<bool>,
+ /// set to `true` to allow edits from maintainers by default
+ pub default_allow_maintainer_edit: Option<bool>,
+ /// sets the default branch for this repository.
+ pub default_branch: Option<String>,
+ /// set to `true` to delete pr branch after merge by default
+ pub default_delete_branch_after_merge: Option<bool>,
+ /// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash".
+ pub default_merge_style: Option<String>,
+ /// a short description of the repository.
+ pub description: Option<String>,
+ /// enable prune - remove obsolete remote-tracking references
+ pub enable_prune: Option<bool>,
+ pub external_tracker: Option<ExternalTracker>,
+ pub external_wiki: Option<ExternalWiki>,
+ /// either `true` to enable actions unit, or `false` to disable them.
+ pub has_actions: Option<bool>,
+ /// either `true` to enable issues for this repository or `false` to disable them.
+ pub has_issues: Option<bool>,
+ /// either `true` to enable packages unit, or `false` to disable them.
+ pub has_packages: Option<bool>,
+ /// either `true` to enable project unit, or `false` to disable them.
+ pub has_projects: Option<bool>,
+ /// either `true` to allow pull requests, or `false` to prevent pull request.
+ pub has_pull_requests: Option<bool>,
+ /// either `true` to enable releases unit, or `false` to disable them.
+ pub has_releases: Option<bool>,
+ /// either `true` to enable the wiki for this repository or `false` to disable it.
+ pub has_wiki: Option<bool>,
+ /// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace.
+ pub ignore_whitespace_conflicts: Option<bool>,
+ pub internal_tracker: Option<InternalTracker>,
+ /// set to a string like `8h30m0s` to set the mirror interval time
+ pub mirror_interval: Option<String>,
+ /// name of the repository
+ pub name: Option<String>,
+ /// 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.
+ pub private: Option<bool>,
+ /// either `true` to make this repository a template or `false` to make it a normal repository
+ pub template: Option<bool>,
+ /// a URL with more information about the repository.
+ pub website: Option<String>,
+}
+
+/// EditTeamOption options for editing a team
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditTeamOption {
+ pub can_create_org_repo: Option<bool>,
+ pub description: Option<String>,
+ pub includes_all_repositories: Option<bool>,
+ pub name: String,
+ pub permission: Option<EditTeamOptionPermission>,
+ pub units: Option<Vec<String>>,
+ pub units_map: Option<BTreeMap<String, String>>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum EditTeamOptionPermission {
+ #[serde(rename = "read")]
+ Read,
+ #[serde(rename = "write")]
+ Write,
+ #[serde(rename = "admin")]
+ Admin,
+}
+/// EditUserOption edit user options
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct EditUserOption {
+ pub active: Option<bool>,
+ pub admin: Option<bool>,
+ pub allow_create_organization: Option<bool>,
+ pub allow_git_hook: Option<bool>,
+ pub allow_import_local: Option<bool>,
+ pub description: Option<String>,
+ pub email: Option<String>,
+ pub full_name: Option<String>,
+ pub location: Option<String>,
+ pub login_name: String,
+ pub max_repo_creation: Option<u64>,
+ pub must_change_password: Option<bool>,
+ pub password: Option<String>,
+ pub prohibit_login: Option<bool>,
+ pub restricted: Option<bool>,
+ pub source_id: u64,
+ pub visibility: Option<String>,
+ pub website: Option<String>,
+}
+
+/// Email an email address belonging to a user
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Email {
+ pub email: Option<String>,
+ pub primary: Option<bool>,
+ pub user_id: Option<u64>,
+ pub username: Option<String>,
+ pub verified: Option<bool>,
+}
+
+/// ExternalTracker represents settings for external tracker
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+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: Option<String>,
+ /// External Issue Tracker issue regular expression
+ pub external_tracker_regexp_pattern: Option<String>,
+ /// External Issue Tracker Number Format, either `numeric`, `alphanumeric`, or `regexp`
+ pub external_tracker_style: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ /// URL of external issue tracker.
+ pub external_tracker_url: Option<url::Url>,
+}
+
+/// ExternalWiki represents setting for external wiki
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ExternalWiki {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ /// URL of external wiki.
+ pub external_wiki_url: Option<url::Url>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct FileCommitResponse {
+ pub author: Option<CommitUser>,
+ pub committer: Option<CommitUser>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub message: Option<String>,
+ pub parents: Option<Vec<CommitMeta>>,
+ pub sha: Option<String>,
+ pub tree: Option<CommitMeta>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// FileDeleteResponse contains information about a repo's file that was deleted
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct FileDeleteResponse {
+ pub commit: Option<FileCommitResponse>,
+ pub content: Option<serde_json::Value>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// FileLinksResponse contains the links for a repo's file
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct FileLinksResponse {
+ pub git: Option<String>,
+ pub html: Option<String>,
+ #[serde(rename = "self")]
+ pub this: Option<String>,
+}
+
+/// FileResponse contains information about a repo's file
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct FileResponse {
+ pub commit: Option<FileCommitResponse>,
+ pub content: Option<ContentsResponse>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// FilesResponse contains information about multiple files from a repo
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct FilesResponse {
+ pub commit: Option<FileCommitResponse>,
+ pub files: Option<Vec<ContentsResponse>>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// GPGKey a user GPG key to sign commit and tag in repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GPGKey {
+ pub can_certify: Option<bool>,
+ pub can_encrypt_comms: Option<bool>,
+ pub can_encrypt_storage: Option<bool>,
+ pub can_sign: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub emails: Option<Vec<GPGKeyEmail>>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub expires_at: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub key_id: Option<String>,
+ pub primary_key_id: Option<String>,
+ pub public_key: Option<String>,
+ pub subkeys: Option<Vec<GPGKey>>,
+ pub verified: Option<bool>,
+}
+
+/// GPGKeyEmail an email attached to a GPGKey
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GPGKeyEmail {
+ pub email: Option<String>,
+ pub verified: Option<bool>,
+}
+
+/// GeneralAPISettings contains global api settings exposed by it
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GeneralAPISettings {
+ pub default_git_trees_per_page: Option<u64>,
+ pub default_max_blob_size: Option<u64>,
+ pub default_paging_num: Option<u64>,
+ pub max_response_items: Option<u64>,
+}
+
+/// GeneralAttachmentSettings contains global Attachment settings exposed by API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GeneralAttachmentSettings {
+ pub allowed_types: Option<String>,
+ pub enabled: Option<bool>,
+ pub max_files: Option<u64>,
+ pub max_size: Option<u64>,
+}
+
+/// GeneralRepoSettings contains global repository settings exposed by API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GeneralRepoSettings {
+ pub http_git_disabled: Option<bool>,
+ pub lfs_disabled: Option<bool>,
+ pub migrations_disabled: Option<bool>,
+ pub mirrors_disabled: Option<bool>,
+ pub stars_disabled: Option<bool>,
+ pub time_tracking_disabled: Option<bool>,
+}
+
+/// GeneralUISettings contains global ui settings exposed by API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GeneralUISettings {
+ pub allowed_reactions: Option<Vec<String>>,
+ pub custom_emojis: Option<Vec<String>>,
+ pub default_theme: Option<String>,
+}
+
+/// GenerateRepoOption options when creating repository using a template
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GenerateRepoOption {
+ /// include avatar of the template repo
+ pub avatar: Option<bool>,
+ /// Default branch of the new repository
+ pub default_branch: Option<String>,
+ /// Description of the repository to create
+ pub description: Option<String>,
+ /// include git content of default branch in template repo
+ pub git_content: Option<bool>,
+ /// include git hooks in template repo
+ pub git_hooks: Option<bool>,
+ /// include labels in template repo
+ pub labels: Option<bool>,
+ /// Name of the repository to create
+ pub name: String,
+ /// The organization or person who will own the new repository
+ pub owner: String,
+ /// Whether the repository is private
+ pub private: Option<bool>,
+ /// include protected branches in template repo
+ pub protected_branch: Option<bool>,
+ /// include topics in template repo
+ pub topics: Option<bool>,
+ /// include webhooks in template repo
+ pub webhooks: Option<bool>,
+}
+
+/// GitBlobResponse represents a git blob
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitBlobResponse {
+ pub content: Option<String>,
+ pub encoding: Option<String>,
+ pub sha: Option<String>,
+ pub size: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// GitEntry represents a git tree
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitEntry {
+ pub mode: Option<String>,
+ pub path: Option<String>,
+ pub sha: Option<String>,
+ pub size: Option<u64>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// GitHook represents a Git repository hook
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitHook {
+ pub content: Option<String>,
+ pub is_active: Option<bool>,
+ pub name: Option<String>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitObject {
+ pub sha: Option<String>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// GitTreeResponse returns a git tree
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitTreeResponse {
+ pub page: Option<u64>,
+ pub sha: Option<String>,
+ pub total_count: Option<u64>,
+ pub tree: Option<Vec<GitEntry>>,
+ pub truncated: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// GitignoreTemplateInfo name and text of a gitignore template
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct GitignoreTemplateInfo {
+ pub name: Option<String>,
+ pub source: Option<String>,
+}
+
+/// Hook a hook is a web hook when one repository changed
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Hook {
+ pub active: Option<bool>,
+ pub authorization_header: Option<String>,
+ pub branch_filter: Option<String>,
+ pub config: Option<BTreeMap<String, String>>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub events: Option<Vec<String>>,
+ pub id: Option<u64>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// Identity for a person's identity like an author or committer
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Identity {
+ pub email: Option<String>,
+ pub name: Option<String>,
+}
+
+/// InternalTracker represents settings for internal tracker
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct InternalTracker {
+ /// Let only contributors track time (Built-in issue tracker)
+ pub allow_only_contributors_to_track_time: Option<bool>,
+ /// Enable dependencies for issues and pull requests (Built-in issue tracker)
+ pub enable_issue_dependencies: Option<bool>,
+ /// Enable time tracking (Built-in issue tracker)
+ pub enable_time_tracker: Option<bool>,
+}
+
+/// Issue represents an issue in a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Issue {
+ pub assets: Option<Vec<Attachment>>,
+ pub assignee: Option<User>,
+ pub assignees: Option<Vec<User>>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub closed_at: Option<time::OffsetDateTime>,
+ pub comments: Option<u64>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub is_locked: Option<bool>,
+ pub labels: Option<Vec<Label>>,
+ pub milestone: Option<Milestone>,
+ pub number: Option<u64>,
+ pub original_author: Option<String>,
+ pub original_author_id: Option<u64>,
+ pub pin_order: Option<u64>,
+ pub pull_request: Option<PullRequestMeta>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ pub repository: Option<RepositoryMeta>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub user: Option<User>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueConfig {
+ pub blank_issues_enabled: Option<bool>,
+ pub contact_links: Option<Vec<IssueConfigContactLink>>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueConfigContactLink {
+ pub about: Option<String>,
+ pub name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueConfigValidation {
+ pub message: Option<String>,
+ pub valid: Option<bool>,
+}
+
+/// IssueDeadline represents an issue deadline
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueDeadline {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+}
+
+/// IssueFormField represents a form field
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueFormField {
+ pub attributes: Option<BTreeMap<String, serde_json::Value>>,
+ pub id: Option<String>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ pub validations: Option<BTreeMap<String, serde_json::Value>>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueFormFieldType {}
+
+/// IssueLabelsOption a collection of labels
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueLabelsOption {
+ /// list of label IDs
+ pub labels: Option<Vec<u64>>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// IssueMeta basic issue information
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueMeta {
+ pub index: Option<u64>,
+ pub owner: Option<String>,
+ pub repo: Option<String>,
+}
+
+/// IssueTemplate represents an issue template for a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct IssueTemplate {
+ pub about: Option<String>,
+ pub body: Option<Vec<IssueFormField>>,
+ pub content: Option<String>,
+ pub file_name: Option<String>,
+ pub labels: Option<Vec<String>>,
+ pub name: Option<String>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ pub title: Option<String>,
+}
+
+/// Label a label to an issue or a pr
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Label {
+ pub color: Option<String>,
+ pub description: Option<String>,
+ pub exclusive: Option<bool>,
+ pub id: Option<u64>,
+ pub is_archived: Option<bool>,
+ pub name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// LabelTemplate info of a Label template
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct LabelTemplate {
+ pub color: Option<String>,
+ pub description: Option<String>,
+ pub exclusive: Option<bool>,
+ pub name: Option<String>,
+}
+
+/// LicensesInfo contains information about a License
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct LicenseTemplateInfo {
+ pub body: Option<String>,
+ pub implementation: Option<String>,
+ pub key: Option<String>,
+ pub name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// LicensesListEntry is used for the API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct LicensesTemplateListEntry {
+ pub key: Option<String>,
+ pub name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// MarkdownOption markdown options
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct MarkdownOption {
+ /// Context to render
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Context")]
+ pub context: Option<String>,
+ /// Mode to render (comment, gfm, markdown)
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Mode")]
+ pub mode: Option<String>,
+ /// Text markdown to render
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Text")]
+ pub text: Option<String>,
+ /// Is it a wiki page ?
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Wiki")]
+ pub wiki: Option<bool>,
+}
+
+/// MarkupOption markup options
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct MarkupOption {
+ /// Context to render
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Context")]
+ pub context: Option<String>,
+ /// File path for detecting extension in file mode
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "FilePath")]
+ pub file_path: Option<String>,
+ /// Mode to render (comment, gfm, markdown, file)
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Mode")]
+ pub mode: Option<String>,
+ /// Text markup to render
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Text")]
+ pub text: Option<String>,
+ /// Is it a wiki page ?
+ ///
+ ///
+ ///
+ /// in: body
+ #[serde(rename = "Wiki")]
+ pub wiki: Option<bool>,
+}
+
+/// MergePullRequestForm form for merging Pull Request
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct MergePullRequestOption {
+ #[serde(rename = "Do")]
+ pub r#do: MergePullRequestOptionDo,
+ #[serde(rename = "MergeCommitID")]
+ pub merge_commit_id: Option<String>,
+ #[serde(rename = "MergeMessageField")]
+ pub merge_message_field: Option<String>,
+ #[serde(rename = "MergeTitleField")]
+ pub merge_title_field: Option<String>,
+ pub delete_branch_after_merge: Option<bool>,
+ pub force_merge: Option<bool>,
+ pub head_commit_id: Option<String>,
+ pub merge_when_checks_succeed: Option<bool>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum MergePullRequestOptionDo {
+ #[serde(rename = "merge")]
+ Merge,
+ #[serde(rename = "rebase")]
+ Rebase,
+ #[serde(rename = "rebase-merge")]
+ RebaseMerge,
+ #[serde(rename = "squash")]
+ Squash,
+ #[serde(rename = "manually-merged")]
+ ManuallyMerged,
+}
+/// MigrateRepoOptions options for migrating repository's
+///
+/// this is used to interact with api v1
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct MigrateRepoOptions {
+ pub auth_password: Option<String>,
+ pub auth_token: Option<String>,
+ pub auth_username: Option<String>,
+ pub clone_addr: String,
+ pub description: Option<String>,
+ pub issues: Option<bool>,
+ pub labels: Option<bool>,
+ pub lfs: Option<bool>,
+ pub lfs_endpoint: Option<String>,
+ pub milestones: Option<bool>,
+ pub mirror: Option<bool>,
+ pub mirror_interval: Option<String>,
+ pub private: Option<bool>,
+ pub pull_requests: Option<bool>,
+ pub releases: Option<bool>,
+ pub repo_name: String,
+ /// Name of User or Organisation who will own Repo after migration
+ pub repo_owner: Option<String>,
+ pub service: Option<MigrateRepoOptionsService>,
+ /// deprecated (only for backwards compatibility)
+ pub uid: Option<u64>,
+ pub wiki: Option<bool>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum MigrateRepoOptionsService {
+ #[serde(rename = "git")]
+ Git,
+ #[serde(rename = "github")]
+ Github,
+ #[serde(rename = "gitea")]
+ Gitea,
+ #[serde(rename = "gitlab")]
+ Gitlab,
+ #[serde(rename = "gogs")]
+ Gogs,
+ #[serde(rename = "onedev")]
+ Onedev,
+ #[serde(rename = "gitbucket")]
+ Gitbucket,
+ #[serde(rename = "codebase")]
+ Codebase,
+}
+/// Milestone milestone is a collection of issues on one repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Milestone {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub closed_at: Option<time::OffsetDateTime>,
+ pub closed_issues: Option<u64>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub description: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_on: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub open_issues: Option<u64>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+/// NewIssuePinsAllowed represents an API response that says if new Issue Pins are allowed
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NewIssuePinsAllowed {
+ pub issues: Option<bool>,
+ pub pull_requests: Option<bool>,
+}
+
+/// NodeInfo contains standardized way of exposing metadata about a server running one of the distributed social networks
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NodeInfo {
+ pub metadata: Option<BTreeMap<String, serde_json::Value>>,
+ #[serde(rename = "openRegistrations")]
+ pub open_registrations: Option<bool>,
+ pub protocols: Option<Vec<String>>,
+ pub services: Option<NodeInfoServices>,
+ pub software: Option<NodeInfoSoftware>,
+ pub usage: Option<NodeInfoUsage>,
+ pub version: Option<String>,
+}
+
+/// NodeInfoServices contains the third party sites this server can connect to via their application API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NodeInfoServices {
+ pub inbound: Option<Vec<String>>,
+ pub outbound: Option<Vec<String>>,
+}
+
+/// NodeInfoSoftware contains Metadata about server software in use
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NodeInfoSoftware {
+ pub homepage: Option<String>,
+ pub name: Option<String>,
+ pub repository: Option<String>,
+ pub version: Option<String>,
+}
+
+/// NodeInfoUsage contains usage statistics for this server
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NodeInfoUsage {
+ #[serde(rename = "localComments")]
+ pub local_comments: Option<u64>,
+ #[serde(rename = "localPosts")]
+ pub local_posts: Option<u64>,
+ pub users: Option<NodeInfoUsageUsers>,
+}
+
+/// NodeInfoUsageUsers contains statistics about the users of this server
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NodeInfoUsageUsers {
+ #[serde(rename = "activeHalfyear")]
+ pub active_halfyear: Option<u64>,
+ #[serde(rename = "activeMonth")]
+ pub active_month: Option<u64>,
+ pub total: Option<u64>,
+}
+
+/// Note contains information related to a git note
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Note {
+ pub commit: Option<Commit>,
+ pub message: Option<String>,
+}
+
+/// NotificationCount number of unread notifications
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NotificationCount {
+ pub new: Option<u64>,
+}
+
+/// NotificationSubject contains the notification subject (Issue/Pull/Commit)
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NotificationSubject {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub latest_comment_html_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub latest_comment_url: Option<url::Url>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// NotificationThread expose Notification on API
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NotificationThread {
+ pub id: Option<u64>,
+ pub pinned: Option<bool>,
+ pub repository: Option<Repository>,
+ pub subject: Option<NotificationSubject>,
+ pub unread: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// NotifySubjectType represent type of notification subject
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct NotifySubjectType {}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct OAuth2Application {
+ pub client_id: Option<String>,
+ pub client_secret: Option<String>,
+ pub confidential_client: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub redirect_uris: Option<Vec<String>>,
+}
+
+/// Organization represents an organization
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Organization {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub avatar_url: Option<url::Url>,
+ pub description: Option<String>,
+ pub email: Option<String>,
+ pub full_name: Option<String>,
+ pub id: Option<u64>,
+ pub location: Option<String>,
+ pub name: Option<String>,
+ pub repo_admin_change_team_access: Option<bool>,
+ /// deprecated
+ pub username: Option<String>,
+ pub visibility: Option<String>,
+ pub website: Option<String>,
+}
+
+/// OrganizationPermissions list different users permissions on an organization
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct OrganizationPermissions {
+ pub can_create_repository: Option<bool>,
+ pub can_read: Option<bool>,
+ pub can_write: Option<bool>,
+ pub is_admin: Option<bool>,
+ pub is_owner: Option<bool>,
+}
+
+/// PRBranchInfo information about a branch
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PRBranchInfo {
+ pub label: Option<String>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ pub repo: Option<Repository>,
+ pub repo_id: Option<u64>,
+ pub sha: Option<String>,
+}
+
+/// Package represents a package
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Package {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub creator: Option<User>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub owner: Option<User>,
+ pub repository: Option<Repository>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ pub version: Option<String>,
+}
+
+/// PackageFile represents a package file
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PackageFile {
+ #[serde(rename = "Size")]
+ pub size: Option<u64>,
+ pub id: Option<u64>,
+ pub md5: Option<String>,
+ pub name: Option<String>,
+ pub sha1: Option<String>,
+ pub sha256: Option<String>,
+ pub sha512: Option<String>,
+}
+
+/// PayloadCommit represents a commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PayloadCommit {
+ pub added: Option<Vec<String>>,
+ pub author: Option<PayloadUser>,
+ pub committer: Option<PayloadUser>,
+ /// sha1 hash of the commit
+ pub id: Option<String>,
+ pub message: Option<String>,
+ pub modified: Option<Vec<String>>,
+ pub removed: Option<Vec<String>>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub timestamp: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// PayloadCommitVerification represents the GPG verification of a commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PayloadCommitVerification {
+ pub payload: Option<String>,
+ pub reason: Option<String>,
+ pub signature: Option<String>,
+ pub signer: Option<PayloadUser>,
+ pub verified: Option<bool>,
+}
+
+/// PayloadUser represents the author or committer of a commit
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PayloadUser {
+ pub email: Option<String>,
+ /// Full name of the commit author
+ pub name: Option<String>,
+ pub username: Option<String>,
+}
+
+/// Permission represents a set of permissions
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Permission {
+ pub admin: Option<bool>,
+ pub pull: Option<bool>,
+ pub push: Option<bool>,
+}
+
+/// PublicKey publickey is a user key to push code to repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PublicKey {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub fingerprint: Option<String>,
+ pub id: Option<u64>,
+ pub key: Option<String>,
+ pub key_type: Option<String>,
+ pub read_only: Option<bool>,
+ pub title: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub user: Option<User>,
+}
+
+/// PullRequest represents a pull request
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PullRequest {
+ pub allow_maintainer_edit: Option<bool>,
+ pub assignee: Option<User>,
+ pub assignees: Option<Vec<User>>,
+ pub base: Option<PRBranchInfo>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub closed_at: Option<time::OffsetDateTime>,
+ pub comments: Option<u64>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub diff_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub due_date: Option<time::OffsetDateTime>,
+ pub head: Option<PRBranchInfo>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub is_locked: Option<bool>,
+ pub labels: Option<Vec<Label>>,
+ pub merge_base: Option<String>,
+ pub merge_commit_sha: Option<String>,
+ pub mergeable: Option<bool>,
+ pub merged: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub merged_at: Option<time::OffsetDateTime>,
+ pub merged_by: Option<User>,
+ pub milestone: Option<Milestone>,
+ pub number: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub patch_url: Option<url::Url>,
+ pub pin_order: Option<u64>,
+ pub requested_reviewers: Option<Vec<User>>,
+ pub state: Option<String>,
+ pub title: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub user: Option<User>,
+}
+
+/// PullRequestMeta PR info if an issue is a PR
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PullRequestMeta {
+ pub merged: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub merged_at: Option<time::OffsetDateTime>,
+}
+
+/// PullReview represents a pull request review
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PullReview {
+ pub body: Option<String>,
+ pub comments_count: Option<u64>,
+ pub commit_id: Option<String>,
+ pub dismissed: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub official: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub pull_request_url: Option<url::Url>,
+ pub stale: Option<bool>,
+ pub state: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub submitted_at: Option<time::OffsetDateTime>,
+ pub team: Option<Team>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ pub user: Option<User>,
+}
+
+/// PullReviewComment represents a comment on a pull request review
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PullReviewComment {
+ pub body: Option<String>,
+ pub commit_id: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub diff_hunk: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub original_commit_id: Option<String>,
+ pub original_position: Option<u32>,
+ pub path: Option<String>,
+ pub position: Option<u32>,
+ pub pull_request_review_id: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub pull_request_url: Option<url::Url>,
+ pub resolver: Option<User>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ pub user: Option<User>,
+}
+
+/// PullReviewRequestOptions are options to add or remove pull review requests
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PullReviewRequestOptions {
+ pub reviewers: Option<Vec<String>>,
+ pub team_reviewers: Option<Vec<String>>,
+}
+
+/// PushMirror represents information of a push mirror
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct PushMirror {
+ pub created: Option<String>,
+ pub interval: Option<String>,
+ pub last_error: Option<String>,
+ pub last_update: Option<String>,
+ pub remote_address: Option<String>,
+ pub remote_name: Option<String>,
+ pub repo_name: Option<String>,
+ pub sync_on_commit: Option<bool>,
+}
+
+/// Reaction contain one reaction
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Reaction {
+ pub content: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub user: Option<User>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Reference {
+ pub object: Option<GitObject>,
+ #[serde(rename = "ref")]
+ pub r#ref: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// Release represents a repository release
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Release {
+ pub assets: Option<Vec<Attachment>>,
+ pub author: Option<User>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub draft: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub prerelease: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub published_at: Option<time::OffsetDateTime>,
+ pub tag_name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub tarball_url: Option<url::Url>,
+ pub target_commitish: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub upload_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub zipball_url: Option<url::Url>,
+}
+
+/// RenameUserOption options when renaming a user
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RenameUserOption {
+ /// New username for this user. This name cannot be in use yet by any other user.
+ pub new_username: String,
+}
+
+/// RepoCollaboratorPermission to get repository permission for a collaborator
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RepoCollaboratorPermission {
+ pub permission: Option<String>,
+ pub role_name: Option<String>,
+ pub user: Option<User>,
+}
+
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RepoCommit {
+ pub author: Option<CommitUser>,
+ pub committer: Option<CommitUser>,
+ pub message: Option<String>,
+ pub tree: Option<CommitMeta>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub verification: Option<PayloadCommitVerification>,
+}
+
+/// RepoTopicOptions a collection of repo topic names
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RepoTopicOptions {
+ /// list of topic names
+ pub topics: Option<Vec<String>>,
+}
+
+/// RepoTransfer represents a pending repo transfer
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RepoTransfer {
+ pub doer: Option<User>,
+ pub recipient: Option<User>,
+ pub teams: Option<Vec<Team>>,
+}
+
+/// Repository represents a repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Repository {
+ pub allow_merge_commits: Option<bool>,
+ pub allow_rebase: Option<bool>,
+ pub allow_rebase_explicit: Option<bool>,
+ pub allow_rebase_update: Option<bool>,
+ pub allow_squash_merge: Option<bool>,
+ pub archived: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub archived_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub avatar_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub clone_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub default_allow_maintainer_edit: Option<bool>,
+ pub default_branch: Option<String>,
+ pub default_delete_branch_after_merge: Option<bool>,
+ pub default_merge_style: Option<String>,
+ pub description: Option<String>,
+ pub empty: Option<bool>,
+ pub external_tracker: Option<ExternalTracker>,
+ pub external_wiki: Option<ExternalWiki>,
+ pub fork: Option<bool>,
+ pub forks_count: Option<u64>,
+ pub full_name: Option<String>,
+ pub has_actions: Option<bool>,
+ pub has_issues: Option<bool>,
+ pub has_packages: Option<bool>,
+ pub has_projects: Option<bool>,
+ pub has_pull_requests: Option<bool>,
+ pub has_releases: Option<bool>,
+ pub has_wiki: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ pub ignore_whitespace_conflicts: Option<bool>,
+ pub internal: Option<bool>,
+ pub internal_tracker: Option<InternalTracker>,
+ pub language: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub languages_url: Option<url::Url>,
+ pub link: Option<String>,
+ pub mirror: Option<bool>,
+ pub mirror_interval: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub mirror_updated: Option<time::OffsetDateTime>,
+ pub name: Option<String>,
+ pub open_issues_count: Option<u64>,
+ pub open_pr_counter: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub original_url: Option<url::Url>,
+ pub owner: Option<User>,
+ pub parent: Option<Box<Repository>>,
+ pub permissions: Option<Permission>,
+ pub private: Option<bool>,
+ pub release_counter: Option<u64>,
+ pub repo_transfer: Option<RepoTransfer>,
+ pub size: Option<u64>,
+ pub ssh_url: Option<String>,
+ pub stars_count: Option<u64>,
+ pub template: Option<bool>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+ pub watchers_count: Option<u64>,
+ pub website: Option<String>,
+}
+
+/// RepositoryMeta basic repository information
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct RepositoryMeta {
+ pub full_name: Option<String>,
+ pub id: Option<u64>,
+ pub name: Option<String>,
+ pub owner: Option<String>,
+}
+
+/// ReviewStateType review state type
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ReviewStateType {}
+
+/// SearchResults results of a successful search
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct SearchResults {
+ pub data: Option<Vec<Repository>>,
+ pub ok: Option<bool>,
+}
+
+/// Secret represents a secret
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Secret {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ /// the secret's name
+ pub name: Option<String>,
+}
+
+/// ServerVersion wraps the version of the server
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct ServerVersion {
+ pub version: Option<String>,
+}
+
+/// StateType issue state type
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct StateType {}
+
+/// StopWatch represent a running stopwatch
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct StopWatch {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub duration: Option<String>,
+ pub issue_index: Option<u64>,
+ pub issue_title: Option<String>,
+ pub repo_name: Option<String>,
+ pub repo_owner_name: Option<String>,
+ pub seconds: Option<u64>,
+}
+
+/// SubmitPullReviewOptions are options to submit a pending pull review
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct SubmitPullReviewOptions {
+ pub body: Option<String>,
+ pub event: Option<String>,
+}
+
+/// Tag represents a repository tag
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Tag {
+ pub commit: Option<CommitMeta>,
+ pub id: Option<String>,
+ pub message: Option<String>,
+ pub name: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub tarball_url: Option<url::Url>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub zipball_url: Option<url::Url>,
+}
+
+/// Team represents a team in an organization
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct Team {
+ pub can_create_org_repo: Option<bool>,
+ pub description: Option<String>,
+ pub id: Option<u64>,
+ pub includes_all_repositories: Option<bool>,
+ pub name: Option<String>,
+ pub organization: Option<Organization>,
+ pub permission: Option<TeamPermission>,
+ pub units: Option<Vec<String>>,
+ pub units_map: Option<BTreeMap<String, String>>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum TeamPermission {
+ #[serde(rename = "none")]
+ None,
+ #[serde(rename = "read")]
+ Read,
+ #[serde(rename = "write")]
+ Write,
+ #[serde(rename = "admin")]
+ Admin,
+ #[serde(rename = "owner")]
+ Owner,
+}
+/// TimeStamp defines a timestamp
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TimeStamp {}
+
+/// TimelineComment represents a timeline comment (comment of any type) on a commit or issue
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TimelineComment {
+ pub assignee: Option<User>,
+ pub assignee_team: Option<Team>,
+ pub body: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub dependent_issue: Option<Issue>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub id: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub issue_url: Option<url::Url>,
+ pub label: Option<Label>,
+ pub milestone: Option<Milestone>,
+ pub new_ref: Option<String>,
+ pub new_title: Option<String>,
+ pub old_milestone: Option<Milestone>,
+ pub old_project_id: Option<u64>,
+ pub old_ref: Option<String>,
+ pub old_title: Option<String>,
+ pub project_id: Option<u64>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub pull_request_url: Option<url::Url>,
+ pub ref_action: Option<String>,
+ pub ref_comment: Option<Comment>,
+ /// commit SHA where issue/PR was referenced
+ pub ref_commit_sha: Option<String>,
+ pub ref_issue: Option<Issue>,
+ /// whether the assignees were removed or added
+ pub removed_assignee: Option<bool>,
+ pub resolve_doer: Option<User>,
+ pub review_id: Option<u64>,
+ pub tracked_time: Option<TrackedTime>,
+ #[serde(rename = "type")]
+ pub r#type: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated_at: Option<time::OffsetDateTime>,
+ pub user: Option<User>,
+}
+
+/// TopicName a list of repo topic names
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TopicName {
+ pub topics: Option<Vec<String>>,
+}
+
+/// TopicResponse for returning topics
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TopicResponse {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub repo_count: Option<u64>,
+ pub topic_name: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub updated: Option<time::OffsetDateTime>,
+}
+
+/// TrackedTime worked time for an issue / pr
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TrackedTime {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ pub id: Option<u64>,
+ pub issue: Option<Issue>,
+ /// deprecated (only for backwards compatibility)
+ pub issue_id: Option<u64>,
+ /// Time in seconds
+ pub time: Option<u64>,
+ /// deprecated (only for backwards compatibility)
+ pub user_id: Option<u64>,
+ pub user_name: Option<String>,
+}
+
+/// TransferRepoOption options when transfer a repository's ownership
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TransferRepoOption {
+ pub new_owner: String,
+ /// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
+ pub team_ids: Option<Vec<u64>>,
+}
+
+/// 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)
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UpdateFileOptions {
+ pub author: Option<Identity>,
+ /// branch (optional) to base this file from. if not given, the default branch is used
+ pub branch: Option<String>,
+ pub committer: Option<Identity>,
+ /// content must be base64 encoded
+ pub content: String,
+ pub dates: Option<CommitDateOptions>,
+ /// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
+ pub from_path: Option<String>,
+ /// message (optional) for the commit of this file. if not supplied, a default message will be used
+ pub message: Option<String>,
+ /// new_branch (optional) will make a new branch from `branch` before creating the file
+ pub new_branch: Option<String>,
+ /// sha is the SHA for the file that already exists
+ pub sha: String,
+ /// Add a Signed-off-by trailer by the committer at the end of the commit log message.
+ pub signoff: Option<bool>,
+}
+
+/// UpdateRepoAvatarUserOption options when updating the repo avatar
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UpdateRepoAvatarOption {
+ /// image must be base64 encoded
+ pub image: Option<String>,
+}
+
+/// UpdateUserAvatarUserOption options when updating the user avatar
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UpdateUserAvatarOption {
+ /// image must be base64 encoded
+ pub image: Option<String>,
+}
+
+/// User represents a user
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct User {
+ /// Is user active
+ pub active: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ /// URL to the user's avatar
+ pub avatar_url: Option<url::Url>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created: Option<time::OffsetDateTime>,
+ /// the user's description
+ pub description: Option<String>,
+ pub email: Option<String>,
+ /// user counts
+ pub followers_count: Option<u64>,
+ pub following_count: Option<u64>,
+ /// the user's full name
+ pub full_name: Option<String>,
+ /// the user's id
+ pub id: Option<u64>,
+ /// Is the user an administrator
+ pub is_admin: Option<bool>,
+ /// User locale
+ pub language: Option<String>,
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub last_login: Option<time::OffsetDateTime>,
+ /// the user's location
+ pub location: Option<String>,
+ /// the user's username
+ pub login: Option<String>,
+ /// the user's authentication sign-in name.
+ pub login_name: Option<String>,
+ /// Is user login prohibited
+ pub prohibit_login: Option<bool>,
+ /// Is user restricted
+ pub restricted: Option<bool>,
+ pub starred_repos_count: Option<u64>,
+ /// User visibility level option: public, limited, private
+ pub visibility: Option<String>,
+ /// the user's website
+ pub website: Option<String>,
+}
+
+/// UserHeatmapData represents the data needed to create a heatmap
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UserHeatmapData {
+ pub contributions: Option<u64>,
+ pub timestamp: Option<u64>,
+}
+
+/// UserSettings represents user settings
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UserSettings {
+ pub description: Option<String>,
+ pub diff_view_style: Option<String>,
+ pub full_name: Option<String>,
+ pub hide_activity: Option<bool>,
+ /// Privacy
+ pub hide_email: Option<bool>,
+ pub language: Option<String>,
+ pub location: Option<String>,
+ pub theme: Option<String>,
+ pub website: Option<String>,
+}
+
+/// UserSettingsOptions represents options to change user settings
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UserSettingsOptions {
+ pub description: Option<String>,
+ pub diff_view_style: Option<String>,
+ pub full_name: Option<String>,
+ pub hide_activity: Option<bool>,
+ /// Privacy
+ pub hide_email: Option<bool>,
+ pub language: Option<String>,
+ pub location: Option<String>,
+ pub theme: Option<String>,
+ pub website: Option<String>,
+}
+
+/// WatchInfo represents an API watch status of one repository
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct WatchInfo {
+ #[serde(with = "time::serde::rfc3339::option")]
+ pub created_at: Option<time::OffsetDateTime>,
+ pub ignored: Option<bool>,
+ pub reason: Option<serde_json::Value>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub repository_url: Option<url::Url>,
+ pub subscribed: Option<bool>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub url: Option<url::Url>,
+}
+
+/// WikiCommit page commit/revision
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct WikiCommit {
+ pub author: Option<CommitUser>,
+ pub commiter: Option<CommitUser>,
+ pub message: Option<String>,
+ pub sha: Option<String>,
+}
+
+/// WikiCommitList commit/revision list
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct WikiCommitList {
+ pub commits: Option<Vec<WikiCommit>>,
+ pub count: Option<u64>,
+}
+
+/// WikiPage a wiki page
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct WikiPage {
+ pub commit_count: Option<u64>,
+ /// Page content, base64 encoded
+ pub content_base64: Option<String>,
+ pub footer: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub last_commit: Option<WikiCommit>,
+ pub sidebar: Option<String>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub sub_url: Option<url::Url>,
+ pub title: Option<String>,
+}
+
+/// WikiPageMetaData wiki page meta information
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct WikiPageMetaData {
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub html_url: Option<url::Url>,
+ pub last_commit: Option<WikiCommit>,
+ #[serde(deserialize_with = "crate::none_if_blank_url")]
+ pub sub_url: Option<url::Url>,
+ pub title: Option<String>,
+}
+
+pub struct ChangedFileListHeaders {
+ pub x_has_more: Option<bool>,
+ pub x_page: Option<u64>,
+ pub x_page_count: Option<u64>,
+ pub x_per_page: Option<u64>,
+ pub x_total: Option<u64>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for ChangedFileListHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let x_has_more = map
+ .get("X-HasMore")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<bool>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_page = map
+ .get("X-Page")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_page_count = map
+ .get("X-PageCount")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_per_page = map
+ .get("X-PerPage")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_total = map
+ .get("X-Total")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ Ok(Self {
+ x_has_more,
+ x_page,
+ x_page_count,
+ x_per_page,
+ x_total,
+ })
+ }
+}
+
+pub struct CommitListHeaders {
+ pub x_has_more: Option<bool>,
+ pub x_page: Option<u64>,
+ pub x_page_count: Option<u64>,
+ pub x_per_page: Option<u64>,
+ pub x_total: Option<u64>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for CommitListHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let x_has_more = map
+ .get("X-HasMore")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<bool>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_page = map
+ .get("X-Page")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_page_count = map
+ .get("X-PageCount")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_per_page = map
+ .get("X-PerPage")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ let x_total = map
+ .get("X-Total")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ s.parse::<u64>()
+ .map_err(|_| StructureError::HeaderParseFailed)
+ })
+ .transpose()?;
+ Ok(Self {
+ x_has_more,
+ x_page,
+ x_page_count,
+ x_per_page,
+ x_total,
+ })
+ }
+}
+
+pub struct ErrorHeaders {
+ pub message: Option<String>,
+ pub url: Option<String>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for ErrorHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let message = map
+ .get("message")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ let url = map
+ .get("url")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ Ok(Self { message, url })
+ }
+}
+
+pub struct ForbiddenHeaders {
+ pub message: Option<String>,
+ pub url: Option<String>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for ForbiddenHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let message = map
+ .get("message")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ let url = map
+ .get("url")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ Ok(Self { message, url })
+ }
+}
+
+pub struct InvalidTopicsErrorHeaders {
+ pub invalid_topics: Option<Vec<String>>,
+ pub message: Option<String>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for InvalidTopicsErrorHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let invalid_topics = map
+ .get("invalidTopics")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.split(",").map(|s| s.to_string()).collect::<Vec<_>>())
+ })
+ .transpose()?;
+ let message = map
+ .get("message")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ Ok(Self {
+ invalid_topics,
+ message,
+ })
+ }
+}
+
+pub struct ValidationErrorHeaders {
+ pub message: Option<String>,
+ pub url: Option<String>,
+}
+
+impl TryFrom<&reqwest::header::HeaderMap> for ValidationErrorHeaders {
+ type Error = StructureError;
+
+ fn try_from(map: &reqwest::header::HeaderMap) -> Result<Self, Self::Error> {
+ let message = map
+ .get("message")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ let url = map
+ .get("url")
+ .map(|s| -> Result<_, _> {
+ let s = s.to_str().map_err(|_| StructureError::HeaderNotAscii)?;
+ Ok(s.to_string())
+ })
+ .transpose()?;
+ Ok(Self { message, url })
+ }
+}
+
+pub struct AdminCronListQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminCronListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminGetAllEmailsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminGetAllEmailsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminSearchEmailsQuery {
+ /// keyword
+ pub q: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminSearchEmailsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminListHooksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminListHooksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminGetAllOrgsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminGetAllOrgsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminUnadoptedListQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+ /// pattern of repositories to search for
+ pub pattern: Option<String>,
+}
+
+impl std::fmt::Display for AdminUnadoptedListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(pattern) = &self.pattern {
+ write!(f, "pattern={pattern}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminSearchUsersQuery {
+ /// ID of the user's login source to search for
+ pub source_id: Option<u64>,
+ /// user's login name to search for
+ pub login_name: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for AdminSearchUsersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(source_id) = &self.source_id {
+ write!(f, "source_id={source_id}&")?;
+ }
+ if let Some(login_name) = &self.login_name {
+ write!(f, "login_name={login_name}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct AdminDeleteUserQuery {
+ /// purge the user from the system completely
+ pub purge: Option<bool>,
+}
+
+impl std::fmt::Display for AdminDeleteUserQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(purge) = &self.purge {
+ write!(f, "purge={purge}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct NotifyGetListQuery {
+ /// If true, show notifications marked as read. Default value is false
+ pub all: Option<bool>,
+ /// Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned.
+ pub status_types: Option<Vec<String>>,
+ /// filter notifications by subject type
+ pub subject_type: Option<Vec<NotifyGetListQuerySubjectType>>,
+ /// Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for NotifyGetListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(all) = &self.all {
+ write!(f, "all={all}&")?;
+ }
+ if let Some(status_types) = &self.status_types {
+ if !status_types.is_empty() {
+ for item in status_types {
+ write!(f, "status-types=")?;
+ write!(f, "{item}")?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(subject_type) = &self.subject_type {
+ if !subject_type.is_empty() {
+ for item in subject_type {
+ write!(f, "subject-type=")?;
+ write!(f, "{}", item.as_str())?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum NotifyGetListQuerySubjectType {
+ #[serde(rename = "issue")]
+ Issue,
+ #[serde(rename = "pull")]
+ Pull,
+ #[serde(rename = "commit")]
+ Commit,
+ #[serde(rename = "repository")]
+ Repository,
+}
+
+impl NotifyGetListQuerySubjectType {
+ fn as_str(&self) -> &'static str {
+ match self {
+ NotifyGetListQuerySubjectType::Issue => "issue",
+ NotifyGetListQuerySubjectType::Pull => "pull",
+ NotifyGetListQuerySubjectType::Commit => "commit",
+ NotifyGetListQuerySubjectType::Repository => "repository",
+ }
+ }
+}
+pub struct NotifyReadListQuery {
+ /// Describes the last point that notifications were checked. Anything updated since this time will not be updated.
+ pub last_read_at: Option<time::OffsetDateTime>,
+ /// If true, mark all notifications on this repo. Default value is false
+ pub all: Option<String>,
+ /// Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread.
+ pub status_types: Option<Vec<String>>,
+ /// Status to mark notifications as, Defaults to read.
+ pub to_status: Option<String>,
+}
+
+impl std::fmt::Display for NotifyReadListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(last_read_at) = &self.last_read_at {
+ write!(
+ f,
+ "last_read_at={field_name}&",
+ field_name = last_read_at
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(all) = &self.all {
+ write!(f, "all={all}&")?;
+ }
+ if let Some(status_types) = &self.status_types {
+ if !status_types.is_empty() {
+ for item in status_types {
+ write!(f, "status-types=")?;
+ write!(f, "{item}")?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(to_status) = &self.to_status {
+ write!(f, "to-status={to_status}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct NotifyReadThreadQuery {
+ /// Status to mark notifications as
+ pub to_status: Option<String>,
+}
+
+impl std::fmt::Display for NotifyReadThreadQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(to_status) = &self.to_status {
+ write!(f, "to-status={to_status}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgGetAllQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgGetAllQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListActionsSecretsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListActionsSecretsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListActivityFeedsQuery {
+ /// the date of the activities to be found
+ pub date: Option<time::Date>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListActivityFeedsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(date) = &self.date {
+ write!(
+ f,
+ "date={field_name}&",
+ field_name = date
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListHooksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListHooksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListLabelsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListLabelsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListBlockedUsersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListBlockedUsersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListMembersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListMembersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListPublicMembersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListPublicMembersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListReposQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListReposQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListTeamsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListTeamsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct TeamSearchQuery {
+ /// keywords to search
+ pub q: Option<String>,
+ /// include search within team description (defaults to true)
+ pub include_desc: Option<bool>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for TeamSearchQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(include_desc) = &self.include_desc {
+ write!(f, "include_desc={include_desc}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct TeamSearchResponse {
+ pub data: Option<Vec<Team>>,
+ pub ok: Option<bool>,
+}
+
+pub struct ListPackagesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+ /// package type filter
+ pub r#type: Option<ListPackagesQueryType>,
+ /// name filter
+ pub q: Option<String>,
+}
+
+impl std::fmt::Display for ListPackagesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(r#type) = &self.r#type {
+ write!(f, "type={}&", r#type.as_str())?;
+ }
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum ListPackagesQueryType {
+ #[serde(rename = "alpine")]
+ Alpine,
+ #[serde(rename = "cargo")]
+ Cargo,
+ #[serde(rename = "chef")]
+ Chef,
+ #[serde(rename = "composer")]
+ Composer,
+ #[serde(rename = "conan")]
+ Conan,
+ #[serde(rename = "conda")]
+ Conda,
+ #[serde(rename = "container")]
+ Container,
+ #[serde(rename = "cran")]
+ Cran,
+ #[serde(rename = "debian")]
+ Debian,
+ #[serde(rename = "generic")]
+ Generic,
+ #[serde(rename = "go")]
+ Go,
+ #[serde(rename = "helm")]
+ Helm,
+ #[serde(rename = "maven")]
+ Maven,
+ #[serde(rename = "npm")]
+ Npm,
+ #[serde(rename = "nuget")]
+ Nuget,
+ #[serde(rename = "pub")]
+ Pub,
+ #[serde(rename = "pypi")]
+ Pypi,
+ #[serde(rename = "rpm")]
+ Rpm,
+ #[serde(rename = "rubygems")]
+ Rubygems,
+ #[serde(rename = "swift")]
+ Swift,
+ #[serde(rename = "vagrant")]
+ Vagrant,
+}
+
+impl ListPackagesQueryType {
+ fn as_str(&self) -> &'static str {
+ match self {
+ ListPackagesQueryType::Alpine => "alpine",
+ ListPackagesQueryType::Cargo => "cargo",
+ ListPackagesQueryType::Chef => "chef",
+ ListPackagesQueryType::Composer => "composer",
+ ListPackagesQueryType::Conan => "conan",
+ ListPackagesQueryType::Conda => "conda",
+ ListPackagesQueryType::Container => "container",
+ ListPackagesQueryType::Cran => "cran",
+ ListPackagesQueryType::Debian => "debian",
+ ListPackagesQueryType::Generic => "generic",
+ ListPackagesQueryType::Go => "go",
+ ListPackagesQueryType::Helm => "helm",
+ ListPackagesQueryType::Maven => "maven",
+ ListPackagesQueryType::Npm => "npm",
+ ListPackagesQueryType::Nuget => "nuget",
+ ListPackagesQueryType::Pub => "pub",
+ ListPackagesQueryType::Pypi => "pypi",
+ ListPackagesQueryType::Rpm => "rpm",
+ ListPackagesQueryType::Rubygems => "rubygems",
+ ListPackagesQueryType::Swift => "swift",
+ ListPackagesQueryType::Vagrant => "vagrant",
+ }
+ }
+}
+pub struct IssueSearchIssuesQuery {
+ /// whether issue is open or closed
+ pub state: Option<String>,
+ /// comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
+ pub labels: Option<String>,
+ /// comma separated list of milestone names. Fetch only issues that have any of this milestones. Non existent are discarded
+ pub milestones: Option<String>,
+ /// search string
+ pub q: Option<String>,
+ /// repository to prioritize in the results
+ pub priority_repo_id: Option<u64>,
+ /// filter by type (issues / pulls) if set
+ pub r#type: Option<String>,
+ /// Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// filter (issues / pulls) assigned to you, default is false
+ pub assigned: Option<bool>,
+ /// filter (issues / pulls) created by you, default is false
+ pub created: Option<bool>,
+ /// filter (issues / pulls) mentioning you, default is false
+ pub mentioned: Option<bool>,
+ /// filter pulls requesting your review, default is false
+ pub review_requested: Option<bool>,
+ /// filter pulls reviewed by you, default is false
+ pub reviewed: Option<bool>,
+ /// filter by owner
+ pub owner: Option<String>,
+ /// filter by team (requires organization owner parameter to be provided)
+ pub team: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueSearchIssuesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(state) = &self.state {
+ write!(f, "state={state}&")?;
+ }
+ if let Some(labels) = &self.labels {
+ write!(f, "labels={labels}&")?;
+ }
+ if let Some(milestones) = &self.milestones {
+ write!(f, "milestones={milestones}&")?;
+ }
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(priority_repo_id) = &self.priority_repo_id {
+ write!(f, "priority_repo_id={priority_repo_id}&")?;
+ }
+ if let Some(r#type) = &self.r#type {
+ write!(f, "type={type}&")?;
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(assigned) = &self.assigned {
+ write!(f, "assigned={assigned}&")?;
+ }
+ if let Some(created) = &self.created {
+ write!(f, "created={created}&")?;
+ }
+ if let Some(mentioned) = &self.mentioned {
+ write!(f, "mentioned={mentioned}&")?;
+ }
+ if let Some(review_requested) = &self.review_requested {
+ write!(f, "review_requested={review_requested}&")?;
+ }
+ if let Some(reviewed) = &self.reviewed {
+ write!(f, "reviewed={reviewed}&")?;
+ }
+ if let Some(owner) = &self.owner {
+ write!(f, "owner={owner}&")?;
+ }
+ if let Some(team) = &self.team {
+ write!(f, "team={team}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoSearchQuery {
+ /// keyword
+ pub q: Option<String>,
+ /// Limit search to repositories with keyword as topic
+ pub topic: Option<bool>,
+ /// include search of keyword within repository description
+ pub include_desc: Option<bool>,
+ /// search only for repos that the user with the given id owns or contributes to
+ pub uid: Option<u64>,
+ /// repo owner to prioritize in the results
+ pub priority_owner_id: Option<u64>,
+ /// search only for repos that belong to the given team id
+ pub team_id: Option<u64>,
+ /// search only for repos that the user with the given id has starred
+ pub starred_by: Option<u64>,
+ /// include private repositories this user has access to (defaults to true)
+ pub private: Option<bool>,
+ /// show only pubic, private or all repositories (defaults to all)
+ pub is_private: Option<bool>,
+ /// include template repositories this user has access to (defaults to true)
+ pub template: Option<bool>,
+ /// show only archived, non-archived or all repositories (defaults to all)
+ pub archived: Option<bool>,
+ /// type of repository to search for. Supported values are "fork", "source", "mirror" and "collaborative"
+ pub mode: Option<String>,
+ /// if `uid` is given, search only for repos that the user owns
+ pub exclusive: Option<bool>,
+ /// sort repos by attribute. Supported values are "alpha", "created", "updated", "size", and "id". Default is "alpha"
+ pub sort: Option<String>,
+ /// sort order, either "asc" (ascending) or "desc" (descending). Default is "asc", ignored if "sort" is not specified.
+ pub order: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoSearchQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(topic) = &self.topic {
+ write!(f, "topic={topic}&")?;
+ }
+ if let Some(include_desc) = &self.include_desc {
+ write!(f, "includeDesc={include_desc}&")?;
+ }
+ if let Some(uid) = &self.uid {
+ write!(f, "uid={uid}&")?;
+ }
+ if let Some(priority_owner_id) = &self.priority_owner_id {
+ write!(f, "priority_owner_id={priority_owner_id}&")?;
+ }
+ if let Some(team_id) = &self.team_id {
+ write!(f, "team_id={team_id}&")?;
+ }
+ if let Some(starred_by) = &self.starred_by {
+ write!(f, "starredBy={starred_by}&")?;
+ }
+ if let Some(private) = &self.private {
+ write!(f, "private={private}&")?;
+ }
+ if let Some(is_private) = &self.is_private {
+ write!(f, "is_private={is_private}&")?;
+ }
+ if let Some(template) = &self.template {
+ write!(f, "template={template}&")?;
+ }
+ if let Some(archived) = &self.archived {
+ write!(f, "archived={archived}&")?;
+ }
+ if let Some(mode) = &self.mode {
+ write!(f, "mode={mode}&")?;
+ }
+ if let Some(exclusive) = &self.exclusive {
+ write!(f, "exclusive={exclusive}&")?;
+ }
+ if let Some(sort) = &self.sort {
+ write!(f, "sort={sort}&")?;
+ }
+ if let Some(order) = &self.order {
+ write!(f, "order={order}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListActivityFeedsQuery {
+ /// the date of the activities to be found
+ pub date: Option<time::Date>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListActivityFeedsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(date) = &self.date {
+ write!(
+ f,
+ "date={field_name}&",
+ field_name = date
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListBranchesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListBranchesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListCollaboratorsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListCollaboratorsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetAllCommitsQuery {
+ /// SHA or branch to start listing commits from (usually 'master')
+ pub sha: Option<String>,
+ /// filepath of a file/dir
+ pub path: Option<String>,
+ /// include diff stats for every commit (disable for speedup, default 'true')
+ pub stat: Option<bool>,
+ /// include verification for every commit (disable for speedup, default 'true')
+ pub verification: Option<bool>,
+ /// include a list of affected files for every commit (disable for speedup, default 'true')
+ pub files: Option<bool>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results (ignored if used with 'path')
+ pub limit: Option<u32>,
+ /// commits that match the given specifier will not be listed.
+ pub not: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetAllCommitsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(sha) = &self.sha {
+ write!(f, "sha={sha}&")?;
+ }
+ if let Some(path) = &self.path {
+ write!(f, "path={path}&")?;
+ }
+ if let Some(stat) = &self.stat {
+ write!(f, "stat={stat}&")?;
+ }
+ if let Some(verification) = &self.verification {
+ write!(f, "verification={verification}&")?;
+ }
+ if let Some(files) = &self.files {
+ write!(f, "files={files}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(not) = &self.not {
+ write!(f, "not={not}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetCombinedStatusByRefQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoGetCombinedStatusByRefQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListStatusesByRefQuery {
+ /// type of sort
+ pub sort: Option<RepoListStatusesByRefQuerySort>,
+ /// type of state
+ pub state: Option<RepoListStatusesByRefQueryState>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListStatusesByRefQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(sort) = &self.sort {
+ write!(f, "sort={}&", sort.as_str())?;
+ }
+ if let Some(state) = &self.state {
+ write!(f, "state={}&", state.as_str())?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListStatusesByRefQuerySort {
+ #[serde(rename = "oldest")]
+ Oldest,
+ #[serde(rename = "recentupdate")]
+ Recentupdate,
+ #[serde(rename = "leastupdate")]
+ Leastupdate,
+ #[serde(rename = "leastindex")]
+ Leastindex,
+ #[serde(rename = "highestindex")]
+ Highestindex,
+}
+
+impl RepoListStatusesByRefQuerySort {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListStatusesByRefQuerySort::Oldest => "oldest",
+ RepoListStatusesByRefQuerySort::Recentupdate => "recentupdate",
+ RepoListStatusesByRefQuerySort::Leastupdate => "leastupdate",
+ RepoListStatusesByRefQuerySort::Leastindex => "leastindex",
+ RepoListStatusesByRefQuerySort::Highestindex => "highestindex",
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListStatusesByRefQueryState {
+ #[serde(rename = "pending")]
+ Pending,
+ #[serde(rename = "success")]
+ Success,
+ #[serde(rename = "error")]
+ Error,
+ #[serde(rename = "failure")]
+ Failure,
+ #[serde(rename = "warning")]
+ Warning,
+}
+
+impl RepoListStatusesByRefQueryState {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListStatusesByRefQueryState::Pending => "pending",
+ RepoListStatusesByRefQueryState::Success => "success",
+ RepoListStatusesByRefQueryState::Error => "error",
+ RepoListStatusesByRefQueryState::Failure => "failure",
+ RepoListStatusesByRefQueryState::Warning => "warning",
+ }
+ }
+}
+pub struct RepoGetContentsListQuery {
+ /// The name of the commit/branch/tag. Default the repository’s default branch (usually master)
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetContentsListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetContentsQuery {
+ /// The name of the commit/branch/tag. Default the repository’s default branch (usually master)
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetContentsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetEditorConfigQuery {
+ /// The name of the commit/branch/tag. Default the repository’s default branch (usually master)
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetEditorConfigQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct ListForksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for ListForksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetSingleCommitQuery {
+ /// include diff stats for every commit (disable for speedup, default 'true')
+ pub stat: Option<bool>,
+ /// include verification for every commit (disable for speedup, default 'true')
+ pub verification: Option<bool>,
+ /// include a list of affected files for every commit (disable for speedup, default 'true')
+ pub files: Option<bool>,
+}
+
+impl std::fmt::Display for RepoGetSingleCommitQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(stat) = &self.stat {
+ write!(f, "stat={stat}&")?;
+ }
+ if let Some(verification) = &self.verification {
+ write!(f, "verification={verification}&")?;
+ }
+ if let Some(files) = &self.files {
+ write!(f, "files={files}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetNoteQuery {
+ /// include verification for every commit (disable for speedup, default 'true')
+ pub verification: Option<bool>,
+ /// include a list of affected files for every commit (disable for speedup, default 'true')
+ pub files: Option<bool>,
+}
+
+impl std::fmt::Display for RepoGetNoteQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(verification) = &self.verification {
+ write!(f, "verification={verification}&")?;
+ }
+ if let Some(files) = &self.files {
+ write!(f, "files={files}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct GetTreeQuery {
+ /// show all directories and files
+ pub recursive: Option<bool>,
+ /// page number; the 'truncated' field in the response will be true if there are still more items after this page, false if the last page
+ pub page: Option<u32>,
+ /// number of items per page
+ pub per_page: Option<u32>,
+}
+
+impl std::fmt::Display for GetTreeQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(recursive) = &self.recursive {
+ write!(f, "recursive={recursive}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(per_page) = &self.per_page {
+ write!(f, "per_page={per_page}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListHooksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListHooksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoTestHookQuery {
+ /// The name of the commit/branch/tag, indicates which commit will be loaded to the webhook payload.
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoTestHookQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueListIssuesQuery {
+ /// whether issue is open or closed
+ pub state: Option<IssueListIssuesQueryState>,
+ /// comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
+ pub labels: Option<String>,
+ /// search string
+ pub q: Option<String>,
+ /// filter by type (issues / pulls) if set
+ pub r#type: Option<IssueListIssuesQueryType>,
+ /// comma separated list of milestone names or ids. It uses names and fall back to ids. Fetch only issues that have any of this milestones. Non existent milestones are discarded
+ pub milestones: Option<String>,
+ /// Only show items updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show items updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// Only show items which were created by the the given user
+ pub created_by: Option<String>,
+ /// Only show items for which the given user is assigned
+ pub assigned_by: Option<String>,
+ /// Only show items in which the given user was mentioned
+ pub mentioned_by: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueListIssuesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(state) = &self.state {
+ write!(f, "state={}&", state.as_str())?;
+ }
+ if let Some(labels) = &self.labels {
+ write!(f, "labels={labels}&")?;
+ }
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(r#type) = &self.r#type {
+ write!(f, "type={}&", r#type.as_str())?;
+ }
+ if let Some(milestones) = &self.milestones {
+ write!(f, "milestones={milestones}&")?;
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(created_by) = &self.created_by {
+ write!(f, "created_by={created_by}&")?;
+ }
+ if let Some(assigned_by) = &self.assigned_by {
+ write!(f, "assigned_by={assigned_by}&")?;
+ }
+ if let Some(mentioned_by) = &self.mentioned_by {
+ write!(f, "mentioned_by={mentioned_by}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum IssueListIssuesQueryState {
+ #[serde(rename = "closed")]
+ Closed,
+ #[serde(rename = "open")]
+ Open,
+ #[serde(rename = "all")]
+ All,
+}
+
+impl IssueListIssuesQueryState {
+ fn as_str(&self) -> &'static str {
+ match self {
+ IssueListIssuesQueryState::Closed => "closed",
+ IssueListIssuesQueryState::Open => "open",
+ IssueListIssuesQueryState::All => "all",
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum IssueListIssuesQueryType {
+ #[serde(rename = "issues")]
+ Issues,
+ #[serde(rename = "pulls")]
+ Pulls,
+}
+
+impl IssueListIssuesQueryType {
+ fn as_str(&self) -> &'static str {
+ match self {
+ IssueListIssuesQueryType::Issues => "issues",
+ IssueListIssuesQueryType::Pulls => "pulls",
+ }
+ }
+}
+pub struct IssueGetRepoCommentsQuery {
+ /// if provided, only comments updated since the provided time are returned.
+ pub since: Option<time::OffsetDateTime>,
+ /// if provided, only comments updated before the provided time are returned.
+ pub before: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueGetRepoCommentsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueCreateIssueCommentAttachmentQuery {
+ /// name of the attachment
+ pub name: Option<String>,
+ /// time of the attachment's creation. This is a timestamp in RFC 3339 format
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for IssueCreateIssueCommentAttachmentQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(name) = &self.name {
+ write!(f, "name={name}&")?;
+ }
+ if let Some(updated_at) = &self.updated_at {
+ write!(
+ f,
+ "updated_at={field_name}&",
+ field_name = updated_at
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueCreateIssueAttachmentQuery {
+ /// name of the attachment
+ pub name: Option<String>,
+ /// time of the attachment's creation. This is a timestamp in RFC 3339 format
+ pub updated_at: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for IssueCreateIssueAttachmentQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(name) = &self.name {
+ write!(f, "name={name}&")?;
+ }
+ if let Some(updated_at) = &self.updated_at {
+ write!(
+ f,
+ "updated_at={field_name}&",
+ field_name = updated_at
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueListBlocksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueListBlocksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueGetCommentsQuery {
+ /// if provided, only comments updated since the specified time are returned.
+ pub since: Option<time::OffsetDateTime>,
+ /// if provided, only comments updated before the provided time are returned.
+ pub before: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for IssueGetCommentsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueListIssueDependenciesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueListIssueDependenciesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueGetIssueReactionsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueGetIssueReactionsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueSubscriptionsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueSubscriptionsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueGetCommentsAndTimelineQuery {
+ /// if provided, only comments updated since the specified time are returned.
+ pub since: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+ /// if provided, only comments updated before the provided time are returned.
+ pub before: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for IssueGetCommentsAndTimelineQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueTrackedTimesQuery {
+ /// optional filter by user (available for issue managers)
+ pub user: Option<String>,
+ /// Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueTrackedTimesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(user) = &self.user {
+ write!(f, "user={user}&")?;
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListKeysQuery {
+ /// the key_id to search for
+ pub key_id: Option<u32>,
+ /// fingerprint of the key
+ pub fingerprint: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListKeysQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(key_id) = &self.key_id {
+ write!(f, "key_id={key_id}&")?;
+ }
+ if let Some(fingerprint) = &self.fingerprint {
+ write!(f, "fingerprint={fingerprint}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueListLabelsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueListLabelsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetRawFileOrLfsQuery {
+ /// The name of the commit/branch/tag. Default the repository’s default branch (usually master)
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetRawFileOrLfsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct IssueGetMilestonesListQuery {
+ /// Milestone state, Recognized values are open, closed and all. Defaults to "open"
+ pub state: Option<String>,
+ /// filter by milestone name
+ pub name: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for IssueGetMilestonesListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(state) = &self.state {
+ write!(f, "state={state}&")?;
+ }
+ if let Some(name) = &self.name {
+ write!(f, "name={name}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct NotifyGetRepoListQuery {
+ /// If true, show notifications marked as read. Default value is false
+ pub all: Option<bool>,
+ /// Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned
+ pub status_types: Option<Vec<String>>,
+ /// filter notifications by subject type
+ pub subject_type: Option<Vec<NotifyGetRepoListQuerySubjectType>>,
+ /// Only show notifications updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show notifications updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for NotifyGetRepoListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(all) = &self.all {
+ write!(f, "all={all}&")?;
+ }
+ if let Some(status_types) = &self.status_types {
+ if !status_types.is_empty() {
+ for item in status_types {
+ write!(f, "status-types=")?;
+ write!(f, "{item}")?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(subject_type) = &self.subject_type {
+ if !subject_type.is_empty() {
+ for item in subject_type {
+ write!(f, "subject-type=")?;
+ write!(f, "{}", item.as_str())?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum NotifyGetRepoListQuerySubjectType {
+ #[serde(rename = "issue")]
+ Issue,
+ #[serde(rename = "pull")]
+ Pull,
+ #[serde(rename = "commit")]
+ Commit,
+ #[serde(rename = "repository")]
+ Repository,
+}
+
+impl NotifyGetRepoListQuerySubjectType {
+ fn as_str(&self) -> &'static str {
+ match self {
+ NotifyGetRepoListQuerySubjectType::Issue => "issue",
+ NotifyGetRepoListQuerySubjectType::Pull => "pull",
+ NotifyGetRepoListQuerySubjectType::Commit => "commit",
+ NotifyGetRepoListQuerySubjectType::Repository => "repository",
+ }
+ }
+}
+pub struct NotifyReadRepoListQuery {
+ /// If true, mark all notifications on this repo. Default value is false
+ pub all: Option<String>,
+ /// Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread.
+ pub status_types: Option<Vec<String>>,
+ /// Status to mark notifications as. Defaults to read.
+ pub to_status: Option<String>,
+ /// Describes the last point that notifications were checked. Anything updated since this time will not be updated.
+ pub last_read_at: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for NotifyReadRepoListQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(all) = &self.all {
+ write!(f, "all={all}&")?;
+ }
+ if let Some(status_types) = &self.status_types {
+ if !status_types.is_empty() {
+ for item in status_types {
+ write!(f, "status-types=")?;
+ write!(f, "{item}")?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(to_status) = &self.to_status {
+ write!(f, "to-status={to_status}&")?;
+ }
+ if let Some(last_read_at) = &self.last_read_at {
+ write!(
+ f,
+ "last_read_at={field_name}&",
+ field_name = last_read_at
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListPullRequestsQuery {
+ /// State of pull request: open or closed (optional)
+ pub state: Option<RepoListPullRequestsQueryState>,
+ /// Type of sort
+ pub sort: Option<RepoListPullRequestsQuerySort>,
+ /// ID of the milestone
+ pub milestone: Option<u64>,
+ /// Label IDs
+ pub labels: Option<Vec<u64>>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListPullRequestsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(state) = &self.state {
+ write!(f, "state={}&", state.as_str())?;
+ }
+ if let Some(sort) = &self.sort {
+ write!(f, "sort={}&", sort.as_str())?;
+ }
+ if let Some(milestone) = &self.milestone {
+ write!(f, "milestone={milestone}&")?;
+ }
+ if let Some(labels) = &self.labels {
+ if !labels.is_empty() {
+ for item in labels {
+ write!(f, "labels=")?;
+ write!(f, "{item}")?;
+ write!(f, "&")?;
+ }
+ }
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListPullRequestsQueryState {
+ #[serde(rename = "closed")]
+ Closed,
+ #[serde(rename = "open")]
+ Open,
+ #[serde(rename = "all")]
+ All,
+}
+
+impl RepoListPullRequestsQueryState {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListPullRequestsQueryState::Closed => "closed",
+ RepoListPullRequestsQueryState::Open => "open",
+ RepoListPullRequestsQueryState::All => "all",
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListPullRequestsQuerySort {
+ #[serde(rename = "oldest")]
+ Oldest,
+ #[serde(rename = "recentupdate")]
+ Recentupdate,
+ #[serde(rename = "leastupdate")]
+ Leastupdate,
+ #[serde(rename = "mostcomment")]
+ Mostcomment,
+ #[serde(rename = "leastcomment")]
+ Leastcomment,
+ #[serde(rename = "priority")]
+ Priority,
+}
+
+impl RepoListPullRequestsQuerySort {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListPullRequestsQuerySort::Oldest => "oldest",
+ RepoListPullRequestsQuerySort::Recentupdate => "recentupdate",
+ RepoListPullRequestsQuerySort::Leastupdate => "leastupdate",
+ RepoListPullRequestsQuerySort::Mostcomment => "mostcomment",
+ RepoListPullRequestsQuerySort::Leastcomment => "leastcomment",
+ RepoListPullRequestsQuerySort::Priority => "priority",
+ }
+ }
+}
+pub struct RepoDownloadPullDiffOrPatchQuery {
+ /// whether to include binary file changes. if true, the diff is applicable with `git apply`
+ pub binary: Option<bool>,
+}
+
+impl std::fmt::Display for RepoDownloadPullDiffOrPatchQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(binary) = &self.binary {
+ write!(f, "binary={binary}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetPullRequestCommitsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+ /// include verification for every commit (disable for speedup, default 'true')
+ pub verification: Option<bool>,
+ /// include a list of affected files for every commit (disable for speedup, default 'true')
+ pub files: Option<bool>,
+}
+
+impl std::fmt::Display for RepoGetPullRequestCommitsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(verification) = &self.verification {
+ write!(f, "verification={verification}&")?;
+ }
+ if let Some(files) = &self.files {
+ write!(f, "files={files}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetPullRequestFilesQuery {
+ /// skip to given file
+ pub skip_to: Option<String>,
+ /// whitespace behavior
+ pub whitespace: Option<RepoGetPullRequestFilesQueryWhitespace>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoGetPullRequestFilesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(skip_to) = &self.skip_to {
+ write!(f, "skip-to={skip_to}&")?;
+ }
+ if let Some(whitespace) = &self.whitespace {
+ write!(f, "whitespace={}&", whitespace.as_str())?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoGetPullRequestFilesQueryWhitespace {
+ #[serde(rename = "ignore-all")]
+ IgnoreAll,
+ #[serde(rename = "ignore-change")]
+ IgnoreChange,
+ #[serde(rename = "ignore-eol")]
+ IgnoreEol,
+ #[serde(rename = "show-all")]
+ ShowAll,
+}
+
+impl RepoGetPullRequestFilesQueryWhitespace {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoGetPullRequestFilesQueryWhitespace::IgnoreAll => "ignore-all",
+ RepoGetPullRequestFilesQueryWhitespace::IgnoreChange => "ignore-change",
+ RepoGetPullRequestFilesQueryWhitespace::IgnoreEol => "ignore-eol",
+ RepoGetPullRequestFilesQueryWhitespace::ShowAll => "show-all",
+ }
+ }
+}
+pub struct RepoListPullReviewsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListPullReviewsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoUpdatePullRequestQuery {
+ /// how to update pull request
+ pub style: Option<RepoUpdatePullRequestQueryStyle>,
+}
+
+impl std::fmt::Display for RepoUpdatePullRequestQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(style) = &self.style {
+ write!(f, "style={}&", style.as_str())?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoUpdatePullRequestQueryStyle {
+ #[serde(rename = "merge")]
+ Merge,
+ #[serde(rename = "rebase")]
+ Rebase,
+}
+
+impl RepoUpdatePullRequestQueryStyle {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoUpdatePullRequestQueryStyle::Merge => "merge",
+ RepoUpdatePullRequestQueryStyle::Rebase => "rebase",
+ }
+ }
+}
+pub struct RepoListPushMirrorsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListPushMirrorsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetRawFileQuery {
+ /// The name of the commit/branch/tag. Default the repository’s default branch (usually master)
+ pub r#ref: Option<String>,
+}
+
+impl std::fmt::Display for RepoGetRawFileQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(r#ref) = &self.r#ref {
+ write!(f, "ref={ref}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListReleasesQuery {
+ /// filter (exclude / include) drafts, if you dont have repo write access none will show
+ pub draft: Option<bool>,
+ /// filter (exclude / include) pre-releases
+ pub pre_release: Option<bool>,
+ /// page size of results, deprecated - use limit
+ pub per_page: Option<u32>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListReleasesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(draft) = &self.draft {
+ write!(f, "draft={draft}&")?;
+ }
+ if let Some(pre_release) = &self.pre_release {
+ write!(f, "pre-release={pre_release}&")?;
+ }
+ if let Some(per_page) = &self.per_page {
+ write!(f, "per_page={per_page}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoCreateReleaseAttachmentQuery {
+ /// name of the attachment
+ pub name: Option<String>,
+}
+
+impl std::fmt::Display for RepoCreateReleaseAttachmentQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(name) = &self.name {
+ write!(f, "name={name}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListStargazersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListStargazersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListStatusesQuery {
+ /// type of sort
+ pub sort: Option<RepoListStatusesQuerySort>,
+ /// type of state
+ pub state: Option<RepoListStatusesQueryState>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListStatusesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(sort) = &self.sort {
+ write!(f, "sort={}&", sort.as_str())?;
+ }
+ if let Some(state) = &self.state {
+ write!(f, "state={}&", state.as_str())?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListStatusesQuerySort {
+ #[serde(rename = "oldest")]
+ Oldest,
+ #[serde(rename = "recentupdate")]
+ Recentupdate,
+ #[serde(rename = "leastupdate")]
+ Leastupdate,
+ #[serde(rename = "leastindex")]
+ Leastindex,
+ #[serde(rename = "highestindex")]
+ Highestindex,
+}
+
+impl RepoListStatusesQuerySort {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListStatusesQuerySort::Oldest => "oldest",
+ RepoListStatusesQuerySort::Recentupdate => "recentupdate",
+ RepoListStatusesQuerySort::Leastupdate => "leastupdate",
+ RepoListStatusesQuerySort::Leastindex => "leastindex",
+ RepoListStatusesQuerySort::Highestindex => "highestindex",
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
+pub enum RepoListStatusesQueryState {
+ #[serde(rename = "pending")]
+ Pending,
+ #[serde(rename = "success")]
+ Success,
+ #[serde(rename = "error")]
+ Error,
+ #[serde(rename = "failure")]
+ Failure,
+ #[serde(rename = "warning")]
+ Warning,
+}
+
+impl RepoListStatusesQueryState {
+ fn as_str(&self) -> &'static str {
+ match self {
+ RepoListStatusesQueryState::Pending => "pending",
+ RepoListStatusesQueryState::Success => "success",
+ RepoListStatusesQueryState::Error => "error",
+ RepoListStatusesQueryState::Failure => "failure",
+ RepoListStatusesQueryState::Warning => "warning",
+ }
+ }
+}
+pub struct RepoListSubscribersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListSubscribersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListTagsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results, default maximum page size is 50
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListTagsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoTrackedTimesQuery {
+ /// optional filter by user (available for issue managers)
+ pub user: Option<String>,
+ /// Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoTrackedTimesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(user) = &self.user {
+ write!(f, "user={user}&")?;
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoListTopicsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoListTopicsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetWikiPagesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for RepoGetWikiPagesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct RepoGetWikiPageRevisionsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+}
+
+impl std::fmt::Display for RepoGetWikiPageRevisionsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListTeamActivityFeedsQuery {
+ /// the date of the activities to be found
+ pub date: Option<time::Date>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListTeamActivityFeedsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(date) = &self.date {
+ write!(
+ f,
+ "date={field_name}&",
+ field_name = date
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListTeamMembersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListTeamMembersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListTeamReposQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListTeamReposQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct TopicSearchQuery {
+ /// keywords to search
+ pub q: String,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for TopicSearchQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let q = &self.q;
+ write!(f, "q={q}&")?;
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserGetOAuth2ApplicationsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserGetOAuth2ApplicationsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListFollowersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListFollowersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListFollowingQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListFollowingQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListGpgKeysQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListGpgKeysQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListHooksQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListHooksQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListKeysQuery {
+ /// fingerprint of the key
+ pub fingerprint: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListKeysQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(fingerprint) = &self.fingerprint {
+ write!(f, "fingerprint={fingerprint}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListBlockedUsersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListBlockedUsersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListCurrentUserOrgsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListCurrentUserOrgsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListReposQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListReposQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListStarredQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListStarredQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserGetStopWatchesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserGetStopWatchesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentListSubscriptionsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserCurrentListSubscriptionsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListTeamsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListTeamsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserCurrentTrackedTimesQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+ /// Only show times updated after the given time. This is a timestamp in RFC 3339 format
+ pub since: Option<time::OffsetDateTime>,
+ /// Only show times updated before the given time. This is a timestamp in RFC 3339 format
+ pub before: Option<time::OffsetDateTime>,
+}
+
+impl std::fmt::Display for UserCurrentTrackedTimesQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+ if let Some(since) = &self.since {
+ write!(
+ f,
+ "since={field_name}&",
+ field_name = since
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(before) = &self.before {
+ write!(
+ f,
+ "before={field_name}&",
+ field_name = before
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserSearchQuery {
+ /// keyword
+ pub q: Option<String>,
+ /// ID of the user to search for
+ pub uid: Option<u64>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserSearchQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(q) = &self.q {
+ write!(f, "q={q}&")?;
+ }
+ if let Some(uid) = &self.uid {
+ write!(f, "uid={uid}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
+pub struct UserSearchResponse {
+ pub data: Option<Vec<User>>,
+ pub ok: Option<bool>,
+}
+
+pub struct UserListActivityFeedsQuery {
+ /// if true, only show actions performed by the requested user
+ pub only_performed_by: Option<bool>,
+ /// the date of the activities to be found
+ pub date: Option<time::Date>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListActivityFeedsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(only_performed_by) = &self.only_performed_by {
+ write!(f, "only-performed-by={only_performed_by}&")?;
+ }
+ if let Some(date) = &self.date {
+ write!(
+ f,
+ "date={field_name}&",
+ field_name = date
+ .format(&time::format_description::well_known::Rfc3339)
+ .unwrap()
+ )?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListFollowersQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListFollowersQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListFollowingQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListFollowingQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListGpgKeysQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListGpgKeysQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListKeysQuery {
+ /// fingerprint of the key
+ pub fingerprint: Option<String>,
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListKeysQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(fingerprint) = &self.fingerprint {
+ write!(f, "fingerprint={fingerprint}&")?;
+ }
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct OrgListUserOrgsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for OrgListUserOrgsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListReposQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListReposQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListStarredQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListStarredQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserListSubscriptionsQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserListSubscriptionsQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
+
+pub struct UserGetTokensQuery {
+ /// page number of results to return (1-based)
+ pub page: Option<u32>,
+ /// page size of results
+ pub limit: Option<u32>,
+}
+
+impl std::fmt::Display for UserGetTokensQuery {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ if let Some(page) = &self.page {
+ write!(f, "page={page}&")?;
+ }
+ if let Some(limit) = &self.limit {
+ write!(f, "limit={limit}&")?;
+ }
+
+ Ok(())
+ }
+}
diff --git a/src/issue.rs b/src/issue.rs
deleted file mode 100644
index 71f2fd5..0000000
--- a/src/issue.rs
+++ /dev/null
@@ -1,347 +0,0 @@
-use super::*;
-
-impl Forgejo {
- pub async fn get_repo_issues(
- &self,
- owner: &str,
- repo: &str,
- query: IssueQuery,
- ) -> Result<Vec<Issue>, ForgejoError> {
- self.get(&query.to_string(owner, repo)).await
- }
-
- pub async fn create_issue(
- &self,
- owner: &str,
- repo: &str,
- opts: CreateIssueOption,
- ) -> Result<Issue, ForgejoError> {
- self.post(&format!("repos/{owner}/{repo}/issues"), &opts)
- .await
- }
-
- pub async fn get_issue(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<Option<Issue>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/issues/{id}"))
- .await
- }
-
- pub async fn delete_issue(&self, owner: &str, repo: &str, id: u64) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/issues/{id}"))
- .await
- }
-
- pub async fn edit_issue(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- opts: EditIssueOption,
- ) -> Result<Issue, ForgejoError> {
- self.patch(&format!("repos/{owner}/{repo}/issues/{id}"), &opts)
- .await
- }
-
- pub async fn get_repo_comments(
- &self,
- owner: &str,
- repo: &str,
- query: RepoCommentQuery,
- ) -> Result<Vec<Comment>, ForgejoError> {
- self.get(&query.to_string(owner, repo)).await
- }
-
- pub async fn get_issue_comments(
- &self,
- owner: &str,
- repo: &str,
- issue_id: u64,
- query: IssueCommentQuery,
- ) -> Result<Vec<Comment>, ForgejoError> {
- self.get(&query.to_string(owner, repo, issue_id)).await
- }
-
- pub async fn create_comment(
- &self,
- owner: &str,
- repo: &str,
- issue_id: u64,
- opts: CreateIssueCommentOption,
- ) -> Result<Comment, ForgejoError> {
- self.post(
- &format!("repos/{owner}/{repo}/issues/{issue_id}/comments"),
- &opts,
- )
- .await
- }
-
- pub async fn get_comment(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<Option<Comment>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
- .await
- }
-
- pub async fn delete_comment(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/issues/comments/{id}"))
- .await
- }
-
- pub async fn edit_comment(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- opts: EditIssueCommentOption,
- ) -> Result<Comment, ForgejoError> {
- self.patch(&format!("repos/{owner}/{repo}/issues/comments/{id}"), &opts)
- .await
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Issue {
- pub assets: Vec<Attachment>,
- pub assignee: Option<User>,
- pub assignees: Option<Vec<User>>,
- pub body: String,
- #[serde(with = "time::serde::rfc3339::option")]
- pub closed_at: Option<time::OffsetDateTime>,
- pub comments: u64,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_date: Option<time::OffsetDateTime>,
- pub html_url: Url,
- pub id: u64,
- pub is_locked: bool,
- pub labels: Vec<Label>,
- pub milestone: Option<Milestone>,
- pub number: u64,
- pub original_author: String,
- pub original_author_id: u64,
- pub pin_order: u64,
- pub pull_request: Option<PullRequestMeta>,
- #[serde(rename = "ref")]
- pub _ref: String,
- pub repository: RepositoryMeta,
- pub state: State,
- pub title: String,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
- pub url: Url,
- pub user: User,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Label {
- pub color: String,
- pub description: String,
- pub exclusive: bool,
- pub id: u64,
- pub name: String,
- pub url: Url,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Attachment {
- pub browser_download_url: Url,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub download_count: u64,
- pub id: u64,
- pub name: String,
- pub size: u64,
- pub uuid: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditAttachmentOption {
- pub name: Option<String>,
-}
-
-#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Copy)]
-pub enum State {
- #[serde(rename = "open")]
- Open,
- #[serde(rename = "closed")]
- Closed,
-}
-
-impl State {
- pub(crate) fn as_str(&self) -> &'static str {
- match self {
- State::Open => "open",
- State::Closed => "closed",
- }
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Comment {
- pub assets: Vec<Attachment>,
- pub body: String,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub html_url: Url,
- pub id: u64,
- pub issue_url: Url,
- pub original_author: String,
- pub original_author_id: u64,
- #[serde(deserialize_with = "crate::none_if_blank_url")]
- pub pull_request_url: Option<Url>,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
- pub user: User,
-}
-
-#[derive(Default, Debug)]
-pub struct IssueQuery {
- pub state: Option<State>,
- pub labels: Vec<String>,
- pub query: Option<String>,
- pub _type: Option<IssueQueryType>,
- pub milestones: Vec<String>,
- pub since: Option<time::OffsetDateTime>,
- pub before: Option<time::OffsetDateTime>,
- pub created_by: Option<String>,
- pub assigned_by: Option<String>,
- pub mentioned_by: Option<String>,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl IssueQuery {
- fn to_string(&self, owner: &str, repo: &str) -> String {
- format!("repos/{owner}/{repo}/issues?state={}&labels={}&q={}&type={}&milestones={}&since={}&before={}&created_by={}&assigned_by={}&mentioned_by={}&page={}&limit={}",
- self.state.map(|s| s.as_str()).unwrap_or_default(),
- self.labels.join(","),
- self.query.as_deref().unwrap_or_default(),
- self._type.map(|t| t.as_str()).unwrap_or_default(),
- self.milestones.join(","),
- self.since.map(|t| t.format(&time::format_description::well_known::Rfc3339).unwrap()).unwrap_or_default(),
- self.before.map(|t| t.format(&time::format_description::well_known::Rfc3339).unwrap()).unwrap_or_default(),
- self.created_by.as_deref().unwrap_or_default(),
- self.assigned_by.as_deref().unwrap_or_default(),
- self.mentioned_by.as_deref().unwrap_or_default(),
- self.page.map(|page| page.to_string()).unwrap_or_default(),
- self.limit.map(|page| page.to_string()).unwrap_or_default(),
- )
- }
-}
-
-#[derive(Debug, PartialEq, Clone, Copy)]
-pub enum IssueQueryType {
- Issues,
- Pulls,
-}
-
-impl IssueQueryType {
- fn as_str(&self) -> &'static str {
- match self {
- IssueQueryType::Issues => "issues",
- IssueQueryType::Pulls => "pulls",
- }
- }
-}
-
-#[derive(Default, Debug)]
-pub struct IssueCommentQuery {
- pub since: Option<time::OffsetDateTime>,
- pub before: Option<time::OffsetDateTime>,
-}
-
-impl IssueCommentQuery {
- fn to_string(&self, owner: &str, repo: &str, issue_id: u64) -> String {
- format!(
- "repos/{owner}/{repo}/issues/{issue_id}/comments?since={}&before={}",
- self.since
- .map(|t| t
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap())
- .unwrap_or_default(),
- self.before
- .map(|t| t
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap())
- .unwrap_or_default(),
- )
- }
-}
-
-#[derive(Default, Debug)]
-pub struct RepoCommentQuery {
- pub since: Option<time::OffsetDateTime>,
- pub before: Option<time::OffsetDateTime>,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl RepoCommentQuery {
- fn to_string(&self, owner: &str, repo: &str) -> String {
- format!(
- "repos/{owner}/{repo}/issues/comments?since={}&before={}&page={}&limit={}",
- self.since
- .map(|t| t
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap())
- .unwrap_or_default(),
- self.before
- .map(|t| t
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap())
- .unwrap_or_default(),
- self.page.map(|page| page.to_string()).unwrap_or_default(),
- self.limit.map(|page| page.to_string()).unwrap_or_default(),
- )
- }
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct CreateIssueOption {
- pub assignees: Vec<String>,
- pub body: Option<String>,
- pub closed: Option<bool>,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_date: Option<time::OffsetDateTime>,
- pub labels: Vec<u64>,
- pub milestone: Option<u64>,
- pub _ref: Option<String>,
- pub title: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditIssueOption {
- pub assignees: Vec<String>,
- pub body: Option<String>,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_date: Option<time::OffsetDateTime>,
- pub labels: Vec<u64>,
- pub milestone: Option<u64>,
- pub _ref: Option<String>,
- pub state: Option<State>,
- pub title: Option<String>,
- pub unset_due_date: Option<bool>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct CreateIssueCommentOption {
- pub body: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditIssueCommentOption {
- pub body: String,
-}
diff --git a/src/lib.rs b/src/lib.rs
index 1776812..161aac1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,4 @@
use reqwest::{Client, Request, StatusCode};
-use serde::{de::DeserializeOwned, Serialize};
use soft_assert::*;
use url::Url;
use zeroize::Zeroize;
@@ -9,23 +8,9 @@ pub struct Forgejo {
client: Client,
}
-mod admin;
-mod issue;
-mod misc;
-mod notification;
-mod organization;
-mod package;
-mod repository;
-mod user;
-
-pub use admin::*;
-pub use issue::*;
-pub use misc::*;
-pub use notification::*;
-pub use organization::*;
-pub use package::*;
-pub use repository::*;
-pub use user::*;
+mod generated;
+
+pub use generated::structs;
#[derive(thiserror::Error, Debug)]
pub enum ForgejoError {
@@ -38,15 +23,30 @@ pub enum ForgejoError {
#[error("API key should be ascii")]
KeyNotAscii,
#[error("the response from forgejo was not properly structured")]
- BadStructure(#[source] serde_json::Error, String),
+ BadStructure(#[from] StructureError),
#[error("unexpected status code {} {}", .0.as_u16(), .0.canonical_reason().unwrap_or(""))]
UnexpectedStatusCode(StatusCode),
- #[error("{} {}: {}", .0.as_u16(), .0.canonical_reason().unwrap_or(""), .1)]
- ApiError(StatusCode, String),
+ #[error("{} {}{}", .0.as_u16(), .0.canonical_reason().unwrap_or(""), .1.as_ref().map(|s| format!(": {s}")).unwrap_or_default())]
+ ApiError(StatusCode, Option<String>),
#[error("the provided authorization was too long to accept")]
AuthTooLong,
}
+#[derive(thiserror::Error, Debug)]
+pub enum StructureError {
+ #[error("{contents}")]
+ Serde {
+ e: serde_json::Error,
+ contents: String,
+ },
+ #[error("failed to find header `{0}`")]
+ HeaderMissing(&'static str),
+ #[error("header was not ascii")]
+ HeaderNotAscii,
+ #[error("failed to parse header")]
+ HeaderParseFailed,
+}
+
/// Method of authentication to connect to the Forgejo host with.
pub enum Auth<'a> {
/// Application Access Token. Grants access to scope enabled for the
@@ -134,218 +134,67 @@ impl Forgejo {
Ok(Self { url, client })
}
- async fn get<T: DeserializeOwned>(&self, path: &str) -> Result<T, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.get(url).build()?;
- self.execute(request).await
- }
-
- async fn get_opt<T: DeserializeOwned>(&self, path: &str) -> Result<Option<T>, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.get(url).build()?;
- self.execute_opt(request).await
- }
-
- async fn get_str(&self, path: &str) -> Result<String, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.get(url).build()?;
- self.execute_str(request).await
- }
-
- async fn get_exists(&self, path: &str) -> Result<bool, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.get(url).build()?;
- self.execute_exists(request).await
- }
-
- async fn post<T: Serialize, U: DeserializeOwned>(
- &self,
- path: &str,
- body: &T,
- ) -> Result<U, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.post(url).json(body).build()?;
- self.execute(request).await
- }
-
- async fn post_multipart<T: DeserializeOwned>(
+ pub async fn download_release_attachment(
&self,
- path: &str,
- body: reqwest::multipart::Form,
- ) -> Result<T, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.post(url).multipart(body).build()?;
- self.execute(request).await
- }
-
- async fn post_str_out<T: Serialize>(
- &self,
- path: &str,
- body: &T,
- ) -> Result<String, ForgejoError> {
- let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.post(url).json(body).build()?;
- self.execute_str(request).await
+ owner: &str,
+ repo: &str,
+ release: u64,
+ attach: u64,
+ ) -> Result<bytes::Bytes, ForgejoError> {
+ let release = self
+ .repo_get_release_attachment(owner, repo, release, attach)
+ .await?;
+ let request = self
+ .client
+ .get(format!("/attachments/{}", release.uuid.unwrap()))
+ .build()?;
+ Ok(self.execute(request).await?.bytes().await?)
}
- async fn post_unit<T: Serialize>(&self, path: &str, body: &T) -> Result<(), ForgejoError> {
+ fn get(&self, path: &str) -> reqwest::RequestBuilder {
let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.post(url).json(body).build()?;
- self.execute_unit(request).await
+ self.client.get(url)
}
- async fn post_raw(&self, path: &str, body: String) -> Result<String, ForgejoError> {
+ fn put(&self, path: &str) -> reqwest::RequestBuilder {
let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.post(url).body(body).build()?;
- self.execute_str(request).await
+ self.client.put(url)
}
- async fn delete(&self, path: &str) -> Result<(), ForgejoError> {
+ fn post(&self, path: &str) -> reqwest::RequestBuilder {
let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.delete(url).build()?;
- self.execute_unit(request).await
+ self.client.post(url)
}
- async fn patch<T: Serialize, U: DeserializeOwned>(
- &self,
- path: &str,
- body: &T,
- ) -> Result<U, ForgejoError> {
+ fn delete(&self, path: &str) -> reqwest::RequestBuilder {
let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.patch(url).json(body).build()?;
- self.execute(request).await
+ self.client.delete(url)
}
- async fn put<T: DeserializeOwned>(&self, path: &str) -> Result<T, ForgejoError> {
+ fn patch(&self, path: &str) -> reqwest::RequestBuilder {
let url = self.url.join("api/v1/").unwrap().join(path).unwrap();
- let request = self.client.put(url).build()?;
- self.execute(request).await
+ self.client.patch(url)
}
- async fn execute<T: DeserializeOwned>(&self, request: Request) -> Result<T, ForgejoError> {
+ async fn execute(&self, request: Request) -> Result<reqwest::Response, ForgejoError> {
let response = self.client.execute(request).await?;
match response.status() {
- status if status.is_success() => {
- let body = response.text().await?;
- let out =
- serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?;
- Ok(out)
+ status if status.is_success() => Ok(response),
+ status if status.is_client_error() => {
+ Err(ForgejoError::ApiError(status, maybe_err(response).await))
}
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
- status => Err(ForgejoError::UnexpectedStatusCode(status)),
- }
- }
-
- /// Like `execute`, but returns a `String`.
- async fn execute_opt_raw(
- &self,
- request: Request,
- ) -> Result<Option<bytes::Bytes>, ForgejoError> {
- let response = self.client.execute(request).await?;
- match response.status() {
- status if status.is_success() => Ok(Some(response.bytes().await?)),
- StatusCode::NOT_FOUND => Ok(None),
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
- status => Err(ForgejoError::UnexpectedStatusCode(status)),
- }
- }
-
- /// Like `execute`, but returns a `String`.
- async fn execute_str(&self, request: Request) -> Result<String, ForgejoError> {
- let response = self.client.execute(request).await?;
- match response.status() {
- status if status.is_success() => Ok(response.text().await?),
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
- status => Err(ForgejoError::UnexpectedStatusCode(status)),
- }
- }
-
- /// Like `execute`, but returns unit.
- async fn execute_unit(&self, request: Request) -> Result<(), ForgejoError> {
- let response = self.client.execute(request).await?;
- match response.status() {
- status if status.is_success() => Ok(()),
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
- status => Err(ForgejoError::UnexpectedStatusCode(status)),
- }
- }
-
- /// Like `execute`, but returns `Ok(None)` on 404.
- async fn execute_opt<T: DeserializeOwned>(
- &self,
- request: Request,
- ) -> Result<Option<T>, ForgejoError> {
- let response = self.client.execute(request).await?;
- match response.status() {
- status if status.is_success() => {
- let body = response.text().await?;
- let out =
- serde_json::from_str(&body).map_err(|e| ForgejoError::BadStructure(e, body))?;
- Ok(out)
- }
- StatusCode::NOT_FOUND => Ok(None),
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
status => Err(ForgejoError::UnexpectedStatusCode(status)),
}
}
+}
- /// Like `execute`, but returns `false` on 404.
- async fn execute_exists(&self, request: Request) -> Result<bool, ForgejoError> {
- let response = self.client.execute(request).await?;
- match response.status() {
- status if status.is_success() => Ok(true),
- StatusCode::NOT_FOUND => Ok(false),
- status if status.is_client_error() => Err(ForgejoError::ApiError(
- status,
- response
- .json::<ErrorMessage>()
- .await?
- .message
- .unwrap_or_else(|| String::from("[no message]")),
- )),
- status => Err(ForgejoError::UnexpectedStatusCode(status)),
- }
- }
+async fn maybe_err(res: reqwest::Response) -> Option<String> {
+ res.json::<ErrorMessage>().await.ok().map(|e| e.message)
}
#[derive(serde::Deserialize)]
struct ErrorMessage {
- message: Option<String>,
+ message: String,
// intentionally ignored, no need for now
// url: Url
}
diff --git a/src/misc.rs b/src/misc.rs
deleted file mode 100644
index 76fc3b8..0000000
--- a/src/misc.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-use super::*;
-
-impl Forgejo {
- pub async fn get_gitignore_templates(&self) -> Result<Vec<String>, ForgejoError> {
- self.get("gitignore/templates").await
- }
-
- pub async fn get_gitignore_template(
- &self,
- name: &str,
- ) -> Result<Option<GitignoreTemplateInfo>, ForgejoError> {
- self.get_opt(&format!("gitignore/templates/{name}")).await
- }
-
- pub async fn get_label_templates(&self) -> Result<Vec<String>, ForgejoError> {
- self.get("label/templates").await
- }
-
- pub async fn get_label_template(&self, name: &str) -> Result<Vec<LabelTemplate>, ForgejoError> {
- self.get(&format!("label/templates/{name}")).await
- }
-
- pub async fn get_licenses(&self) -> Result<Vec<LicenseTemplateListEntry>, ForgejoError> {
- self.get("licenses").await
- }
-
- pub async fn get_license(
- &self,
- name: &str,
- ) -> Result<Option<GitignoreTemplateInfo>, ForgejoError> {
- self.get_opt(&format!("license/{name}")).await
- }
-
- pub async fn render_markdown(&self, opt: MarkdownOption) -> Result<String, ForgejoError> {
- self.post_str_out("markdown", &opt).await
- }
-
- pub async fn render_markdown_raw(&self, body: String) -> Result<String, ForgejoError> {
- self.post_raw("markdown/raw", body).await
- }
-
- pub async fn render_markup(&self, opt: MarkupOption) -> Result<String, ForgejoError> {
- self.post_str_out("markup", &opt).await
- }
-
- pub async fn nodeinfo(&self) -> Result<NodeInfo, ForgejoError> {
- self.get("nodeinfo").await
- }
-
- pub async fn signing_key(&self) -> Result<String, ForgejoError> {
- self.get_str("signing-key.gpg").await
- }
-
- pub async fn version(&self) -> Result<ServerVersion, ForgejoError> {
- self.get("version").await
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct GitignoreTemplateInfo {
- pub name: String,
- pub source: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct LabelTemplate {
- pub color: String,
- pub description: String,
- pub exclusive: bool,
- pub name: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct LicenseTemplateListEntry {
- pub key: String,
- pub name: String,
- pub url: Url,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct LicenseTemplateInfo {
- pub body: String,
- pub implementation: String,
- pub key: String,
- pub name: String,
- pub url: Url,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct MarkdownOption {
- #[serde(rename = "Context")]
- pub context: String,
- #[serde(rename = "Mode")]
- pub mode: String,
- #[serde(rename = "Text")]
- pub text: String,
- #[serde(rename = "Wiki")]
- pub wiki: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct MarkupOption {
- #[serde(rename = "Context")]
- pub context: String,
- #[serde(rename = "FilePath")]
- pub file_path: String,
- #[serde(rename = "Mode")]
- pub mode: String,
- #[serde(rename = "Text")]
- pub text: String,
- #[serde(rename = "Wiki")]
- pub wiki: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NodeInfo {
- pub metadata: std::collections::BTreeMap<String, String>,
- #[serde(rename = "openRegistrations")]
- pub open_registrations: bool,
- pub protocols: Vec<String>,
- pub services: NodeInfoServices,
- pub software: NodeInfoSoftware,
- pub usage: NodeInfoUsage,
- pub version: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NodeInfoServices {
- pub inbound: Vec<String>,
- pub outbound: Vec<String>,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NodeInfoSoftware {
- pub homepage: Url,
- pub name: String,
- pub repository: Url,
- pub version: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NodeInfoUsage {
- #[serde(rename = "localComments")]
- pub local_comments: u64,
- #[serde(rename = "localPosts")]
- pub local_posts: u64,
- pub users: NodeInfoUsageUsers,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NodeInfoUsageUsers {
- #[serde(rename = "activeHalfYear")]
- pub active_half_year: u64,
- #[serde(rename = "activeMonth")]
- pub active_month: u64,
- pub total: u64,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct ServerVersion {
- pub version: String,
-}
diff --git a/src/notification.rs b/src/notification.rs
deleted file mode 100644
index 348363a..0000000
--- a/src/notification.rs
+++ /dev/null
@@ -1,273 +0,0 @@
-use super::*;
-
-impl Forgejo {
- pub async fn notifications(
- &self,
- query: NotificationQuery,
- ) -> Result<Vec<NotificationThread>, ForgejoError> {
- self.get(&format!("notifications?{}", query.query_string()))
- .await
- }
-
- pub async fn set_notifications_state(
- &self,
- query: NotificationPutQuery,
- ) -> Result<Vec<NotificationThread>, ForgejoError> {
- self.put(&format!("notifications?{}", query.query_string()))
- .await
- }
-
- pub async fn notification_count(&self) -> Result<Vec<NotificationCount>, ForgejoError> {
- self.get("notifications/new").await
- }
-
- pub async fn get_notification(
- &self,
- id: u64,
- ) -> Result<Option<NotificationThread>, ForgejoError> {
- self.get_opt(&format!("notifications/threads/{id}")).await
- }
-
- pub async fn set_notification_state(
- &self,
- id: u64,
- to_status: ToStatus,
- ) -> Result<Option<NotificationThread>, ForgejoError> {
- self.patch(
- &format!(
- "notifications/threads/{id}?to-status={}",
- to_status.as_str()
- ),
- &(),
- )
- .await
- }
-
- pub async fn get_repo_notifications(
- &self,
- owner: &str,
- name: &str,
- query: NotificationQuery,
- ) -> Result<Vec<NotificationThread>, ForgejoError> {
- self.get(&format!(
- "repos/{owner}/{name}/notifications?{}",
- query.query_string()
- ))
- .await
- }
-
- pub async fn set_repo_notifications_state(
- &self,
- owner: &str,
- name: &str,
- query: NotificationPutQuery,
- ) -> Result<Vec<NotificationThread>, ForgejoError> {
- self.put(&format!(
- "repos/{owner}/{name}/notifications?{}",
- query.query_string()
- ))
- .await
- }
-}
-
-#[derive(Debug)]
-pub struct NotificationQuery {
- pub all: bool,
- pub include_unread: bool,
- pub include_read: bool,
- pub include_pinned: bool,
- pub subject_type: Option<NotificationSubjectType>,
- pub since: Option<time::OffsetDateTime>,
- pub before: Option<time::OffsetDateTime>,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl Default for NotificationQuery {
- fn default() -> Self {
- NotificationQuery {
- all: false,
- include_unread: true,
- include_read: false,
- include_pinned: true,
- subject_type: None,
- since: None,
- before: None,
- page: None,
- limit: None,
- }
- }
-}
-
-impl NotificationQuery {
- fn query_string(&self) -> String {
- use std::fmt::Write;
- let mut s = String::new();
- if self.all {
- s.push_str("all=true&");
- }
- if self.include_unread {
- s.push_str("status-types=unread&");
- }
- if self.include_read {
- s.push_str("status-types=read&");
- }
- if self.include_pinned {
- s.push_str("status-types=pinned&");
- }
- if let Some(subject_type) = self.subject_type {
- s.push_str("subject-type=");
- s.push_str(subject_type.as_str());
- s.push('&');
- }
- if let Some(since) = &self.since {
- s.push_str("since=");
- s.push_str(
- &since
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap(),
- );
- s.push('&');
- }
- if let Some(before) = &self.before {
- s.push_str("before=");
- s.push_str(
- &before
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap(),
- );
- s.push('&');
- }
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to a string never fails");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to a string never fails");
- }
- s
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-pub enum NotificationSubjectType {
- Issue,
- Pull,
- Commit,
- Repository,
-}
-
-impl NotificationSubjectType {
- fn as_str(&self) -> &'static str {
- match self {
- NotificationSubjectType::Issue => "issue",
- NotificationSubjectType::Pull => "pull",
- NotificationSubjectType::Commit => "commit",
- NotificationSubjectType::Repository => "repository",
- }
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NotificationThread {
- pub id: u64,
- pub pinned: bool,
- pub repository: Repository,
- pub subject: NotificationSubject,
- pub unread: bool,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
- pub url: Url,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NotificationSubject {
- pub html_url: Url,
- pub latest_comment_html_url: Url,
- pub latest_comment_url: Url,
- pub state: String,
- pub title: String,
- #[serde(rename = "type")]
- pub _type: String,
- pub url: Url,
-}
-
-#[derive(Debug)]
-pub struct NotificationPutQuery {
- pub last_read_at: Option<time::OffsetDateTime>,
- pub all: bool,
- pub include_unread: bool,
- pub include_read: bool,
- pub include_pinned: bool,
- pub to_status: ToStatus,
-}
-
-impl Default for NotificationPutQuery {
- fn default() -> Self {
- NotificationPutQuery {
- last_read_at: None,
- all: false,
- include_unread: true,
- include_read: false,
- include_pinned: false,
- to_status: ToStatus::default(),
- }
- }
-}
-
-impl NotificationPutQuery {
- fn query_string(&self) -> String {
- let mut s = String::new();
- if let Some(last_read_at) = &self.last_read_at {
- s.push_str("since=");
- s.push_str(
- &last_read_at
- .format(&time::format_description::well_known::Rfc3339)
- .unwrap(),
- );
- s.push('&');
- }
- if self.all {
- s.push_str("all=true&");
- }
- if self.include_unread {
- s.push_str("status-types=unread&");
- }
- if self.include_read {
- s.push_str("status-types=read&");
- }
- if self.include_pinned {
- s.push_str("status-types=pinned&");
- }
- s.push_str("subject-type=");
- s.push_str(self.to_status.as_str());
- s
- }
-}
-
-#[derive(Default, Debug)]
-pub enum ToStatus {
- #[default]
- Read,
- Unread,
- Pinned,
-}
-
-impl ToStatus {
- fn as_str(&self) -> &'static str {
- match self {
- ToStatus::Read => "read",
- ToStatus::Unread => "unread",
- ToStatus::Pinned => "pinned",
- }
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct NotificationCount {
- pub new: u64,
-}
diff --git a/src/organization.rs b/src/organization.rs
deleted file mode 100644
index 6a54f10..0000000
--- a/src/organization.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use crate::*;
-use std::collections::BTreeMap;
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Organization {
- #[serde(deserialize_with = "crate::none_if_blank_url")]
- pub avatar_url: Option<Url>,
- pub description: String,
- pub full_name: String,
- pub id: u64,
- pub location: Option<String>,
- pub name: String,
- pub repo_admin_change_team_access: bool,
- pub visibility: String,
- #[serde(deserialize_with = "crate::none_if_blank_url")]
- pub website: Option<Url>,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Team {
- pub can_create_org_repo: bool,
- pub description: String,
- pub id: u64,
- pub includes_all_repositories: bool,
- pub name: String,
- pub organization: Organization,
- pub permission: String,
- pub units: Vec<String>,
- pub units_map: BTreeMap<String, String>,
-}
diff --git a/src/package.rs b/src/package.rs
deleted file mode 100644
index 4c49d5b..0000000
--- a/src/package.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-use std::fmt::Write;
-
-use super::*;
-
-impl Forgejo {
- pub async fn get_user_packages(
- &self,
- owner: &str,
- query: PackagesQuery,
- ) -> Result<Vec<Package>, ForgejoError> {
- self.get(&query.path(owner)).await
- }
-
- pub async fn get_package(
- &self,
- owner: &str,
- _type: PackageType,
- name: &str,
- version: &str,
- ) -> Result<Option<Package>, ForgejoError> {
- self.get_opt(&format!(
- "packages/{owner}/{}/{name}/{version}",
- _type.as_str()
- ))
- .await
- }
-
- pub async fn delete_package(
- &self,
- owner: &str,
- _type: PackageType,
- name: &str,
- version: &str,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!(
- "packages/{owner}/{}/{name}/{version}",
- _type.as_str()
- ))
- .await
- }
-
- pub async fn get_package_files(
- &self,
- owner: &str,
- _type: PackageType,
- name: &str,
- version: &str,
- ) -> Result<Vec<PackageFile>, ForgejoError> {
- self.get(&format!(
- "packages/{owner}/{}/{name}/{version}",
- _type.as_str()
- ))
- .await
- }
-}
-
-#[derive(Default, Debug)]
-pub struct PackagesQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
- pub kind: Option<PackageType>,
- pub query: String,
-}
-
-impl PackagesQuery {
- fn path(&self, owner: &str) -> String {
- let mut s = String::from("packages/");
- s.push_str(owner);
- s.push('?');
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to string can't fail");
- s.push('&');
- }
- if let Some(kind) = self.kind {
- s.push_str("type=");
- s.push_str(kind.as_str());
- s.push('&');
- }
- if !self.query.is_empty() {
- s.push_str("q=");
- s.push_str(&self.query);
- s.push('&');
- }
- s
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
-#[serde(rename_all = "lowercase")]
-#[non_exhaustive]
-pub enum PackageType {
- Alpine,
- Cargo,
- Chef,
- Composer,
- Conan,
- Conda,
- Container,
- Cran,
- Debian,
- Generic,
- Go,
- Helm,
- Maven,
- Npm,
- Nuget,
- Pub,
- Pypi,
- Rpm,
- RubyGems,
- Swift,
- Vagrant,
-}
-
-impl PackageType {
- fn as_str(&self) -> &'static str {
- match self {
- PackageType::Alpine => "alpine",
- PackageType::Cargo => "cargo",
- PackageType::Chef => "chef",
- PackageType::Composer => "composer",
- PackageType::Conan => "conan",
- PackageType::Conda => "conda",
- PackageType::Container => "container",
- PackageType::Cran => "cran",
- PackageType::Debian => "debian",
- PackageType::Generic => "generic",
- PackageType::Go => "go",
- PackageType::Helm => "helm",
- PackageType::Maven => "maven",
- PackageType::Npm => "npm",
- PackageType::Nuget => "nuget",
- PackageType::Pub => "pub",
- PackageType::Pypi => "pypi",
- PackageType::Rpm => "rpm",
- PackageType::RubyGems => "rubygems",
- PackageType::Swift => "swift",
- PackageType::Vagrant => "vagrant",
- }
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Package {
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub creator: User,
- pub id: u64,
- pub name: String,
- pub owner: User,
- pub repository: Option<Repository>,
- pub _type: PackageType,
- pub version: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct PackageFile {
- #[serde(rename = "Size")]
- pub size: u64,
- pub id: u64,
- pub md5: String,
- pub name: String,
- pub sha1: String,
- pub sha256: String,
- pub sha512: String,
-}
diff --git a/src/repository.rs b/src/repository.rs
deleted file mode 100644
index eb638ac..0000000
--- a/src/repository.rs
+++ /dev/null
@@ -1,743 +0,0 @@
-use super::*;
-
-/// Repository operations.
-impl Forgejo {
- /// Gets info about the specified repository.
- pub async fn get_repo(
- &self,
- user: &str,
- repo: &str,
- ) -> Result<Option<Repository>, ForgejoError> {
- self.get_opt(&format!("repos/{user}/{repo}/")).await
- }
-
- /// Creates a repository.
- pub async fn create_repo(&self, repo: CreateRepoOption) -> Result<Repository, ForgejoError> {
- self.post("user/repos", &repo).await
- }
-
- pub async fn get_pulls(
- &self,
- owner: &str,
- repo: &str,
- query: PullQuery,
- ) -> Result<Vec<PullRequest>, ForgejoError> {
- self.get(&query.to_string(owner, repo)).await
- }
-
- pub async fn create_pr(
- &self,
- owner: &str,
- repo: &str,
- opts: CreatePullRequestOption,
- ) -> Result<PullRequest, ForgejoError> {
- self.post(&format!("repos/{owner}/{repo}/pulls"), &opts)
- .await
- }
-
- pub async fn is_merged(&self, owner: &str, repo: &str, pr: u64) -> Result<bool, ForgejoError> {
- self.get_exists(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"))
- .await
- }
-
- pub async fn merge_pr(
- &self,
- owner: &str,
- repo: &str,
- pr: u64,
- opts: MergePullRequestOption,
- ) -> Result<(), ForgejoError> {
- self.post_unit(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"), &opts)
- .await
- }
-
- pub async fn cancel_merge(&self, owner: &str, repo: &str, pr: u64) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/pulls/{pr}/merge"))
- .await
- }
-
- pub async fn get_releases(
- &self,
- owner: &str,
- repo: &str,
- query: ReleaseQuery,
- ) -> Result<Vec<Release>, ForgejoError> {
- self.get(&query.to_string(owner, repo)).await
- }
-
- pub async fn get_release(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<Option<Release>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/releases/{id}"))
- .await
- }
-
- pub async fn get_release_by_tag(
- &self,
- owner: &str,
- repo: &str,
- tag: &str,
- ) -> Result<Option<Release>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
- .await
- }
-
- pub async fn delete_release(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/releases/{id}"))
- .await
- }
-
- pub async fn delete_release_by_tag(
- &self,
- owner: &str,
- repo: &str,
- tag: &str,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/releases/tags/{tag}"))
- .await
- }
-
- pub async fn edit_release(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- opts: EditReleaseOption,
- ) -> Result<Release, ForgejoError> {
- self.patch(&format!("repos/{owner}/{repo}/releases/{id}"), &opts)
- .await
- }
-
- pub async fn get_release_attachments(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- ) -> Result<Vec<Attachment>, ForgejoError> {
- self.get(&format!("repos/{owner}/{repo}/releases/{id}/assets"))
- .await
- }
-
- pub async fn get_release_attachment(
- &self,
- owner: &str,
- repo: &str,
- release_id: u64,
- attachment_id: u64,
- ) -> Result<Attachment, ForgejoError> {
- self.get(&format!(
- "repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"
- ))
- .await
- }
-
- pub async fn create_release_attachment(
- &self,
- owner: &str,
- repo: &str,
- id: u64,
- name: &str,
- file: Vec<u8>,
- ) -> Result<Attachment, ForgejoError> {
- self.post_multipart(
- &format!("repos/{owner}/{repo}/releases/{id}/assets?name={name}"),
- reqwest::multipart::Form::new().part(
- "attachment",
- reqwest::multipart::Part::bytes(file)
- .file_name("file")
- .mime_str("*/*")
- .unwrap(),
- ),
- )
- .await
- }
-
- pub async fn delete_release_attachment(
- &self,
- owner: &str,
- repo: &str,
- release_id: u64,
- attachment_id: u64,
- ) -> Result<(), ForgejoError> {
- self.delete(&format!(
- "repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"
- ))
- .await
- }
-
- pub async fn edit_release_attachment(
- &self,
- owner: &str,
- repo: &str,
- release_id: u64,
- attachment_id: u64,
- opts: EditAttachmentOption,
- ) -> Result<Attachment, ForgejoError> {
- self.patch(
- &format!("repos/{owner}/{repo}/releases/{release_id}/assets/{attachment_id}"),
- &opts,
- )
- .await
- }
-
- pub async fn create_release(
- &self,
- owner: &str,
- repo: &str,
- opts: CreateReleaseOption,
- ) -> Result<Release, ForgejoError> {
- self.post(&format!("repos/{owner}/{repo}/releases"), &opts)
- .await
- }
-
- pub async fn latest_release(
- &self,
- owner: &str,
- repo: &str,
- ) -> Result<Option<Release>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/releases/latest"))
- .await
- }
-
- pub async fn download_zip_archive(
- &self,
- owner: &str,
- repo: &str,
- target: &str,
- ) -> Result<Option<bytes::Bytes>, ForgejoError> {
- let request = self
- .client
- .get(
- self.url
- .join(&format!("api/v1/repos/{owner}/{repo}/archive/{target}.zip"))
- .unwrap(),
- )
- .build()?;
- self.execute_opt_raw(request).await
- }
-
- pub async fn download_tarball_archive(
- &self,
- owner: &str,
- repo: &str,
- target: &str,
- ) -> Result<Option<bytes::Bytes>, ForgejoError> {
- let request = self
- .client
- .get(
- self.url
- .join(&format!(
- "api/v1/repos/{owner}/{repo}/archive/{target}.tar.gz"
- ))
- .unwrap(),
- )
- .build()?;
- self.execute_opt_raw(request).await
- }
-
- pub async fn download_release_attachment(
- &self,
- owner: &str,
- repo: &str,
- release: u64,
- attach: u64,
- ) -> Result<Option<bytes::Bytes>, ForgejoError> {
- let release = self
- .get_release_attachment(owner, repo, release, attach)
- .await?;
- let request = self.client.get(release.browser_download_url).build()?;
- self.execute_opt_raw(request).await
- }
-
- pub async fn get_tags(
- &self,
- owner: &str,
- repo: &str,
- query: TagQuery,
- ) -> Result<Vec<Tag>, ForgejoError> {
- self.get(&query.to_string(owner, repo)).await
- }
-
- pub async fn create_tag(
- &self,
- owner: &str,
- repo: &str,
- opts: CreateTagOption,
- ) -> Result<Tag, ForgejoError> {
- self.post(&format!("repos/{owner}/{repo}/tags"), &opts)
- .await
- }
-
- pub async fn get_tag(
- &self,
- owner: &str,
- repo: &str,
- tag: &str,
- ) -> Result<Option<Tag>, ForgejoError> {
- self.get_opt(&format!("repos/{owner}/{repo}/tags/{tag}"))
- .await
- }
-
- pub async fn delete_tag(&self, owner: &str, repo: &str, tag: &str) -> Result<(), ForgejoError> {
- self.delete(&format!("repos/{owner}/{repo}/tags/{tag}"))
- .await
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Repository {
- pub allow_merge_commits: bool,
- pub allow_rebase: bool,
- pub allow_rebase_explicit: bool,
- pub allow_rebase_update: bool,
- pub allow_squash_merge: bool,
- pub archived: bool,
- #[serde(with = "time::serde::rfc3339::option")]
- pub archived_at: Option<time::OffsetDateTime>,
- #[serde(deserialize_with = "crate::none_if_blank_url")]
- pub avatar_url: Option<Url>,
- pub clone_url: Url,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub default_allow_maintainer_edit: bool,
- pub default_branch: String,
- pub default_delete_branch_after_merge: bool,
- pub default_merge_style: String,
- pub description: String,
- pub empty: bool,
- pub external_tracker: Option<ExternalTracker>,
- pub external_wiki: Option<ExternalWiki>,
- pub fork: bool,
- pub forks_count: u64,
- pub full_name: String,
- pub has_actions: bool,
- pub has_issues: bool,
- pub has_packages: bool,
- pub has_projects: bool,
- pub has_pull_requests: bool,
- pub has_releases: bool,
- pub has_wiki: bool,
- pub html_url: Url,
- pub id: u64,
- pub ignore_whitespace_conflicts: bool,
- pub internal: bool,
- pub internal_tracker: Option<InternalTracker>,
- pub language: String,
- pub languages_url: Url,
- pub link: String,
- pub mirror: bool,
- pub mirror_interval: Option<String>,
- #[serde(with = "time::serde::rfc3339::option")]
- pub mirror_updated: Option<time::OffsetDateTime>,
- pub name: String,
- pub open_issues_count: u64,
- pub open_pr_counter: u64,
- #[serde(deserialize_with = "crate::none_if_blank_url")]
- pub original_url: Option<Url>,
- pub owner: User,
- pub parent: Option<Box<Repository>>,
- pub permissions: Permission,
- pub private: bool,
- pub release_counter: u64,
- pub repo_transfer: Option<RepoTransfer>,
- pub size: u64,
- pub ssh_url: String,
- pub stars_count: u64,
- pub template: bool,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
- pub url: Url,
- pub watchers_count: u64,
- pub website: Option<String>,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct RepositoryMeta {
- pub full_name: String,
- pub id: u64,
- pub name: String,
- pub owner: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub struct CreateRepoOption {
- pub auto_init: bool,
- pub default_branch: String,
- pub description: Option<String>,
- pub gitignores: String,
- pub issue_labels: String,
- pub license: String,
- pub name: String,
- pub private: bool,
- pub readme: String,
- pub template: bool,
- pub trust_model: TrustModel,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq)]
-pub enum TrustModel {
- Default,
- Collaborator,
- Committer,
- #[serde(rename = "collaboratorcommiter")]
- CollaboratorCommitter,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Milestone {
- #[serde(with = "time::serde::rfc3339::option")]
- pub closed_at: Option<time::OffsetDateTime>,
- pub closed_issues: u64,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub description: String,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_on: Option<time::OffsetDateTime>,
- pub id: u64,
- pub open_issues: u64,
- pub state: State,
- pub title: String,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct PullRequest {
- pub allow_maintainer_edit: bool,
- pub assignee: User,
- pub assignees: Vec<User>,
- pub base: PrBranchInfo,
- pub body: String,
- #[serde(with = "time::serde::rfc3339::option")]
- pub closed_at: Option<time::OffsetDateTime>,
- pub comments: u64,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub diff_url: Url,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_date: Option<time::OffsetDateTime>,
- pub head: PrBranchInfo,
- pub html_url: Url,
- pub id: u64,
- pub is_locked: bool,
- pub labels: Vec<Label>,
- pub merge_base: String,
- pub merge_commit_sha: Option<String>,
- pub mergeable: bool,
- pub merged: bool,
- #[serde(with = "time::serde::rfc3339::option")]
- pub merged_at: Option<time::OffsetDateTime>,
- pub merged_by: Option<User>,
- pub milestone: Option<Milestone>,
- pub number: u64,
- pub patch_url: Url,
- pub pin_order: u64,
- pub requested_reviewers: Option<Vec<User>>,
- pub state: State,
- pub title: String,
- #[serde(with = "time::serde::rfc3339")]
- pub updated_at: time::OffsetDateTime,
- pub url: Url,
- pub user: User,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct PrBranchInfo {
- pub label: String,
- #[serde(rename = "ref")]
- pub _ref: String,
- pub repo: Repository,
- pub repo_id: u64,
- pub sha: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct PullRequestMeta {
- pub merged: bool,
- #[serde(with = "time::serde::rfc3339::option")]
- pub merged_at: Option<time::OffsetDateTime>,
-}
-
-#[derive(Debug)]
-pub struct PullQuery {
- pub state: Option<State>,
- pub sort: Option<PullQuerySort>,
- pub milestone: Option<u64>,
- pub labels: Vec<u64>,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl PullQuery {
- fn to_string(&self, owner: &str, repo: &str) -> String {
- use std::fmt::Write;
- // This is different to other query struct serialization because
- // `labels` is serialized so strangely
- let mut s = String::new();
- s.push_str("repos/");
- s.push_str(owner);
- s.push('/');
- s.push_str(repo);
- s.push_str("/pulls?");
- if let Some(state) = self.state {
- s.push_str("state=");
- s.push_str(state.as_str());
- s.push('&');
- }
- if let Some(sort) = self.sort {
- s.push_str("sort=");
- s.push_str(sort.as_str());
- s.push('&');
- }
- if let Some(milestone) = self.milestone {
- s.push_str("sort=");
- s.write_fmt(format_args!("{milestone}"))
- .expect("writing to a string never fails");
- s.push('&');
- }
- for label in &self.labels {
- s.push_str("labels=");
- s.write_fmt(format_args!("{label}"))
- .expect("writing to a string never fails");
- s.push('&');
- }
- if let Some(page) = self.page {
- s.push_str("page=");
- s.write_fmt(format_args!("{page}"))
- .expect("writing to a string never fails");
- s.push('&');
- }
- if let Some(limit) = self.limit {
- s.push_str("limit=");
- s.write_fmt(format_args!("{limit}"))
- .expect("writing to a string never fails");
- s.push('&');
- }
- s
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub enum PullQuerySort {
- Oldest,
- RecentUpdate,
- LeastUpdate,
- MostComment,
- LeastComment,
- Priority,
-}
-
-impl PullQuerySort {
- fn as_str(&self) -> &'static str {
- match self {
- PullQuerySort::Oldest => "oldest",
- PullQuerySort::RecentUpdate => "recentupdate",
- PullQuerySort::LeastUpdate => "leastupdate",
- PullQuerySort::MostComment => "mostcomment",
- PullQuerySort::LeastComment => "leastcomment",
- PullQuerySort::Priority => "priority",
- }
- }
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct CreatePullRequestOption {
- pub assignee: Option<String>,
- pub assignees: Vec<String>,
- pub base: String,
- pub body: String,
- #[serde(with = "time::serde::rfc3339::option")]
- pub due_date: Option<time::OffsetDateTime>,
- pub head: String,
- pub labels: Vec<u64>,
- pub milestone: Option<u64>,
- pub title: String,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct MergePullRequestOption {
- #[serde(rename = "Do")]
- pub act: MergePrAction,
- #[serde(rename = "MergeCommitId")]
- pub merge_commit_id: Option<String>,
- #[serde(rename = "MergeMessageField")]
- pub merge_message_field: Option<String>,
- #[serde(rename = "MergeTitleField")]
- pub merge_title_field: Option<String>,
- pub delete_branch_after_merge: Option<bool>,
- pub force_merge: Option<bool>,
- pub head_commit_id: Option<String>,
- pub merge_when_checks_succeed: Option<bool>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub enum MergePrAction {
- #[serde(rename = "merge")]
- #[default]
- Merge,
- #[serde(rename = "rebase")]
- Rebase,
- #[serde(rename = "rebase-merge")]
- RebaseMerge,
- #[serde(rename = "squash")]
- Squash,
- #[serde(rename = "manually-merged")]
- ManuallyMerged,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Release {
- pub assets: Vec<Attachment>,
- pub author: User,
- pub body: String,
- #[serde(with = "time::serde::rfc3339")]
- pub created_at: time::OffsetDateTime,
- pub draft: bool,
- pub html_url: Url,
- pub id: u64,
- pub name: String,
- pub prerelease: bool,
- #[serde(with = "time::serde::rfc3339")]
- pub published_at: time::OffsetDateTime,
- pub tag_name: String,
- pub tarball_url: Url,
- pub target_commitish: String,
- pub url: Url,
- pub zipball_url: Url,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct CreateReleaseOption {
- pub body: String,
- pub draft: bool,
- pub name: String,
- pub prerelease: bool,
- pub tag_name: String,
- pub target_commitish: Option<String>,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct EditReleaseOption {
- pub body: Option<String>,
- pub draft: Option<bool>,
- pub name: Option<String>,
- pub prerelease: Option<bool>,
- pub tag_name: Option<String>,
- pub target_commitish: Option<String>,
-}
-
-#[derive(Default, Debug)]
-pub struct ReleaseQuery {
- pub draft: Option<bool>,
- pub prerelease: Option<bool>,
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl ReleaseQuery {
- fn to_string(&self, owner: &str, repo: &str) -> String {
- format!(
- "repos/{owner}/{repo}/releases?draft={}&pre-release={}&page={}&limit={}",
- opt_bool_s(self.draft),
- opt_bool_s(self.prerelease),
- self.page.map(|page| page.to_string()).unwrap_or_default(),
- self.limit.map(|page| page.to_string()).unwrap_or_default(),
- )
- }
-}
-
-fn opt_bool_s(b: Option<bool>) -> &'static str {
- match b {
- Some(true) => "true",
- Some(false) => "false",
- None => "",
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Tag {
- pub commit: CommitMeta,
- pub id: String,
- pub message: String,
- pub name: String,
- pub tarball_url: Url,
- pub zipball_url: Url,
-}
-
-#[derive(serde::Serialize, Debug, PartialEq, Default)]
-pub struct CreateTagOption {
- pub message: Option<String>,
- pub tag_name: String,
- pub target: Option<String>,
-}
-
-#[derive(Default, Debug)]
-pub struct TagQuery {
- pub page: Option<u32>,
- pub limit: Option<u32>,
-}
-
-impl TagQuery {
- fn to_string(&self, owner: &str, repo: &str) -> String {
- format!(
- "repos/{owner}/{repo}/tags?page={}&limit={}",
- self.page.map(|page| page.to_string()).unwrap_or_default(),
- self.limit.map(|page| page.to_string()).unwrap_or_default(),
- )
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct CommitMeta {
- #[serde(with = "time::serde::rfc3339")]
- pub created: time::OffsetDateTime,
- pub url: Url,
- pub sha: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct ExternalTracker {
- #[serde(rename = "external_tracker_format")]
- pub format: String,
- #[serde(rename = "external_tracker_regexp_pattern")]
- pub regexp_pattern: String,
- #[serde(rename = "external_tracker_style")]
- pub style: String,
- #[serde(rename = "external_tracker_url")]
- pub url: Url,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct InternalTracker {
- pub allow_only_contributors_to_track_time: bool,
- pub enable_issue_dependencies: bool,
- pub enable_time_tracker: bool,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct ExternalWiki {
- #[serde(rename = "external_wiki_url")]
- pub url: Url,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct Permission {
- pub admin: bool,
- pub pull: bool,
- pub push: bool,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct RepoTransfer {
- pub doer: User,
- pub recipient: User,
- pub teams: Vec<Team>,
-}
diff --git a/src/user.rs b/src/user.rs
deleted file mode 100644
index a99a5e2..0000000
--- a/src/user.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use super::*;
-
-/// User operations.
-impl Forgejo {
- /// Returns info about the authorized user.
- pub async fn myself(&self) -> Result<User, ForgejoError> {
- self.get("user").await
- }
-
- /// Returns info about the specified user.
- pub async fn get_user(&self, user: &str) -> Result<Option<User>, ForgejoError> {
- self.get_opt(&format!("users/{user}/")).await
- }
-
- /// Gets the list of users that follow the specified user.
- pub async fn get_followers(&self, user: &str) -> Result<Option<Vec<User>>, ForgejoError> {
- self.get_opt(&format!("users/{user}/followers/")).await
- }
-
- /// Gets the list of users the specified user is following.
- pub async fn get_following(&self, user: &str) -> Result<Option<Vec<User>>, ForgejoError> {
- self.get_opt(&format!("users/{user}/following/")).await
- }
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub struct User {
- pub active: bool,
- pub avatar_url: Url,
- #[serde(with = "time::serde::rfc3339")]
- pub created: time::OffsetDateTime,
- pub description: String,
- pub email: String,
- pub followers_count: u64,
- pub following_count: u64,
- pub full_name: String,
- pub id: u64,
- pub is_admin: bool,
- pub language: String,
- #[serde(with = "time::serde::rfc3339")]
- pub last_login: time::OffsetDateTime,
- pub location: String,
- pub login: String,
- pub login_name: String,
- pub prohibit_login: bool,
- pub restricted: bool,
- pub starred_repos_count: u64,
- pub website: String,
-}
-
-#[derive(serde::Deserialize, Debug, PartialEq)]
-pub enum UserVisibility {
- #[serde(rename = "public")]
- Public,
- #[serde(rename = "limited")]
- Limited,
- #[serde(rename = "private")]
- Private,
-}
diff --git a/swagger.v1.json b/swagger.v1.json
new file mode 100644
index 0000000..9ae07c0
--- /dev/null
+++ b/swagger.v1.json
@@ -0,0 +1,24321 @@
+{
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "schemes": [
+ "http",
+ "https"
+ ],
+ "swagger": "2.0",
+ "info": {
+ "description": "This documentation describes the Forgejo API.",
+ "title": "Forgejo API",
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/MIT"
+ },
+ "version": "1.21.2+1-73-gfedce17"
+ },
+ "basePath": "/api/v1",
+ "paths": {
+ "/activitypub/user-id/{user-id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "activitypub"
+ ],
+ "summary": "Returns the Person actor for a user",
+ "operationId": "activitypubPerson",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "user ID of the user",
+ "name": "user-id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ActivityPub"
+ }
+ }
+ }
+ },
+ "/activitypub/user-id/{user-id}/inbox": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "activitypub"
+ ],
+ "summary": "Send to the inbox",
+ "operationId": "activitypubPersonInbox",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "user ID of the user",
+ "name": "user-id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ }
+ },
+ "/admin/cron": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List cron tasks",
+ "operationId": "adminCronList",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CronList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/cron/{task}": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Run cron task",
+ "operationId": "adminCronRun",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "task to run",
+ "name": "task",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/admin/emails": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List all emails",
+ "operationId": "adminGetAllEmails",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/EmailList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/emails/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Search all emails",
+ "operationId": "adminSearchEmails",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "keyword",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/EmailList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List system's webhooks",
+ "operationId": "adminListHooks",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Create a hook",
+ "operationId": "adminCreateHook",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/admin/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Get a hook",
+ "operationId": "adminGetHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Delete a hook",
+ "operationId": "adminDeleteHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Update a hook",
+ "operationId": "adminEditHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/admin/orgs": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List all organizations",
+ "operationId": "adminGetAllOrgs",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OrganizationList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/unadopted": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List unadopted repositories",
+ "operationId": "adminUnadoptedList",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "pattern of repositories to search for",
+ "name": "pattern",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/StringSlice"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/unadopted/{owner}/{repo}": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Adopt unadopted files as a repository",
+ "operationId": "adminAdoptRepository",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Delete unadopted files",
+ "operationId": "adminDeleteUnadoptedRepository",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/admin/users": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Search users according filter conditions",
+ "operationId": "adminSearchUsers",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "ID of the user's login source to search for",
+ "name": "source_id",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "user's login name to search for",
+ "name": "login_name",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Create a user",
+ "operationId": "adminCreateUser",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateUserOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/User"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Delete a user",
+ "operationId": "adminDeleteUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to delete",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "purge the user from the system completely",
+ "name": "purge",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Edit an existing user",
+ "operationId": "adminEditUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to edit",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditUserOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/User"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}/keys": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Add a public key on behalf of a user",
+ "operationId": "adminCreatePublicKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "key",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateKeyOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/PublicKey"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}/keys/{id}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Delete a user's public key",
+ "operationId": "adminDeleteUserPublicKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the key to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}/orgs": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Create an organization",
+ "operationId": "adminCreateOrg",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user that will own the created organization",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "organization",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateOrgOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Organization"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}/rename": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Rename a user",
+ "operationId": "adminRenameUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "existing username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/RenameUserOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/admin/users/{username}/repos": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Create a repository on behalf of a user",
+ "operationId": "adminCreateRepo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user. This user will own the created repository",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "repository",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/gitignore/templates": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns a list of all gitignore templates",
+ "operationId": "listGitignoresTemplates",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitignoreTemplateList"
+ }
+ }
+ }
+ },
+ "/gitignore/templates/{name}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns information about a gitignore template",
+ "operationId": "getGitignoreTemplateInfo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the template",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitignoreTemplateInfo"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/label/templates": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns a list of all label templates",
+ "operationId": "listLabelTemplates",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelTemplateList"
+ }
+ }
+ }
+ },
+ "/label/templates/{name}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns all labels in a template",
+ "operationId": "getLabelTemplateInfo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the template",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelTemplateInfo"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/licenses": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns a list of all license templates",
+ "operationId": "listLicenseTemplates",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LicenseTemplateList"
+ }
+ }
+ }
+ },
+ "/licenses/{name}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns information about a license template",
+ "operationId": "getLicenseTemplateInfo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the license",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LicenseTemplateInfo"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/markdown": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "text/html"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Render a markdown document as HTML",
+ "operationId": "renderMarkdown",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/MarkdownOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/MarkdownRender"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/markdown/raw": {
+ "post": {
+ "consumes": [
+ "text/plain"
+ ],
+ "produces": [
+ "text/html"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Render raw markdown as HTML",
+ "operationId": "renderMarkdownRaw",
+ "parameters": [
+ {
+ "description": "Request body to render",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/MarkdownRender"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/markup": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "text/html"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Render a markup document as HTML",
+ "operationId": "renderMarkup",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/MarkupOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/MarkupRender"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/nodeinfo": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns the nodeinfo of the Gitea application",
+ "operationId": "getNodeInfo",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/NodeInfo"
+ }
+ }
+ }
+ },
+ "/notifications": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "List users's notification threads",
+ "operationId": "notifyGetList",
+ "parameters": [
+ {
+ "type": "boolean",
+ "description": "If true, show notifications marked as read. Default value is false",
+ "name": "all",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread \u0026 pinned.",
+ "name": "status-types",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "enum": [
+ "issue",
+ "pull",
+ "commit",
+ "repository"
+ ],
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "filter notifications by subject type",
+ "name": "subject-type",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/NotificationThreadList"
+ }
+ }
+ },
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "Mark notification threads as read, pinned or unread",
+ "operationId": "notifyReadList",
+ "parameters": [
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Describes the last point that notifications were checked. Anything updated since this time will not be updated.",
+ "name": "last_read_at",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "If true, mark all notifications on this repo. Default value is false",
+ "name": "all",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread.",
+ "name": "status-types",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Status to mark notifications as, Defaults to read.",
+ "name": "to-status",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "205": {
+ "$ref": "#/responses/NotificationThreadList"
+ }
+ }
+ }
+ },
+ "/notifications/new": {
+ "get": {
+ "tags": [
+ "notification"
+ ],
+ "summary": "Check if unread notifications exist",
+ "operationId": "notifyNewAvailable",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/NotificationCount"
+ }
+ }
+ }
+ },
+ "/notifications/threads/{id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "Get notification thread by ID",
+ "operationId": "notifyGetThread",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "id of notification thread",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/NotificationThread"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "Mark notification thread as read by ID",
+ "operationId": "notifyReadThread",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "id of notification thread",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "default": "read",
+ "description": "Status to mark notifications as",
+ "name": "to-status",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "205": {
+ "$ref": "#/responses/NotificationThread"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/org/{org}/repos": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create a repository in an organization",
+ "operationId": "createOrgRepoDeprecated",
+ "deprecated": true,
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get list of organizations",
+ "operationId": "orgGetAll",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OrganizationList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create an organization",
+ "operationId": "orgCreate",
+ "parameters": [
+ {
+ "name": "organization",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateOrgOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Organization"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs/{org}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get an organization",
+ "operationId": "orgGet",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization to get",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Organization"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete an organization",
+ "operationId": "orgDelete",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "organization that is to be deleted",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Edit an organization",
+ "operationId": "orgEdit",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization to edit",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/EditOrgOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Organization"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/actions/secrets": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's actions secrets",
+ "operationId": "orgListActionsSecrets",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/SecretList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/actions/secrets/{secretname}": {
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create or Update a secret value in an organization",
+ "operationId": "updateOrgSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateOrUpdateSecretOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "response when creating a secret"
+ },
+ "204": {
+ "description": "response when updating a secret"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete a secret in an organization",
+ "operationId": "deleteOrgSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "delete one secret of the organization"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/activities/feeds": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's activity feeds",
+ "operationId": "orgListActivityFeeds",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the org",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date",
+ "description": "the date of the activities to be found",
+ "name": "date",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ActivityFeedsList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/avatar": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Update Avatar",
+ "operationId": "orgUpdateAvatar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/UpdateUserAvatarOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete Avatar",
+ "operationId": "orgDeleteAvatar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/block/{username}": {
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Blocks a user from the organization",
+ "operationId": "orgBlockUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the org",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's webhooks",
+ "operationId": "orgListHooks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create a hook",
+ "operationId": "orgCreateHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get a hook",
+ "operationId": "orgGetHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete a hook",
+ "operationId": "orgDeleteHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Update a hook",
+ "operationId": "orgEditHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/labels": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's labels",
+ "operationId": "orgListLabels",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create a label for an organization",
+ "operationId": "orgCreateLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateLabelOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/labels/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get a single label",
+ "operationId": "orgGetLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete a label",
+ "operationId": "orgDeleteLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Update a label",
+ "operationId": "orgEditLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditLabelOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/list_blocked": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List the organization's blocked users",
+ "operationId": "orgListBlockedUsers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the org",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BlockedUserList"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/members": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's members",
+ "operationId": "orgListMembers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/members/{username}": {
+ "get": {
+ "tags": [
+ "organization"
+ ],
+ "summary": "Check if a user is a member of an organization",
+ "operationId": "orgIsMember",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "user is a member"
+ },
+ "303": {
+ "description": "redirection to /orgs/{org}/public_members/{username}"
+ },
+ "404": {
+ "description": "user is not a member"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Remove a member from an organization",
+ "operationId": "orgDeleteMember",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "member removed"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/public_members": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's public members",
+ "operationId": "orgListPublicMembers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/public_members/{username}": {
+ "get": {
+ "tags": [
+ "organization"
+ ],
+ "summary": "Check if a user is a public member of an organization",
+ "operationId": "orgIsPublicMember",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "user is a public member"
+ },
+ "404": {
+ "description": "user is not a public member"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Publicize a user's membership",
+ "operationId": "orgPublicizeMember",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "membership publicized"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Conceal a user's membership",
+ "operationId": "orgConcealMember",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/repos": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's repos",
+ "operationId": "orgListRepos",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create a repository in an organization",
+ "operationId": "createOrgRepo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/teams": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List an organization's teams",
+ "operationId": "orgListTeams",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TeamList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Create a team",
+ "operationId": "orgCreateTeam",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateTeamOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Team"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/teams/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Search for teams within an organization",
+ "operationId": "teamSearch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "keywords to search",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include search within team description (defaults to true)",
+ "name": "include_desc",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "SearchResults of a successful search",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Team"
+ }
+ },
+ "ok": {
+ "type": "boolean"
+ }
+ }
+ }
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/orgs/{org}/unblock/{username}": {
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Unblock a user from the organization",
+ "operationId": "orgUnblockUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the org",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/packages/{owner}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "package"
+ ],
+ "summary": "Gets all packages of an owner",
+ "operationId": "listPackages",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the packages",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "alpine",
+ "cargo",
+ "chef",
+ "composer",
+ "conan",
+ "conda",
+ "container",
+ "cran",
+ "debian",
+ "generic",
+ "go",
+ "helm",
+ "maven",
+ "npm",
+ "nuget",
+ "pub",
+ "pypi",
+ "rpm",
+ "rubygems",
+ "swift",
+ "vagrant"
+ ],
+ "type": "string",
+ "description": "package type filter",
+ "name": "type",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "name filter",
+ "name": "q",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PackageList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/packages/{owner}/{type}/{name}/{version}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "package"
+ ],
+ "summary": "Gets a package",
+ "operationId": "getPackage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the package",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "type of the package",
+ "name": "type",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the package",
+ "name": "name",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "version of the package",
+ "name": "version",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Package"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "package"
+ ],
+ "summary": "Delete a package",
+ "operationId": "deletePackage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the package",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "type of the package",
+ "name": "type",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the package",
+ "name": "name",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "version of the package",
+ "name": "version",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/packages/{owner}/{type}/{name}/{version}/files": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "package"
+ ],
+ "summary": "Gets all files of a package",
+ "operationId": "listPackageFiles",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the package",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "type of the package",
+ "name": "type",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the package",
+ "name": "name",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "version of the package",
+ "name": "version",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PackageFileList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/issues/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Search for issues across the repositories that the user has access to",
+ "operationId": "issueSearchIssues",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "whether issue is open or closed",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded",
+ "name": "labels",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "comma separated list of milestone names. Fetch only issues that have any of this milestones. Non existent are discarded",
+ "name": "milestones",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "search string",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "repository to prioritize in the results",
+ "name": "priority_repo_id",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "filter by type (issues / pulls) if set",
+ "name": "type",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter (issues / pulls) assigned to you, default is false",
+ "name": "assigned",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter (issues / pulls) created by you, default is false",
+ "name": "created",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter (issues / pulls) mentioning you, default is false",
+ "name": "mentioned",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter pulls requesting your review, default is false",
+ "name": "review_requested",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter pulls reviewed by you, default is false",
+ "name": "reviewed",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "filter by owner",
+ "name": "owner",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "filter by team (requires organization owner parameter to be provided)",
+ "name": "team",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueList"
+ }
+ }
+ }
+ },
+ "/repos/migrate": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Migrate a remote git repository",
+ "operationId": "repoMigrate",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/MigrateRepoOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "409": {
+ "description": "The repository with the same name already exists."
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Search for repositories",
+ "operationId": "repoSearch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "keyword",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "Limit search to repositories with keyword as topic",
+ "name": "topic",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include search of keyword within repository description",
+ "name": "includeDesc",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "search only for repos that the user with the given id owns or contributes to",
+ "name": "uid",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "repo owner to prioritize in the results",
+ "name": "priority_owner_id",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "search only for repos that belong to the given team id",
+ "name": "team_id",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "search only for repos that the user with the given id has starred",
+ "name": "starredBy",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include private repositories this user has access to (defaults to true)",
+ "name": "private",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "show only pubic, private or all repositories (defaults to all)",
+ "name": "is_private",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include template repositories this user has access to (defaults to true)",
+ "name": "template",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "show only archived, non-archived or all repositories (defaults to all)",
+ "name": "archived",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "type of repository to search for. Supported values are \"fork\", \"source\", \"mirror\" and \"collaborative\"",
+ "name": "mode",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "if `uid` is given, search only for repos that the user owns",
+ "name": "exclusive",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "sort repos by attribute. Supported values are \"alpha\", \"created\", \"updated\", \"size\", and \"id\". Default is \"alpha\"",
+ "name": "sort",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "sort order, either \"asc\" (ascending) or \"desc\" (descending). Default is \"asc\", ignored if \"sort\" is not specified.",
+ "name": "order",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/SearchResults"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a repository",
+ "operationId": "repoGet",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Repository"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a repository",
+ "operationId": "repoDelete",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to delete",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to delete",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a repository's properties. Only fields that are set will be changed.",
+ "operationId": "repoEdit",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to edit",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to edit",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "Properties of a repo that you can edit",
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/actions/secrets/{secretname}": {
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create or Update a secret value in a repository",
+ "operationId": "updateRepoSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repository",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repository",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateOrUpdateSecretOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "response when creating a secret"
+ },
+ "204": {
+ "description": "response when updating a secret"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a secret in a repository",
+ "operationId": "deleteRepoSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repository",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repository",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "delete one secret of the organization"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/activities/feeds": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's activity feeds",
+ "operationId": "repoListActivityFeeds",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date",
+ "description": "the date of the activities to be found",
+ "name": "date",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ActivityFeedsList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/archive/{archive}": {
+ "get": {
+ "produces": [
+ "application/octet-stream",
+ "application/zip,",
+ "application/gzip"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get an archive of a repository",
+ "operationId": "repoGetArchive",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "the git reference for download with attached archive format (e.g. master.zip)",
+ "name": "archive",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "success"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/assignees": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Return all users that have write access and can be assigned to issues",
+ "operationId": "repoGetAssignees",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/avatar": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Update avatar",
+ "operationId": "repoUpdateAvatar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/UpdateRepoAvatarOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete avatar",
+ "operationId": "repoDeleteAvatar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/branch_protections": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List branch protections for a repository",
+ "operationId": "repoListBranchProtection",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BranchProtectionList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a branch protections for a repository",
+ "operationId": "repoCreateBranchProtection",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateBranchProtectionOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/BranchProtection"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/branch_protections/{name}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a specific branch protection for the repository",
+ "operationId": "repoGetBranchProtection",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of protected branch",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BranchProtection"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a specific branch protection for the repository",
+ "operationId": "repoDeleteBranchProtection",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of protected branch",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a branch protections for a repository. Only fields that are set will be changed",
+ "operationId": "repoEditBranchProtection",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of protected branch",
+ "name": "name",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditBranchProtectionOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BranchProtection"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/branches": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's branches",
+ "operationId": "repoListBranches",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BranchList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a branch",
+ "operationId": "repoCreateBranch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateBranchRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Branch"
+ },
+ "403": {
+ "description": "The branch is archived or a mirror."
+ },
+ "404": {
+ "description": "The old branch does not exist."
+ },
+ "409": {
+ "description": "The branch with the same name already exists."
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/branches/{branch}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Retrieve a specific branch from a repository, including its effective branch protection",
+ "operationId": "repoGetBranch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "branch to get",
+ "name": "branch",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Branch"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a specific branch from a repository",
+ "operationId": "repoDeleteBranch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "branch to delete",
+ "name": "branch",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/collaborators": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's collaborators",
+ "operationId": "repoListCollaborators",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/collaborators/{collaborator}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Check if a user is a collaborator of a repository",
+ "operationId": "repoCheckCollaborator",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the collaborator",
+ "name": "collaborator",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Add a collaborator to a repository",
+ "operationId": "repoAddCollaborator",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the collaborator to add",
+ "name": "collaborator",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/AddCollaboratorOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a collaborator from a repository",
+ "operationId": "repoDeleteCollaborator",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the collaborator to delete",
+ "name": "collaborator",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/collaborators/{collaborator}/permission": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get repository permissions for a user",
+ "operationId": "repoGetRepoPermissions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the collaborator",
+ "name": "collaborator",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepoCollaboratorPermission"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/commits": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a list of all commits from a repository",
+ "operationId": "repoGetAllCommits",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "SHA or branch to start listing commits from (usually 'master')",
+ "name": "sha",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "filepath of a file/dir",
+ "name": "path",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include diff stats for every commit (disable for speedup, default 'true')",
+ "name": "stat",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include verification for every commit (disable for speedup, default 'true')",
+ "name": "verification",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include a list of affected files for every commit (disable for speedup, default 'true')",
+ "name": "files",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results (ignored if used with 'path')",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "commits that match the given specifier will not be listed.",
+ "name": "not",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommitList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/EmptyRepository"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/commits/{ref}/status": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a commit's combined status, by branch/tag/commit reference",
+ "operationId": "repoGetCombinedStatusByRef",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of branch/tag/commit",
+ "name": "ref",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CombinedStatus"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/commits/{ref}/statuses": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a commit's statuses, by branch/tag/commit reference",
+ "operationId": "repoListStatusesByRef",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of branch/tag/commit",
+ "name": "ref",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "oldest",
+ "recentupdate",
+ "leastupdate",
+ "leastindex",
+ "highestindex"
+ ],
+ "type": "string",
+ "description": "type of sort",
+ "name": "sort",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "pending",
+ "success",
+ "error",
+ "failure",
+ "warning"
+ ],
+ "type": "string",
+ "description": "type of state",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommitStatusList"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/contents": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the metadata of all the entries of the root dir",
+ "operationId": "repoGetContentsList",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ContentsListResponse"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Modify multiple files in a repository",
+ "operationId": "repoChangeFiles",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/ChangeFilesOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/FilesResponse"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/contents/{filepath}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir",
+ "operationId": "repoGetContents",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "path of the dir, file, symlink or submodule in the repo",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ContentsResponse"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Update a file in a repository",
+ "operationId": "repoUpdateFile",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "path of the file to update",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateFileOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/FileResponse"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a file in a repository",
+ "operationId": "repoCreateFile",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "path of the file to create",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateFileOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/FileResponse"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a file in a repository",
+ "operationId": "repoDeleteFile",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "path of the file to delete",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/DeleteFileOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/FileDeleteResponse"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/diffpatch": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Apply diff patch to repository",
+ "operationId": "repoApplyDiffPatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/UpdateFileOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/FileResponse"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/editorconfig/{filepath}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get the EditorConfig definitions of a file in a repository",
+ "operationId": "repoGetEditorConfig",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "filepath of file to get",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "success"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/forks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's forks",
+ "operationId": "listForks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Fork a repository",
+ "operationId": "createFork",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to fork",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to fork",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateForkOption"
+ }
+ }
+ ],
+ "responses": {
+ "202": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "description": "The repository with the same name already exists."
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/blobs/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the blob of a repository.",
+ "operationId": "GetBlob",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "sha of the commit",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitBlobResponse"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/commits/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a single commit from a repository",
+ "operationId": "repoGetSingleCommit",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "a git ref or commit sha",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "include diff stats for every commit (disable for speedup, default 'true')",
+ "name": "stat",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include verification for every commit (disable for speedup, default 'true')",
+ "name": "verification",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include a list of affected files for every commit (disable for speedup, default 'true')",
+ "name": "files",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Commit"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/commits/{sha}.{diffType}": {
+ "get": {
+ "produces": [
+ "text/plain"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a commit's diff or patch",
+ "operationId": "repoDownloadCommitDiffOrPatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "SHA of the commit to get",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "diff",
+ "patch"
+ ],
+ "type": "string",
+ "description": "whether the output is diff or patch",
+ "name": "diffType",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/string"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/notes/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a note corresponding to a single commit from a repository",
+ "operationId": "repoGetNote",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "a git ref or commit sha",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "include verification for every commit (disable for speedup, default 'true')",
+ "name": "verification",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include a list of affected files for every commit (disable for speedup, default 'true')",
+ "name": "files",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Note"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/refs": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get specified ref or filtered repository's refs",
+ "operationId": "repoListAllGitRefs",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ReferenceList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/refs/{ref}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get specified ref or filtered repository's refs",
+ "operationId": "repoListGitRefs",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "part or full name of the ref",
+ "name": "ref",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ReferenceList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/tags/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the tag object of an annotated tag (not lightweight tags)",
+ "operationId": "GetAnnotatedTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "sha of the tag. The Git tags API only supports annotated tag objects, not lightweight tags.",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/AnnotatedTag"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/git/trees/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the tree of a repository.",
+ "operationId": "GetTree",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "sha of the commit",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "show all directories and files",
+ "name": "recursive",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number; the 'truncated' field in the response will be true if there are still more items after this page, false if the last page",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "number of items per page",
+ "name": "per_page",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitTreeResponse"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List the hooks in a repository",
+ "operationId": "repoListHooks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a hook",
+ "operationId": "repoCreateHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/hooks/git": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List the Git hooks in a repository",
+ "operationId": "repoListGitHooks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitHookList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/hooks/git/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a Git hook",
+ "operationId": "repoGetGitHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitHook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a Git hook in a repository",
+ "operationId": "repoDeleteGitHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a Git hook in a repository",
+ "operationId": "repoEditGitHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditGitHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GitHook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a hook",
+ "operationId": "repoGetHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a hook in a repository",
+ "operationId": "repoDeleteHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a hook in a repository",
+ "operationId": "repoEditHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the hook",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/hooks/{id}/tests": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Test a push webhook",
+ "operationId": "repoTestHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to test",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag, indicates which commit will be loaded to the webhook payload.",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issue_config": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Returns the issue config for a repo",
+ "operationId": "repoGetIssueConfig",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepoIssueConfig"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issue_config/validate": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Returns the validation information for a issue config",
+ "operationId": "repoValidateIssueConfig",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepoIssueConfigValidation"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issue_templates": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get available issue templates for a repository",
+ "operationId": "repoGetIssueTemplates",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueTemplates"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List a repository's issues",
+ "operationId": "issueListIssues",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "closed",
+ "open",
+ "all"
+ ],
+ "type": "string",
+ "description": "whether issue is open or closed",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded",
+ "name": "labels",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "search string",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "issues",
+ "pulls"
+ ],
+ "type": "string",
+ "description": "filter by type (issues / pulls) if set",
+ "name": "type",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "comma separated list of milestone names or ids. It uses names and fall back to ids. Fetch only issues that have any of this milestones. Non existent milestones are discarded",
+ "name": "milestones",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show items updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show items updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Only show items which were created by the the given user",
+ "name": "created_by",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Only show items for which the given user is assigned",
+ "name": "assigned_by",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Only show items in which the given user was mentioned",
+ "name": "mentioned_by",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Create an issue. If using deadline only the date will be taken into account, and time of day ignored.",
+ "operationId": "issueCreateIssue",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateIssueOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Issue"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "412": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/comments": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List all comments in a repository",
+ "operationId": "issueGetRepoComments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated since the provided time are returned.",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated before the provided time are returned.",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommentList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/comments/{id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a comment",
+ "operationId": "issueGetComment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Comment"
+ },
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete a comment",
+ "operationId": "issueDeleteComment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of comment to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Edit a comment",
+ "operationId": "issueEditComment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditIssueCommentOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Comment"
+ },
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/comments/{id}/assets": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List comment's attachments",
+ "operationId": "issueListIssueCommentAttachments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/AttachmentList"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "multipart/form-data"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Create a comment attachment",
+ "operationId": "issueCreateIssueCommentAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the attachment",
+ "name": "name",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "time of the attachment's creation. This is a timestamp in RFC 3339 format",
+ "name": "updated_at",
+ "in": "query"
+ },
+ {
+ "type": "file",
+ "description": "attachment to upload",
+ "name": "attachment",
+ "in": "formData",
+ "required": true
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/comments/{id}/assets/{attachment_id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a comment attachment",
+ "operationId": "issueGetIssueCommentAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to get",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete a comment attachment",
+ "operationId": "issueDeleteIssueCommentAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to delete",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Edit a comment attachment",
+ "operationId": "issueEditIssueCommentAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to edit",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditAttachmentOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/comments/{id}/reactions": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a list of reactions from a comment of an issue",
+ "operationId": "issueGetCommentReactions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ReactionList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add a reaction to a comment of an issue",
+ "operationId": "issuePostCommentReaction",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "content",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditReactionOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Reaction"
+ },
+ "201": {
+ "$ref": "#/responses/Reaction"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Remove a reaction from a comment of an issue",
+ "operationId": "issueDeleteCommentReaction",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "content",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditReactionOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/pinned": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's pinned issues",
+ "operationId": "repoListPinnedIssues",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get an issue",
+ "operationId": "issueGetIssue",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Issue"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete an issue",
+ "operationId": "issueDelete",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of issue to delete",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Edit an issue. If using deadline only the date will be taken into account, and time of day ignored.",
+ "operationId": "issueEditIssue",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to edit",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditIssueOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Issue"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "412": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/assets": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List issue's attachments",
+ "operationId": "issueListIssueAttachments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/AttachmentList"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "multipart/form-data"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Create an issue attachment",
+ "operationId": "issueCreateIssueAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the attachment",
+ "name": "name",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "time of the attachment's creation. This is a timestamp in RFC 3339 format",
+ "name": "updated_at",
+ "in": "query"
+ },
+ {
+ "type": "file",
+ "description": "attachment to upload",
+ "name": "attachment",
+ "in": "formData",
+ "required": true
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/assets/{attachment_id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get an issue attachment",
+ "operationId": "issueGetIssueAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to get",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete an issue attachment",
+ "operationId": "issueDeleteIssueAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to delete",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Edit an issue attachment",
+ "operationId": "issueEditIssueAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to edit",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditAttachmentOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/blocks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List issues that are blocked by this issue",
+ "operationId": "issueListBlocks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Block the issue given in the body by the issue in path",
+ "operationId": "issueCreateIssueBlocking",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueMeta"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Issue"
+ },
+ "404": {
+ "description": "the issue does not exist"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Unblock the issue given in the body by the issue in path",
+ "operationId": "issueRemoveIssueBlocking",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueMeta"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Issue"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/comments": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List all comments on an issue",
+ "operationId": "issueGetComments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated since the specified time are returned.",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated before the provided time are returned.",
+ "name": "before",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommentList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add a comment to an issue",
+ "operationId": "issueCreateComment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateIssueCommentOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Comment"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/comments/{id}": {
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete a comment",
+ "operationId": "issueDeleteCommentDeprecated",
+ "deprecated": true,
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "this parameter is ignored",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of comment to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Edit a comment",
+ "operationId": "issueEditCommentDeprecated",
+ "deprecated": true,
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "this parameter is ignored",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the comment to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditIssueCommentOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Comment"
+ },
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/deadline": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Set an issue deadline. If set to null, the deadline is deleted. If using deadline only the date will be taken into account, and time of day ignored.",
+ "operationId": "issueEditIssueDeadline",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to create or update a deadline on",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditDeadlineOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/IssueDeadline"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/dependencies": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List an issue's dependencies, i.e all issues that block this issue.",
+ "operationId": "issueListIssueDependencies",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/IssueList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Make the issue in the url depend on the issue in the form.",
+ "operationId": "issueCreateIssueDependencies",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueMeta"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Issue"
+ },
+ "404": {
+ "description": "the issue does not exist"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Remove an issue dependency",
+ "operationId": "issueRemoveIssueDependencies",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueMeta"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Issue"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/labels": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get an issue's labels",
+ "operationId": "issueGetLabels",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Replace an issue's labels",
+ "operationId": "issueReplaceLabels",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueLabelsOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add a label to an issue",
+ "operationId": "issueAddLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/IssueLabelsOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Remove all labels from an issue",
+ "operationId": "issueClearLabels",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/DeleteLabelsOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/labels/{id}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Remove a label from an issue",
+ "operationId": "issueRemoveLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to remove",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/DeleteLabelsOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/pin": {
+ "post": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Pin an Issue",
+ "operationId": "pinIssue",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of issue to pin",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Unpin an Issue",
+ "operationId": "unpinIssue",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of issue to unpin",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/pin/{position}": {
+ "patch": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Moves the Pin to the given Position",
+ "operationId": "moveIssuePin",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "the new position",
+ "name": "position",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/reactions": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a list reactions of an issue",
+ "operationId": "issueGetIssueReactions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ReactionList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add a reaction to an issue",
+ "operationId": "issuePostIssueReaction",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "content",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditReactionOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Reaction"
+ },
+ "201": {
+ "$ref": "#/responses/Reaction"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Remove a reaction from an issue",
+ "operationId": "issueDeleteIssueReaction",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "content",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditReactionOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/stopwatch/delete": {
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete an issue's existing stopwatch.",
+ "operationId": "issueDeleteStopWatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to stop the stopwatch on",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "description": "Not repo writer, user does not have rights to toggle stopwatch"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "description": "Cannot cancel a non existent stopwatch"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/stopwatch/start": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Start stopwatch on an issue.",
+ "operationId": "issueStartStopWatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to create the stopwatch on",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "description": "Not repo writer, user does not have rights to toggle stopwatch"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "description": "Cannot start a stopwatch again if it already exists"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/stopwatch/stop": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Stop an issue's existing stopwatch.",
+ "operationId": "issueStopStopWatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to stop the stopwatch on",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "description": "Not repo writer, user does not have rights to toggle stopwatch"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "description": "Cannot stop a non existent stopwatch"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/subscriptions": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get users who subscribed on an issue.",
+ "operationId": "issueSubscriptions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/subscriptions/check": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Check if user is subscribed to an issue",
+ "operationId": "issueCheckSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WatchInfo"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/subscriptions/{user}": {
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Subscribe user to issue",
+ "operationId": "issueAddSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "user to subscribe",
+ "name": "user",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Already subscribed"
+ },
+ "201": {
+ "description": "Successfully Subscribed"
+ },
+ "304": {
+ "description": "User can only subscribe itself if he is no admin"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Unsubscribe user from issue",
+ "operationId": "issueDeleteSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "user witch unsubscribe",
+ "name": "user",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Already unsubscribed"
+ },
+ "201": {
+ "description": "Successfully Unsubscribed"
+ },
+ "304": {
+ "description": "User can only subscribe itself if he is no admin"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/timeline": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List all comments and events on an issue",
+ "operationId": "issueGetCommentsAndTimeline",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated since the specified time are returned.",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "if provided, only comments updated before the provided time are returned.",
+ "name": "before",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TimelineList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/times": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List an issue's tracked times",
+ "operationId": "issueTrackedTimes",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "optional filter by user (available for issue managers)",
+ "name": "user",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTimeList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add tracked time to a issue",
+ "operationId": "issueAddTime",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/AddTimeOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTime"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Reset a tracked time of an issue",
+ "operationId": "issueResetTime",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue to add tracked time to",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/issues/{index}/times/{id}": {
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete specific tracked time",
+ "operationId": "issueDeleteTime",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the issue",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of time to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/keys": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's keys",
+ "operationId": "repoListKeys",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "the key_id to search for",
+ "name": "key_id",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "fingerprint of the key",
+ "name": "fingerprint",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/DeployKeyList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Add a key to a repository",
+ "operationId": "repoCreateKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateKeyOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/DeployKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/keys/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a repository's key by id",
+ "operationId": "repoGetKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the key to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/DeployKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a key from a repository",
+ "operationId": "repoDeleteKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the key to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/labels": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get all of a repository's labels",
+ "operationId": "issueListLabels",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LabelList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Create a label",
+ "operationId": "issueCreateLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateLabelOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/labels/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a single label",
+ "operationId": "issueGetLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete a label",
+ "operationId": "issueDeleteLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Update a label",
+ "operationId": "issueEditLabel",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the label to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditLabelOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Label"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/languages": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get languages and number of bytes of code written",
+ "operationId": "repoGetLanguages",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/LanguageStatistics"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/media/{filepath}": {
+ "get": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a file or it's LFS object from a repository",
+ "operationId": "repoGetRawFileOrLFS",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "filepath of the file to get",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Returns raw file content."
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/milestones": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get all of a repository's opened milestones",
+ "operationId": "issueGetMilestonesList",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Milestone state, Recognized values are open, closed and all. Defaults to \"open\"",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "filter by milestone name",
+ "name": "name",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/MilestoneList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Create a milestone",
+ "operationId": "issueCreateMilestone",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateMilestoneOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Milestone"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/milestones/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Get a milestone",
+ "operationId": "issueGetMilestone",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "the milestone to get, identified by ID and if not available by name",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Milestone"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "issue"
+ ],
+ "summary": "Delete a milestone",
+ "operationId": "issueDeleteMilestone",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "the milestone to delete, identified by ID and if not available by name",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Update a milestone",
+ "operationId": "issueEditMilestone",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "the milestone to edit, identified by ID and if not available by name",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditMilestoneOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Milestone"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/mirror-sync": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Sync a mirrored repository",
+ "operationId": "repoMirrorSync",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to sync",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to sync",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/new_pin_allowed": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Returns if new Issue Pins are allowed",
+ "operationId": "repoNewPinAllowed",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepoNewIssuePinsAllowed"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/notifications": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "List users's notification threads on a specific repo",
+ "operationId": "notifyGetRepoList",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "If true, show notifications marked as read. Default value is false",
+ "name": "all",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread \u0026 pinned",
+ "name": "status-types",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "enum": [
+ "issue",
+ "pull",
+ "commit",
+ "repository"
+ ],
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "filter notifications by subject type",
+ "name": "subject-type",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show notifications updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/NotificationThreadList"
+ }
+ }
+ },
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "notification"
+ ],
+ "summary": "Mark notification threads as read, pinned or unread on a specific repo",
+ "operationId": "notifyReadRepoList",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "If true, mark all notifications on this repo. Default value is false",
+ "name": "all",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "collectionFormat": "multi",
+ "description": "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread.",
+ "name": "status-types",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "description": "Status to mark notifications as. Defaults to read.",
+ "name": "to-status",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Describes the last point that notifications were checked. Anything updated since this time will not be updated.",
+ "name": "last_read_at",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "205": {
+ "$ref": "#/responses/NotificationThreadList"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's pull requests",
+ "operationId": "repoListPullRequests",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "closed",
+ "open",
+ "all"
+ ],
+ "type": "string",
+ "description": "State of pull request: open or closed (optional)",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "oldest",
+ "recentupdate",
+ "leastupdate",
+ "mostcomment",
+ "leastcomment",
+ "priority"
+ ],
+ "type": "string",
+ "description": "Type of sort",
+ "name": "sort",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "ID of the milestone",
+ "name": "milestone",
+ "in": "query"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "collectionFormat": "multi",
+ "description": "Label IDs",
+ "name": "labels",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullRequestList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a pull request",
+ "operationId": "repoCreatePullRequest",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreatePullRequestOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/PullRequest"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/pinned": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's pinned pull requests",
+ "operationId": "repoListPinnedPullRequests",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullRequestList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a pull request",
+ "operationId": "repoGetPullRequest",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullRequest"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Update a pull request. If using deadline only the date will be taken into account, and time of day ignored.",
+ "operationId": "repoEditPullRequest",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to edit",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditPullRequestOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/PullRequest"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ },
+ "412": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}.{diffType}": {
+ "get": {
+ "produces": [
+ "text/plain"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a pull request diff or patch",
+ "operationId": "repoDownloadPullDiffOrPatch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "diff",
+ "patch"
+ ],
+ "type": "string",
+ "description": "whether the output is diff or patch",
+ "name": "diffType",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "whether to include binary file changes. if true, the diff is applicable with `git apply`",
+ "name": "binary",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/string"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/commits": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get commits for a pull request",
+ "operationId": "repoGetPullRequestCommits",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include verification for every commit (disable for speedup, default 'true')",
+ "name": "verification",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "include a list of affected files for every commit (disable for speedup, default 'true')",
+ "name": "files",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommitList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/files": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get changed files for a pull request",
+ "operationId": "repoGetPullRequestFiles",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "skip to given file",
+ "name": "skip-to",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "ignore-all",
+ "ignore-change",
+ "ignore-eol",
+ "show-all"
+ ],
+ "type": "string",
+ "description": "whitespace behavior",
+ "name": "whitespace",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ChangedFileList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/merge": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Check if a pull request has been merged",
+ "operationId": "repoPullRequestIsMerged",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "pull request has been merged"
+ },
+ "404": {
+ "description": "pull request has not been merged"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Merge a pull request",
+ "operationId": "repoMergePullRequest",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to merge",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/MergePullRequestOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/empty"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Cancel the scheduled auto merge for the given pull request",
+ "operationId": "repoCancelScheduledAutoMerge",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to merge",
+ "name": "index",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/requested_reviewers": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "create review requests for a pull request",
+ "operationId": "repoCreatePullReviewRequests",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/PullReviewRequestOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/PullReviewList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "cancel review requests for a pull request",
+ "operationId": "repoDeletePullReviewRequests",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/PullReviewRequestOptions"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/reviews": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List all reviews for a pull request",
+ "operationId": "repoListPullReviews",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReviewList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a review to an pull request",
+ "operationId": "repoCreatePullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreatePullReviewOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReview"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/reviews/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a specific review for a pull request",
+ "operationId": "repoGetPullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReview"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Submit a pending review to an pull request",
+ "operationId": "repoSubmitPullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/SubmitPullReviewOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReview"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a specific review from a pull request",
+ "operationId": "repoDeletePullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a specific review for a pull request",
+ "operationId": "repoGetPullReviewComments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReviewCommentList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Dismiss a review for a pull request",
+ "operationId": "repoDismissPullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/DismissPullReviewOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReview"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/undismissals": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Cancel to dismiss a review for a pull request",
+ "operationId": "repoUnDismissPullReview",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the review",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PullReview"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/pulls/{index}/update": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Merge PR's baseBranch into headBranch",
+ "operationId": "repoUpdatePullRequest",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "index of the pull request to get",
+ "name": "index",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "merge",
+ "rebase"
+ ],
+ "type": "string",
+ "description": "how to update pull request",
+ "name": "style",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/push_mirrors": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get all push mirrors of the repository",
+ "operationId": "repoListPushMirrors",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PushMirrorList"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "add a push mirror to the repository",
+ "operationId": "repoAddPushMirror",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreatePushMirrorOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PushMirror"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/push_mirrors-sync": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Sync all push mirrored repository",
+ "operationId": "repoPushMirrorSync",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to sync",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to sync",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/empty"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/push_mirrors/{name}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get push mirror of the repository by remoteName",
+ "operationId": "repoGetPushMirrorByRemoteName",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "remote name of push mirror",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PushMirror"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "deletes a push mirror from a repository by remoteName",
+ "operationId": "repoDeletePushMirror",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "remote name of the pushMirror",
+ "name": "name",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/raw/{filepath}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a file from a repository",
+ "operationId": "repoGetRawFile",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "filepath of the file to get",
+ "name": "filepath",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
+ "name": "ref",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Returns raw file content."
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's releases",
+ "operationId": "repoListReleases",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "filter (exclude / include) drafts, if you dont have repo write access none will show",
+ "name": "draft",
+ "in": "query"
+ },
+ {
+ "type": "boolean",
+ "description": "filter (exclude / include) pre-releases",
+ "name": "pre-release",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results, deprecated - use limit",
+ "name": "per_page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ReleaseList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a release",
+ "operationId": "repoCreateRelease",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateReleaseOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Release"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases/latest": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Gets the most recent non-prerelease, non-draft release of a repository, sorted by created_at",
+ "operationId": "repoGetLatestRelease",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Release"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases/tags/{tag}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a release by tag name",
+ "operationId": "repoGetReleaseByTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "tag name of the release to get",
+ "name": "tag",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Release"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a release by tag name",
+ "operationId": "repoDeleteReleaseByTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "tag name of the release to delete",
+ "name": "tag",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a release",
+ "operationId": "repoGetRelease",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Release"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a release",
+ "operationId": "repoDeleteRelease",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Update a release",
+ "operationId": "repoEditRelease",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditReleaseOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Release"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases/{id}/assets": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List release's attachments",
+ "operationId": "repoListReleaseAttachments",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/AttachmentList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "multipart/form-data"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a release attachment",
+ "operationId": "repoCreateReleaseAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the attachment",
+ "name": "name",
+ "in": "query"
+ },
+ {
+ "type": "file",
+ "description": "attachment to upload",
+ "name": "attachment",
+ "in": "formData",
+ "required": true
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/releases/{id}/assets/{attachment_id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a release attachment",
+ "operationId": "repoGetReleaseAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to get",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a release attachment",
+ "operationId": "repoDeleteReleaseAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to delete",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a release attachment",
+ "operationId": "repoEditReleaseAttachment",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the release",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the attachment to edit",
+ "name": "attachment_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditAttachmentOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Attachment"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/reviewers": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Return all users that can be requested to review in this repo",
+ "operationId": "repoGetReviewers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/signing-key.gpg": {
+ "get": {
+ "produces": [
+ "text/plain"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get signing-key.gpg for given repository",
+ "operationId": "repoSigningKey",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "GPG armored public key",
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/stargazers": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's stargazers",
+ "operationId": "repoListStargazers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/statuses/{sha}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a commit's statuses",
+ "operationId": "repoListStatuses",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "sha of the commit",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "enum": [
+ "oldest",
+ "recentupdate",
+ "leastupdate",
+ "leastindex",
+ "highestindex"
+ ],
+ "type": "string",
+ "description": "type of sort",
+ "name": "sort",
+ "in": "query"
+ },
+ {
+ "enum": [
+ "pending",
+ "success",
+ "error",
+ "failure",
+ "warning"
+ ],
+ "type": "string",
+ "description": "type of state",
+ "name": "state",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/CommitStatusList"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a commit status",
+ "operationId": "repoCreateStatus",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "sha of the commit",
+ "name": "sha",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateStatusOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/CommitStatus"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/subscribers": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's watchers",
+ "operationId": "repoListSubscribers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/subscription": {
+ "get": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Check if the current user is watching a repo",
+ "operationId": "userCurrentCheckSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WatchInfo"
+ },
+ "404": {
+ "description": "User is not watching this repo or repo do not exist"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Watch a repo",
+ "operationId": "userCurrentPutSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WatchInfo"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Unwatch a repo",
+ "operationId": "userCurrentDeleteSubscription",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/tags": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's tags",
+ "operationId": "repoListTags",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results, default maximum page size is 50",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TagList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a new git tag in a repository",
+ "operationId": "repoCreateTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateTagOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Tag"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/empty"
+ },
+ "409": {
+ "$ref": "#/responses/conflict"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/tags/{tag}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get the tag of a repository by tag name",
+ "operationId": "repoGetTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of tag",
+ "name": "tag",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Tag"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a repository's tag by name",
+ "operationId": "repoDeleteTag",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of tag to delete",
+ "name": "tag",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/empty"
+ },
+ "409": {
+ "$ref": "#/responses/conflict"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/teams": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repository's teams",
+ "operationId": "repoListTeams",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TeamList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/teams/{team}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Check if a team is assigned to a repository",
+ "operationId": "repoCheckTeam",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "team name",
+ "name": "team",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Team"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/error"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Add a team to a repository",
+ "operationId": "repoAddTeam",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "team name",
+ "name": "team",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a team from a repository",
+ "operationId": "repoDeleteTeam",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "team name",
+ "name": "team",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "405": {
+ "$ref": "#/responses/error"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/times": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a repo's tracked times",
+ "operationId": "repoTrackedTimes",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "optional filter by user (available for issue managers)",
+ "name": "user",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTimeList"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/times/{user}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "List a user's tracked times in a repo",
+ "operationId": "userTrackedTimes",
+ "deprecated": true,
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "user",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTimeList"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/topics": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get list of topics that a repository has",
+ "operationId": "repoListTopics",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TopicNames"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Replace list of topics for a repository",
+ "operationId": "repoUpdateTopics",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/RepoTopicOptions"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/invalidTopicsError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/topics/{topic}": {
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Add a topic to a repository",
+ "operationId": "repoAddTopic",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the topic to add",
+ "name": "topic",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/invalidTopicsError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a topic from a repository",
+ "operationId": "repoDeleteTopic",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the topic to delete",
+ "name": "topic",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/invalidTopicsError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/transfer": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Transfer a repo ownership",
+ "operationId": "repoTransfer",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to transfer",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to transfer",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "description": "Transfer Options",
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/TransferRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "202": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/transfer/accept": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Accept a repo transfer",
+ "operationId": "acceptRepoTransfer",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to transfer",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to transfer",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "202": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/transfer/reject": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Reject a repo transfer",
+ "operationId": "rejectRepoTransfer",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to transfer",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to transfer",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/wiki/new": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a wiki page",
+ "operationId": "repoCreateWikiPage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateWikiPageOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/WikiPage"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/wiki/page/{pageName}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a wiki page",
+ "operationId": "repoGetWikiPage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the page",
+ "name": "pageName",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WikiPage"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a wiki page",
+ "operationId": "repoDeleteWikiPage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the page",
+ "name": "pageName",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Edit a wiki page",
+ "operationId": "repoEditWikiPage",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the page",
+ "name": "pageName",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateWikiPageOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WikiPage"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/wiki/pages": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get all wiki pages",
+ "operationId": "repoGetWikiPages",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WikiPageList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{owner}/{repo}/wiki/revisions/{pageName}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get revisions of a wiki page",
+ "operationId": "repoGetWikiPageRevisions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the page",
+ "name": "pageName",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/WikiCommitList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/repos/{template_owner}/{template_repo}/generate": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Create a repository using a template",
+ "operationId": "generateRepo",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the template repository owner",
+ "name": "template_owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the template repository",
+ "name": "template_repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/GenerateRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "409": {
+ "description": "The repository with the same name already exists."
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/repositories/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Get a repository by id",
+ "operationId": "repoGetByID",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the repo to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Repository"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/settings/api": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "settings"
+ ],
+ "summary": "Get instance's global settings for api",
+ "operationId": "getGeneralAPISettings",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GeneralAPISettings"
+ }
+ }
+ }
+ },
+ "/settings/attachment": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "settings"
+ ],
+ "summary": "Get instance's global settings for Attachment",
+ "operationId": "getGeneralAttachmentSettings",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GeneralAttachmentSettings"
+ }
+ }
+ }
+ },
+ "/settings/repository": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "settings"
+ ],
+ "summary": "Get instance's global settings for repositories",
+ "operationId": "getGeneralRepositorySettings",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GeneralRepoSettings"
+ }
+ }
+ }
+ },
+ "/settings/ui": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "settings"
+ ],
+ "summary": "Get instance's global settings for ui",
+ "operationId": "getGeneralUISettings",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GeneralUISettings"
+ }
+ }
+ }
+ },
+ "/signing-key.gpg": {
+ "get": {
+ "produces": [
+ "text/plain"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Get default signing-key.gpg",
+ "operationId": "getSigningKey",
+ "responses": {
+ "200": {
+ "description": "GPG armored public key",
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "/teams/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get a team",
+ "operationId": "orgGetTeam",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Team"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "organization"
+ ],
+ "summary": "Delete a team",
+ "operationId": "orgDeleteTeam",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "team deleted"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Edit a team",
+ "operationId": "orgEditTeam",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "id of the team to edit",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditTeamOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Team"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/teams/{id}/activities/feeds": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a team's activity feeds",
+ "operationId": "orgListTeamActivityFeeds",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "format": "date",
+ "description": "the date of the activities to be found",
+ "name": "date",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ActivityFeedsList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/teams/{id}/members": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a team's members",
+ "operationId": "orgListTeamMembers",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/teams/{id}/members/{username}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a particular member of team",
+ "operationId": "orgListTeamMember",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the member to list",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/User"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Add a team member",
+ "operationId": "orgAddTeamMember",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user to add",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Remove a team member",
+ "operationId": "orgRemoveTeamMember",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of the user to remove",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/teams/{id}/repos": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a team's repos",
+ "operationId": "orgListTeamRepos",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/teams/{id}/repos/{org}/{repo}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a particular repo of team",
+ "operationId": "orgListTeamRepo",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "organization that owns the repo to list",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to list",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Repository"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Add a repository to a team",
+ "operationId": "orgAddTeamRepository",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "organization that owns the repo to add",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to add",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "description": "This does not delete the repository, it only removes the repository from the team.",
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Remove a repository from a team",
+ "operationId": "orgRemoveTeamRepository",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the team",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "organization that owns the repo to remove",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to remove",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/topics/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "search topics via keyword",
+ "operationId": "topicSearch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "keywords to search",
+ "name": "q",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TopicListResponse"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get the authenticated user",
+ "operationId": "userGetCurrent",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/User"
+ }
+ }
+ }
+ },
+ "/user/actions/secrets/{secretname}": {
+ "put": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create or Update a secret value in a user scope",
+ "operationId": "updateUserSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateOrUpdateSecretOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "response when creating a secret"
+ },
+ "204": {
+ "description": "response when updating a secret"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete a secret in a user scope",
+ "operationId": "deleteUserSecret",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the secret",
+ "name": "secretname",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": "delete one secret of the user"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/applications/oauth2": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's oauth2 applications",
+ "operationId": "userGetOAuth2Applications",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OAuth2ApplicationList"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "creates a new OAuth2 application",
+ "operationId": "userCreateOAuth2Application",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/OAuth2Application"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/user/applications/oauth2/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "get an OAuth2 Application",
+ "operationId": "userGetOAuth2Application",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "Application ID to be found",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OAuth2Application"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "delete an OAuth2 Application",
+ "operationId": "userDeleteOAuth2Application",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "token to be deleted",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "patch": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "update an OAuth2 Application, this includes regenerating the client secret",
+ "operationId": "userUpdateOAuth2Application",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "application to be updated",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateOAuth2ApplicationOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OAuth2Application"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/avatar": {
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Update Avatar",
+ "operationId": "userUpdateAvatar",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/UpdateUserAvatarOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete Avatar",
+ "operationId": "userDeleteAvatar",
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ }
+ },
+ "/user/block/{username}": {
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Blocks a user from the doer.",
+ "operationId": "userBlockUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/user/emails": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's email addresses",
+ "operationId": "userListEmails",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/EmailList"
+ }
+ }
+ },
+ "post": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Add email addresses",
+ "operationId": "userAddEmail",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateEmailOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/EmailList"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete email addresses",
+ "operationId": "userDeleteEmail",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/DeleteEmailOption"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/followers": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's followers",
+ "operationId": "userCurrentListFollowers",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ }
+ }
+ }
+ },
+ "/user/following": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the users that the authenticated user is following",
+ "operationId": "userCurrentListFollowing",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ }
+ }
+ }
+ },
+ "/user/following/{username}": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Check whether a user is followed by the authenticated user",
+ "operationId": "userCurrentCheckFollowing",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of followed user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Follow a user",
+ "operationId": "userCurrentPutFollow",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to follow",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Unfollow a user",
+ "operationId": "userCurrentDeleteFollow",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to unfollow",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/gpg_key_token": {
+ "get": {
+ "produces": [
+ "text/plain"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a Token to verify",
+ "operationId": "getVerificationToken",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/string"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/gpg_key_verify": {
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Verify a GPG key",
+ "operationId": "userVerifyGPGKey",
+ "responses": {
+ "201": {
+ "$ref": "#/responses/GPGKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/user/gpg_keys": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's GPG keys",
+ "operationId": "userCurrentListGPGKeys",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GPGKeyList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create a GPG key",
+ "operationId": "userCurrentPostGPGKey",
+ "parameters": [
+ {
+ "name": "Form",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateGPGKeyOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/GPGKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/user/gpg_keys/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a GPG key",
+ "operationId": "userCurrentGetGPGKey",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of key to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GPGKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Remove a GPG key",
+ "operationId": "userCurrentDeleteGPGKey",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of key to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's webhooks",
+ "operationId": "userListHooks",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create a hook",
+ "operationId": "userCreateHook",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/user/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a hook",
+ "operationId": "userGetHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete a hook",
+ "operationId": "userDeleteHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Update a hook",
+ "operationId": "userEditHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/user/keys": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's public keys",
+ "operationId": "userCurrentListKeys",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "fingerprint of the key",
+ "name": "fingerprint",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PublicKeyList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create a public key",
+ "operationId": "userCurrentPostKey",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateKeyOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/PublicKey"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/user/keys/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a public key",
+ "operationId": "userCurrentGetKey",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of key to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PublicKey"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete a public key",
+ "operationId": "userCurrentDeleteKey",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of key to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/list_blocked": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's blocked users",
+ "operationId": "userListBlockedUsers",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/BlockedUserList"
+ }
+ }
+ }
+ },
+ "/user/orgs": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List the current user's organizations",
+ "operationId": "orgListCurrentUserOrgs",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OrganizationList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/repos": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the repos that the authenticated user owns",
+ "operationId": "userCurrentListRepos",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository",
+ "user"
+ ],
+ "summary": "Create a repository",
+ "operationId": "createCurrentUserRepo",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateRepoOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Repository"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "409": {
+ "description": "The repository with the same name already exists."
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/user/settings": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get user settings",
+ "operationId": "getUserSettings",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserSettings"
+ }
+ }
+ },
+ "patch": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Update user settings",
+ "operationId": "updateUserSettings",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/UserSettingsOptions"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserSettings"
+ }
+ }
+ }
+ },
+ "/user/starred": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "The repos that the authenticated user has starred",
+ "operationId": "userCurrentListStarred",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ }
+ }
+ }
+ },
+ "/user/starred/{owner}/{repo}": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Whether the authenticated is starring the repo",
+ "operationId": "userCurrentCheckStarring",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Star the given repo",
+ "operationId": "userCurrentPutStar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to star",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to star",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Unstar the given repo",
+ "operationId": "userCurrentDeleteStar",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo to unstar",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo to unstar",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/user/stopwatches": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get list of all existing stopwatches",
+ "operationId": "userGetStopWatches",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/StopWatchList"
+ }
+ }
+ }
+ },
+ "/user/subscriptions": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List repositories watched by the authenticated user",
+ "operationId": "userCurrentListSubscriptions",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ }
+ }
+ }
+ },
+ "/user/teams": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List all the teams a user belongs to",
+ "operationId": "userListTeams",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TeamList"
+ }
+ }
+ }
+ },
+ "/user/times": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the current user's tracked times",
+ "operationId": "userCurrentTrackedTimes",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated after the given time. This is a timestamp in RFC 3339 format",
+ "name": "since",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date-time",
+ "description": "Only show times updated before the given time. This is a timestamp in RFC 3339 format",
+ "name": "before",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTimeList"
+ }
+ }
+ }
+ },
+ "/user/unblock/{username}": {
+ "put": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Unblocks a user from the doer.",
+ "operationId": "userUnblockUser",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/validationError"
+ }
+ }
+ }
+ },
+ "/users/search": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Search for users",
+ "operationId": "userSearch",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "keyword",
+ "name": "q",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "ID of the user to search for",
+ "name": "uid",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "SearchResults of a successful search",
+ "schema": {
+ "type": "object",
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "ok": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/users/{username}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a user",
+ "operationId": "userGet",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to get",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/User"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/activities/feeds": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List a user's activity feeds",
+ "operationId": "userListActivityFeeds",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "boolean",
+ "description": "if true, only show actions performed by the requested user",
+ "name": "only-performed-by",
+ "in": "query"
+ },
+ {
+ "type": "string",
+ "format": "date",
+ "description": "the date of the activities to be found",
+ "name": "date",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ActivityFeedsList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/followers": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the given user's followers",
+ "operationId": "userListFollowers",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/following": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the users that the given user is following",
+ "operationId": "userListFollowing",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/following/{target}": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Check if one user is following another user",
+ "operationId": "userCheckFollowing",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of following user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "username of followed user",
+ "name": "target",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/gpg_keys": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the given user's GPG keys",
+ "operationId": "userListGPGKeys",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/GPGKeyList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/heatmap": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Get a user's heatmap",
+ "operationId": "userGetHeatmapData",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user to get",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/UserHeatmapData"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/keys": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the given user's public keys",
+ "operationId": "userListKeys",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "fingerprint of the key",
+ "name": "fingerprint",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/PublicKeyList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/orgs": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "List a user's organizations",
+ "operationId": "orgListUserOrgs",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OrganizationList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/orgs/{org}/permissions": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "organization"
+ ],
+ "summary": "Get user permissions in organization",
+ "operationId": "orgGetUserPermissions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/OrganizationPermissions"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/repos": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the repos owned by the given user",
+ "operationId": "userListRepos",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/starred": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "The repos that the given user has starred",
+ "operationId": "userListStarred",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/subscriptions": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the repositories watched by a user",
+ "operationId": "userListSubscriptions",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of the user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/RepositoryList"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ }
+ },
+ "/users/{username}/tokens": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "List the authenticated user's access tokens",
+ "operationId": "userGetTokens",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/AccessTokenList"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "Create an access token",
+ "operationId": "userCreateToken",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/CreateAccessTokenOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/AccessToken"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ }
+ }
+ }
+ },
+ "/users/{username}/tokens/{token}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "user"
+ ],
+ "summary": "delete an access token",
+ "operationId": "userDeleteAccessToken",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "token to be deleted, identified by ID and if not available by name",
+ "name": "token",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "403": {
+ "$ref": "#/responses/forbidden"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ },
+ "422": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
+ "/version": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "miscellaneous"
+ ],
+ "summary": "Returns the version of the Gitea application",
+ "operationId": "getVersion",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/ServerVersion"
+ }
+ }
+ }
+ }
+ },
+ "definitions": {
+ "APIError": {
+ "description": "APIError is an api error with a message",
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "AccessToken": {
+ "type": "object",
+ "title": "AccessToken represents an API access token.",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "scopes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Scopes"
+ },
+ "sha1": {
+ "type": "string",
+ "x-go-name": "Token"
+ },
+ "token_last_eight": {
+ "type": "string",
+ "x-go-name": "TokenLastEight"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Activity": {
+ "type": "object",
+ "properties": {
+ "act_user": {
+ "$ref": "#/definitions/User"
+ },
+ "act_user_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ActUserID"
+ },
+ "comment": {
+ "$ref": "#/definitions/Comment"
+ },
+ "comment_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "CommentID"
+ },
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "is_private": {
+ "type": "boolean",
+ "x-go-name": "IsPrivate"
+ },
+ "op_type": {
+ "type": "string",
+ "x-go-name": "OpType"
+ },
+ "ref_name": {
+ "type": "string",
+ "x-go-name": "RefName"
+ },
+ "repo": {
+ "$ref": "#/definitions/Repository"
+ },
+ "repo_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RepoID"
+ },
+ "user_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "UserID"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ActivityPub": {
+ "description": "ActivityPub type",
+ "type": "object",
+ "properties": {
+ "@context": {
+ "type": "string",
+ "x-go-name": "Context"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "AddCollaboratorOption": {
+ "description": "AddCollaboratorOption options when adding a user as a collaborator of a repository",
+ "type": "object",
+ "properties": {
+ "permission": {
+ "type": "string",
+ "x-go-name": "Permission"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "AddTimeOption": {
+ "description": "AddTimeOption options for adding time to an issue",
+ "type": "object",
+ "required": [
+ "time"
+ ],
+ "properties": {
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "time": {
+ "description": "time in seconds",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Time"
+ },
+ "user_name": {
+ "description": "User who spent the time (optional)",
+ "type": "string",
+ "x-go-name": "User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "AnnotatedTag": {
+ "description": "AnnotatedTag represents an annotated tag",
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "object": {
+ "$ref": "#/definitions/AnnotatedTagObject"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "tag": {
+ "type": "string",
+ "x-go-name": "Tag"
+ },
+ "tagger": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "AnnotatedTagObject": {
+ "description": "AnnotatedTagObject contains meta information of the tag object",
+ "type": "object",
+ "properties": {
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Attachment": {
+ "description": "Attachment a generic attachment",
+ "type": "object",
+ "properties": {
+ "browser_download_url": {
+ "type": "string",
+ "x-go-name": "DownloadURL"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "download_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "DownloadCount"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Size"
+ },
+ "uuid": {
+ "type": "string",
+ "x-go-name": "UUID"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "BlockedUser": {
+ "type": "object",
+ "title": "BlockedUser represents a blocked user.",
+ "properties": {
+ "block_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "BlockID"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Branch": {
+ "description": "Branch represents a repository branch",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/PayloadCommit"
+ },
+ "effective_branch_protection_name": {
+ "type": "string",
+ "x-go-name": "EffectiveBranchProtectionName"
+ },
+ "enable_status_check": {
+ "type": "boolean",
+ "x-go-name": "EnableStatusCheck"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "protected": {
+ "type": "boolean",
+ "x-go-name": "Protected"
+ },
+ "required_approvals": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RequiredApprovals"
+ },
+ "status_check_contexts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "StatusCheckContexts"
+ },
+ "user_can_merge": {
+ "type": "boolean",
+ "x-go-name": "UserCanMerge"
+ },
+ "user_can_push": {
+ "type": "boolean",
+ "x-go-name": "UserCanPush"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "BranchProtection": {
+ "description": "BranchProtection represents a branch protection for a repository",
+ "type": "object",
+ "properties": {
+ "approvals_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistTeams"
+ },
+ "approvals_whitelist_username": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistUsernames"
+ },
+ "block_on_official_review_requests": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOfficialReviewRequests"
+ },
+ "block_on_outdated_branch": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOutdatedBranch"
+ },
+ "block_on_rejected_reviews": {
+ "type": "boolean",
+ "x-go-name": "BlockOnRejectedReviews"
+ },
+ "branch_name": {
+ "description": "Deprecated: true",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "dismiss_stale_approvals": {
+ "type": "boolean",
+ "x-go-name": "DismissStaleApprovals"
+ },
+ "enable_approvals_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableApprovalsWhitelist"
+ },
+ "enable_merge_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableMergeWhitelist"
+ },
+ "enable_push": {
+ "type": "boolean",
+ "x-go-name": "EnablePush"
+ },
+ "enable_push_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnablePushWhitelist"
+ },
+ "enable_status_check": {
+ "type": "boolean",
+ "x-go-name": "EnableStatusCheck"
+ },
+ "merge_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistTeams"
+ },
+ "merge_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistUsernames"
+ },
+ "protected_file_patterns": {
+ "type": "string",
+ "x-go-name": "ProtectedFilePatterns"
+ },
+ "push_whitelist_deploy_keys": {
+ "type": "boolean",
+ "x-go-name": "PushWhitelistDeployKeys"
+ },
+ "push_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistTeams"
+ },
+ "push_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistUsernames"
+ },
+ "require_signed_commits": {
+ "type": "boolean",
+ "x-go-name": "RequireSignedCommits"
+ },
+ "required_approvals": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RequiredApprovals"
+ },
+ "rule_name": {
+ "type": "string",
+ "x-go-name": "RuleName"
+ },
+ "status_check_contexts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "StatusCheckContexts"
+ },
+ "unprotected_file_patterns": {
+ "type": "string",
+ "x-go-name": "UnprotectedFilePatterns"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ChangeFileOperation": {
+ "description": "ChangeFileOperation for creating, updating or deleting a file",
+ "type": "object",
+ "required": [
+ "operation",
+ "path"
+ ],
+ "properties": {
+ "content": {
+ "description": "new or updated file content, must be base64 encoded",
+ "type": "string",
+ "x-go-name": "ContentBase64"
+ },
+ "from_path": {
+ "description": "old path of the file to move",
+ "type": "string",
+ "x-go-name": "FromPath"
+ },
+ "operation": {
+ "description": "indicates what to do with the file",
+ "type": "string",
+ "enum": [
+ "create",
+ "update",
+ "delete"
+ ],
+ "x-go-name": "Operation"
+ },
+ "path": {
+ "description": "path to the existing or new file",
+ "type": "string",
+ "x-go-name": "Path"
+ },
+ "sha": {
+ "description": "sha is the SHA for the file that already exists, required for update or delete",
+ "type": "string",
+ "x-go-name": "SHA"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ChangeFilesOptions": {
+ "description": "ChangeFilesOptions options for creating, updating or deleting multiple files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
+ "type": "object",
+ "required": [
+ "files"
+ ],
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/Identity"
+ },
+ "branch": {
+ "description": "branch (optional) to base this file from. if not given, the default branch is used",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "committer": {
+ "$ref": "#/definitions/Identity"
+ },
+ "dates": {
+ "$ref": "#/definitions/CommitDateOptions"
+ },
+ "files": {
+ "description": "list of file operations",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ChangeFileOperation"
+ },
+ "x-go-name": "Files"
+ },
+ "message": {
+ "description": "message (optional) for the commit of this file. if not supplied, a default message will be used",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "new_branch": {
+ "description": "new_branch (optional) will make a new branch from `branch` before creating the file",
+ "type": "string",
+ "x-go-name": "NewBranchName"
+ },
+ "signoff": {
+ "description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
+ "type": "boolean",
+ "x-go-name": "Signoff"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ChangedFile": {
+ "description": "ChangedFile store information about files affected by the pull request",
+ "type": "object",
+ "properties": {
+ "additions": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Additions"
+ },
+ "changes": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Changes"
+ },
+ "contents_url": {
+ "type": "string",
+ "x-go-name": "ContentsURL"
+ },
+ "deletions": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Deletions"
+ },
+ "filename": {
+ "type": "string",
+ "x-go-name": "Filename"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "previous_filename": {
+ "type": "string",
+ "x-go-name": "PreviousFilename"
+ },
+ "raw_url": {
+ "type": "string",
+ "x-go-name": "RawURL"
+ },
+ "status": {
+ "type": "string",
+ "x-go-name": "Status"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CombinedStatus": {
+ "description": "CombinedStatus holds the combined state of several statuses for a single commit",
+ "type": "object",
+ "properties": {
+ "commit_url": {
+ "type": "string",
+ "x-go-name": "CommitURL"
+ },
+ "repository": {
+ "$ref": "#/definitions/Repository"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "state": {
+ "$ref": "#/definitions/CommitStatusState"
+ },
+ "statuses": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CommitStatus"
+ },
+ "x-go-name": "Statuses"
+ },
+ "total_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "TotalCount"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Comment": {
+ "description": "Comment represents a comment on a commit or issue",
+ "type": "object",
+ "properties": {
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Attachment"
+ },
+ "x-go-name": "Attachments"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "issue_url": {
+ "type": "string",
+ "x-go-name": "IssueURL"
+ },
+ "original_author": {
+ "type": "string",
+ "x-go-name": "OriginalAuthor"
+ },
+ "original_author_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OriginalAuthorID"
+ },
+ "pull_request_url": {
+ "type": "string",
+ "x-go-name": "PRURL"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Commit": {
+ "type": "object",
+ "title": "Commit contains information generated from a Git commit.",
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/User"
+ },
+ "commit": {
+ "$ref": "#/definitions/RepoCommit"
+ },
+ "committer": {
+ "$ref": "#/definitions/User"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CommitAffectedFiles"
+ },
+ "x-go-name": "Files"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "parents": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CommitMeta"
+ },
+ "x-go-name": "Parents"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "stats": {
+ "$ref": "#/definitions/CommitStats"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitAffectedFiles": {
+ "description": "CommitAffectedFiles store information about files affected by the commit",
+ "type": "object",
+ "properties": {
+ "filename": {
+ "type": "string",
+ "x-go-name": "Filename"
+ },
+ "status": {
+ "type": "string",
+ "x-go-name": "Status"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitDateOptions": {
+ "description": "CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE",
+ "type": "object",
+ "properties": {
+ "author": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Author"
+ },
+ "committer": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Committer"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitMeta": {
+ "type": "object",
+ "title": "CommitMeta contains meta information of a commit in terms of API.",
+ "properties": {
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitStats": {
+ "description": "CommitStats is statistics for a RepoCommit",
+ "type": "object",
+ "properties": {
+ "additions": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Additions"
+ },
+ "deletions": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Deletions"
+ },
+ "total": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Total"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitStatus": {
+ "description": "CommitStatus holds a single status of a single Commit",
+ "type": "object",
+ "properties": {
+ "context": {
+ "type": "string",
+ "x-go-name": "Context"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "creator": {
+ "$ref": "#/definitions/User"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "status": {
+ "$ref": "#/definitions/CommitStatusState"
+ },
+ "target_url": {
+ "type": "string",
+ "x-go-name": "TargetURL"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitStatusState": {
+ "description": "CommitStatusState holds the state of a CommitStatus\nIt can be \"pending\", \"success\", \"error\" and \"failure\"",
+ "type": "string",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CommitUser": {
+ "type": "object",
+ "title": "CommitUser contains information of a user in the context of a commit.",
+ "properties": {
+ "date": {
+ "type": "string",
+ "x-go-name": "Date"
+ },
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ContentsResponse": {
+ "description": "ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content",
+ "type": "object",
+ "properties": {
+ "_links": {
+ "$ref": "#/definitions/FileLinksResponse"
+ },
+ "content": {
+ "description": "`content` is populated when `type` is `file`, otherwise null",
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "download_url": {
+ "type": "string",
+ "x-go-name": "DownloadURL"
+ },
+ "encoding": {
+ "description": "`encoding` is populated when `type` is `file`, otherwise null",
+ "type": "string",
+ "x-go-name": "Encoding"
+ },
+ "git_url": {
+ "type": "string",
+ "x-go-name": "GitURL"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "last_commit_sha": {
+ "type": "string",
+ "x-go-name": "LastCommitSHA"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "path": {
+ "type": "string",
+ "x-go-name": "Path"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Size"
+ },
+ "submodule_git_url": {
+ "description": "`submodule_git_url` is populated when `type` is `submodule`, otherwise null",
+ "type": "string",
+ "x-go-name": "SubmoduleGitURL"
+ },
+ "target": {
+ "description": "`target` is populated when `type` is `symlink`, otherwise null",
+ "type": "string",
+ "x-go-name": "Target"
+ },
+ "type": {
+ "description": "`type` will be `file`, `dir`, `symlink`, or `submodule`",
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateAccessTokenOption": {
+ "description": "CreateAccessTokenOption options when create access token",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "scopes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Scopes"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateBranchProtectionOption": {
+ "description": "CreateBranchProtectionOption options for creating a branch protection",
+ "type": "object",
+ "properties": {
+ "approvals_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistTeams"
+ },
+ "approvals_whitelist_username": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistUsernames"
+ },
+ "block_on_official_review_requests": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOfficialReviewRequests"
+ },
+ "block_on_outdated_branch": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOutdatedBranch"
+ },
+ "block_on_rejected_reviews": {
+ "type": "boolean",
+ "x-go-name": "BlockOnRejectedReviews"
+ },
+ "branch_name": {
+ "description": "Deprecated: true",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "dismiss_stale_approvals": {
+ "type": "boolean",
+ "x-go-name": "DismissStaleApprovals"
+ },
+ "enable_approvals_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableApprovalsWhitelist"
+ },
+ "enable_merge_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableMergeWhitelist"
+ },
+ "enable_push": {
+ "type": "boolean",
+ "x-go-name": "EnablePush"
+ },
+ "enable_push_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnablePushWhitelist"
+ },
+ "enable_status_check": {
+ "type": "boolean",
+ "x-go-name": "EnableStatusCheck"
+ },
+ "merge_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistTeams"
+ },
+ "merge_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistUsernames"
+ },
+ "protected_file_patterns": {
+ "type": "string",
+ "x-go-name": "ProtectedFilePatterns"
+ },
+ "push_whitelist_deploy_keys": {
+ "type": "boolean",
+ "x-go-name": "PushWhitelistDeployKeys"
+ },
+ "push_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistTeams"
+ },
+ "push_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistUsernames"
+ },
+ "require_signed_commits": {
+ "type": "boolean",
+ "x-go-name": "RequireSignedCommits"
+ },
+ "required_approvals": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RequiredApprovals"
+ },
+ "rule_name": {
+ "type": "string",
+ "x-go-name": "RuleName"
+ },
+ "status_check_contexts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "StatusCheckContexts"
+ },
+ "unprotected_file_patterns": {
+ "type": "string",
+ "x-go-name": "UnprotectedFilePatterns"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateBranchRepoOption": {
+ "description": "CreateBranchRepoOption options when creating a branch in a repository",
+ "type": "object",
+ "required": [
+ "new_branch_name"
+ ],
+ "properties": {
+ "new_branch_name": {
+ "description": "Name of the branch to create",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "BranchName"
+ },
+ "old_branch_name": {
+ "description": "Deprecated: true\nName of the old branch to create from",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "OldBranchName"
+ },
+ "old_ref_name": {
+ "description": "Name of the old branch/tag/commit to create from",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "OldRefName"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateEmailOption": {
+ "description": "CreateEmailOption options when creating email addresses",
+ "type": "object",
+ "properties": {
+ "emails": {
+ "description": "email addresses to add",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Emails"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateFileOptions": {
+ "description": "CreateFileOptions options for creating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
+ "type": "object",
+ "required": [
+ "content"
+ ],
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/Identity"
+ },
+ "branch": {
+ "description": "branch (optional) to base this file from. if not given, the default branch is used",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "committer": {
+ "$ref": "#/definitions/Identity"
+ },
+ "content": {
+ "description": "content must be base64 encoded",
+ "type": "string",
+ "x-go-name": "ContentBase64"
+ },
+ "dates": {
+ "$ref": "#/definitions/CommitDateOptions"
+ },
+ "message": {
+ "description": "message (optional) for the commit of this file. if not supplied, a default message will be used",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "new_branch": {
+ "description": "new_branch (optional) will make a new branch from `branch` before creating the file",
+ "type": "string",
+ "x-go-name": "NewBranchName"
+ },
+ "signoff": {
+ "description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
+ "type": "boolean",
+ "x-go-name": "Signoff"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateForkOption": {
+ "description": "CreateForkOption options for creating a fork",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "name of the forked repository",
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "organization": {
+ "description": "organization name, if forking into an organization",
+ "type": "string",
+ "x-go-name": "Organization"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateGPGKeyOption": {
+ "description": "CreateGPGKeyOption options create user GPG key",
+ "type": "object",
+ "required": [
+ "armored_public_key"
+ ],
+ "properties": {
+ "armored_public_key": {
+ "description": "An armored GPG key to add",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "ArmoredKey"
+ },
+ "armored_signature": {
+ "type": "string",
+ "x-go-name": "Signature"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateHookOption": {
+ "description": "CreateHookOption options when create a hook",
+ "type": "object",
+ "required": [
+ "type",
+ "config"
+ ],
+ "properties": {
+ "active": {
+ "type": "boolean",
+ "default": false,
+ "x-go-name": "Active"
+ },
+ "authorization_header": {
+ "type": "string",
+ "x-go-name": "AuthorizationHeader"
+ },
+ "branch_filter": {
+ "type": "string",
+ "x-go-name": "BranchFilter"
+ },
+ "config": {
+ "$ref": "#/definitions/CreateHookOptionConfig"
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Events"
+ },
+ "type": {
+ "type": "string",
+ "enum": [
+ "forgejo",
+ "dingtalk",
+ "discord",
+ "gitea",
+ "gogs",
+ "msteams",
+ "slack",
+ "telegram",
+ "feishu",
+ "wechatwork",
+ "packagist"
+ ],
+ "x-go-name": "Type"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateHookOptionConfig": {
+ "description": "CreateHookOptionConfig has all config options in it\nrequired are \"content_type\" and \"url\" Required",
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateIssueCommentOption": {
+ "description": "CreateIssueCommentOption options for creating a comment on an issue",
+ "type": "object",
+ "required": [
+ "body"
+ ],
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateIssueOption": {
+ "description": "CreateIssueOption options to create one issue",
+ "type": "object",
+ "required": [
+ "title"
+ ],
+ "properties": {
+ "assignee": {
+ "description": "deprecated",
+ "type": "string",
+ "x-go-name": "Assignee"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Assignees"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "closed": {
+ "type": "boolean",
+ "x-go-name": "Closed"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "labels": {
+ "description": "list of label ids",
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "x-go-name": "Labels"
+ },
+ "milestone": {
+ "description": "milestone id",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Milestone"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateKeyOption": {
+ "description": "CreateKeyOption options when creating a key",
+ "type": "object",
+ "required": [
+ "title",
+ "key"
+ ],
+ "properties": {
+ "key": {
+ "description": "An armored SSH key to add",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "Key"
+ },
+ "read_only": {
+ "description": "Describe if the key has only read access or read/write",
+ "type": "boolean",
+ "x-go-name": "ReadOnly"
+ },
+ "title": {
+ "description": "Title of the key to add",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateLabelOption": {
+ "description": "CreateLabelOption options for creating a label",
+ "type": "object",
+ "required": [
+ "name",
+ "color"
+ ],
+ "properties": {
+ "color": {
+ "type": "string",
+ "x-go-name": "Color",
+ "example": "#00aabb"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "exclusive": {
+ "type": "boolean",
+ "x-go-name": "Exclusive",
+ "example": false
+ },
+ "is_archived": {
+ "type": "boolean",
+ "x-go-name": "IsArchived",
+ "example": false
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateMilestoneOption": {
+ "description": "CreateMilestoneOption options for creating a milestone",
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "due_on": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "state": {
+ "type": "string",
+ "enum": [
+ "open",
+ "closed"
+ ],
+ "x-go-name": "State"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateOAuth2ApplicationOptions": {
+ "description": "CreateOAuth2ApplicationOptions holds options to create an oauth2 application",
+ "type": "object",
+ "properties": {
+ "confidential_client": {
+ "type": "boolean",
+ "x-go-name": "ConfidentialClient"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "redirect_uris": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "RedirectURIs"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateOrUpdateSecretOption": {
+ "description": "CreateOrUpdateSecretOption options when creating or updating secret",
+ "type": "object",
+ "required": [
+ "data"
+ ],
+ "properties": {
+ "data": {
+ "description": "Data of the secret to update",
+ "type": "string",
+ "x-go-name": "Data"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateOrgOption": {
+ "description": "CreateOrgOption options for creating an organization",
+ "type": "object",
+ "required": [
+ "username"
+ ],
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "email": {
+ "type": "string",
+ "x-go-name": "Email"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "repo_admin_change_team_access": {
+ "type": "boolean",
+ "x-go-name": "RepoAdminChangeTeamAccess"
+ },
+ "username": {
+ "type": "string",
+ "x-go-name": "UserName"
+ },
+ "visibility": {
+ "description": "possible values are `public` (default), `limited` or `private`",
+ "type": "string",
+ "enum": [
+ "public",
+ "limited",
+ "private"
+ ],
+ "x-go-name": "Visibility"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreatePullRequestOption": {
+ "description": "CreatePullRequestOption options when creating a pull request",
+ "type": "object",
+ "properties": {
+ "assignee": {
+ "type": "string",
+ "x-go-name": "Assignee"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Assignees"
+ },
+ "base": {
+ "type": "string",
+ "x-go-name": "Base"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "head": {
+ "type": "string",
+ "x-go-name": "Head"
+ },
+ "labels": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "x-go-name": "Labels"
+ },
+ "milestone": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Milestone"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreatePullReviewComment": {
+ "description": "CreatePullReviewComment represent a review comment for creation api",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "new_position": {
+ "description": "if comment to new file line or 0",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "NewLineNum"
+ },
+ "old_position": {
+ "description": "if comment to old file line or 0",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OldLineNum"
+ },
+ "path": {
+ "description": "the tree path",
+ "type": "string",
+ "x-go-name": "Path"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreatePullReviewOptions": {
+ "description": "CreatePullReviewOptions are options to create a pull review",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "comments": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CreatePullReviewComment"
+ },
+ "x-go-name": "Comments"
+ },
+ "commit_id": {
+ "type": "string",
+ "x-go-name": "CommitID"
+ },
+ "event": {
+ "$ref": "#/definitions/ReviewStateType"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreatePushMirrorOption": {
+ "type": "object",
+ "title": "CreatePushMirrorOption represents need information to create a push mirror of a repository.",
+ "properties": {
+ "interval": {
+ "type": "string",
+ "x-go-name": "Interval"
+ },
+ "remote_address": {
+ "type": "string",
+ "x-go-name": "RemoteAddress"
+ },
+ "remote_password": {
+ "type": "string",
+ "x-go-name": "RemotePassword"
+ },
+ "remote_username": {
+ "type": "string",
+ "x-go-name": "RemoteUsername"
+ },
+ "sync_on_commit": {
+ "type": "boolean",
+ "x-go-name": "SyncOnCommit"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateReleaseOption": {
+ "description": "CreateReleaseOption options when creating a release",
+ "type": "object",
+ "required": [
+ "tag_name"
+ ],
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Note"
+ },
+ "draft": {
+ "type": "boolean",
+ "x-go-name": "IsDraft"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "prerelease": {
+ "type": "boolean",
+ "x-go-name": "IsPrerelease"
+ },
+ "tag_name": {
+ "type": "string",
+ "x-go-name": "TagName"
+ },
+ "target_commitish": {
+ "type": "string",
+ "x-go-name": "Target"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateRepoOption": {
+ "description": "CreateRepoOption options when creating repository",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "auto_init": {
+ "description": "Whether the repository should be auto-initialized?",
+ "type": "boolean",
+ "x-go-name": "AutoInit"
+ },
+ "default_branch": {
+ "description": "DefaultBranch of the repository (used when initializes and in template)",
+ "type": "string",
+ "x-go-name": "DefaultBranch"
+ },
+ "description": {
+ "description": "Description of the repository to create",
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "gitignores": {
+ "description": "Gitignores to use",
+ "type": "string",
+ "x-go-name": "Gitignores"
+ },
+ "issue_labels": {
+ "description": "Label-Set to use",
+ "type": "string",
+ "x-go-name": "IssueLabels"
+ },
+ "license": {
+ "description": "License to use",
+ "type": "string",
+ "x-go-name": "License"
+ },
+ "name": {
+ "description": "Name of the repository to create",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "Name"
+ },
+ "private": {
+ "description": "Whether the repository is private",
+ "type": "boolean",
+ "x-go-name": "Private"
+ },
+ "readme": {
+ "description": "Readme of the repository to create",
+ "type": "string",
+ "x-go-name": "Readme"
+ },
+ "template": {
+ "description": "Whether the repository is template",
+ "type": "boolean",
+ "x-go-name": "Template"
+ },
+ "trust_model": {
+ "description": "TrustModel of the repository",
+ "type": "string",
+ "enum": [
+ "default",
+ "collaborator",
+ "committer",
+ "collaboratorcommitter"
+ ],
+ "x-go-name": "TrustModel"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateStatusOption": {
+ "description": "CreateStatusOption holds the information needed to create a new CommitStatus for a Commit",
+ "type": "object",
+ "properties": {
+ "context": {
+ "type": "string",
+ "x-go-name": "Context"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "state": {
+ "$ref": "#/definitions/CommitStatusState"
+ },
+ "target_url": {
+ "type": "string",
+ "x-go-name": "TargetURL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateTagOption": {
+ "description": "CreateTagOption options when creating a tag",
+ "type": "object",
+ "required": [
+ "tag_name"
+ ],
+ "properties": {
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "tag_name": {
+ "type": "string",
+ "x-go-name": "TagName"
+ },
+ "target": {
+ "type": "string",
+ "x-go-name": "Target"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateTeamOption": {
+ "description": "CreateTeamOption options for creating a team",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "can_create_org_repo": {
+ "type": "boolean",
+ "x-go-name": "CanCreateOrgRepo"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "permission": {
+ "type": "string",
+ "enum": [
+ "read",
+ "write",
+ "admin"
+ ],
+ "x-go-name": "Permission"
+ },
+ "units": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Units",
+ "example": [
+ "repo.actions",
+ "repo.code",
+ "repo.issues",
+ "repo.ext_issues",
+ "repo.wiki",
+ "repo.ext_wiki",
+ "repo.pulls",
+ "repo.releases",
+ "repo.projects",
+ "repo.ext_wiki"
+ ]
+ },
+ "units_map": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-name": "UnitsMap",
+ "example": "{\"repo.actions\",\"repo.packages\",\"repo.code\":\"read\",\"repo.issues\":\"write\",\"repo.ext_issues\":\"none\",\"repo.wiki\":\"admin\",\"repo.pulls\":\"owner\",\"repo.releases\":\"none\",\"repo.projects\":\"none\",\"repo.ext_wiki\":\"none\"}"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateUserOption": {
+ "description": "CreateUserOption create user options",
+ "type": "object",
+ "required": [
+ "username",
+ "email"
+ ],
+ "properties": {
+ "created_at": {
+ "description": "For explicitly setting the user creation timestamp. Useful when users are\nmigrated from other systems. When omitted, the user's creation timestamp\nwill be set to \"now\".",
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "login_name": {
+ "type": "string",
+ "x-go-name": "LoginName"
+ },
+ "must_change_password": {
+ "type": "boolean",
+ "x-go-name": "MustChangePassword"
+ },
+ "password": {
+ "type": "string",
+ "x-go-name": "Password"
+ },
+ "restricted": {
+ "type": "boolean",
+ "x-go-name": "Restricted"
+ },
+ "send_notify": {
+ "type": "boolean",
+ "x-go-name": "SendNotify"
+ },
+ "source_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "SourceID"
+ },
+ "username": {
+ "type": "string",
+ "x-go-name": "Username"
+ },
+ "visibility": {
+ "type": "string",
+ "x-go-name": "Visibility"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "CreateWikiPageOptions": {
+ "description": "CreateWikiPageOptions form for creating wiki",
+ "type": "object",
+ "properties": {
+ "content_base64": {
+ "description": "content must be base64 encoded",
+ "type": "string",
+ "x-go-name": "ContentBase64"
+ },
+ "message": {
+ "description": "optional commit message summarizing the change",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "title": {
+ "description": "page title. leave empty to keep unchanged",
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Cron": {
+ "description": "Cron represents a Cron task",
+ "type": "object",
+ "properties": {
+ "exec_times": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ExecTimes"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "next": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Next"
+ },
+ "prev": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Prev"
+ },
+ "schedule": {
+ "type": "string",
+ "x-go-name": "Schedule"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "DeleteEmailOption": {
+ "description": "DeleteEmailOption options when deleting email addresses",
+ "type": "object",
+ "properties": {
+ "emails": {
+ "description": "email addresses to delete",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Emails"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "DeleteFileOptions": {
+ "description": "DeleteFileOptions options for deleting files (used for other File structs below)\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
+ "type": "object",
+ "required": [
+ "sha"
+ ],
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/Identity"
+ },
+ "branch": {
+ "description": "branch (optional) to base this file from. if not given, the default branch is used",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "committer": {
+ "$ref": "#/definitions/Identity"
+ },
+ "dates": {
+ "$ref": "#/definitions/CommitDateOptions"
+ },
+ "message": {
+ "description": "message (optional) for the commit of this file. if not supplied, a default message will be used",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "new_branch": {
+ "description": "new_branch (optional) will make a new branch from `branch` before creating the file",
+ "type": "string",
+ "x-go-name": "NewBranchName"
+ },
+ "sha": {
+ "description": "sha is the SHA for the file that already exists",
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "signoff": {
+ "description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
+ "type": "boolean",
+ "x-go-name": "Signoff"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "DeleteLabelsOption": {
+ "description": "DeleteLabelOption options for deleting a label",
+ "type": "object",
+ "properties": {
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "DeployKey": {
+ "description": "DeployKey a deploy key",
+ "type": "object",
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "fingerprint": {
+ "type": "string",
+ "x-go-name": "Fingerprint"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "key": {
+ "type": "string",
+ "x-go-name": "Key"
+ },
+ "key_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "KeyID"
+ },
+ "read_only": {
+ "type": "boolean",
+ "x-go-name": "ReadOnly"
+ },
+ "repository": {
+ "$ref": "#/definitions/Repository"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "DismissPullReviewOptions": {
+ "description": "DismissPullReviewOptions are options to dismiss a pull review",
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "priors": {
+ "type": "boolean",
+ "x-go-name": "Priors"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditAttachmentOptions": {
+ "description": "EditAttachmentOptions options for editing attachments",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditBranchProtectionOption": {
+ "description": "EditBranchProtectionOption options for editing a branch protection",
+ "type": "object",
+ "properties": {
+ "approvals_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistTeams"
+ },
+ "approvals_whitelist_username": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "ApprovalsWhitelistUsernames"
+ },
+ "block_on_official_review_requests": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOfficialReviewRequests"
+ },
+ "block_on_outdated_branch": {
+ "type": "boolean",
+ "x-go-name": "BlockOnOutdatedBranch"
+ },
+ "block_on_rejected_reviews": {
+ "type": "boolean",
+ "x-go-name": "BlockOnRejectedReviews"
+ },
+ "dismiss_stale_approvals": {
+ "type": "boolean",
+ "x-go-name": "DismissStaleApprovals"
+ },
+ "enable_approvals_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableApprovalsWhitelist"
+ },
+ "enable_merge_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnableMergeWhitelist"
+ },
+ "enable_push": {
+ "type": "boolean",
+ "x-go-name": "EnablePush"
+ },
+ "enable_push_whitelist": {
+ "type": "boolean",
+ "x-go-name": "EnablePushWhitelist"
+ },
+ "enable_status_check": {
+ "type": "boolean",
+ "x-go-name": "EnableStatusCheck"
+ },
+ "merge_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistTeams"
+ },
+ "merge_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "MergeWhitelistUsernames"
+ },
+ "protected_file_patterns": {
+ "type": "string",
+ "x-go-name": "ProtectedFilePatterns"
+ },
+ "push_whitelist_deploy_keys": {
+ "type": "boolean",
+ "x-go-name": "PushWhitelistDeployKeys"
+ },
+ "push_whitelist_teams": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistTeams"
+ },
+ "push_whitelist_usernames": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "PushWhitelistUsernames"
+ },
+ "require_signed_commits": {
+ "type": "boolean",
+ "x-go-name": "RequireSignedCommits"
+ },
+ "required_approvals": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RequiredApprovals"
+ },
+ "status_check_contexts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "StatusCheckContexts"
+ },
+ "unprotected_file_patterns": {
+ "type": "string",
+ "x-go-name": "UnprotectedFilePatterns"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditDeadlineOption": {
+ "description": "EditDeadlineOption options for creating a deadline",
+ "type": "object",
+ "required": [
+ "due_date"
+ ],
+ "properties": {
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditGitHookOption": {
+ "description": "EditGitHookOption options when modifying one Git hook",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditHookOption": {
+ "description": "EditHookOption options when modify one hook",
+ "type": "object",
+ "properties": {
+ "active": {
+ "type": "boolean",
+ "x-go-name": "Active"
+ },
+ "authorization_header": {
+ "type": "string",
+ "x-go-name": "AuthorizationHeader"
+ },
+ "branch_filter": {
+ "type": "string",
+ "x-go-name": "BranchFilter"
+ },
+ "config": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-name": "Config"
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Events"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditIssueCommentOption": {
+ "description": "EditIssueCommentOption options for editing a comment",
+ "type": "object",
+ "required": [
+ "body"
+ ],
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditIssueOption": {
+ "description": "EditIssueOption options for editing an issue",
+ "type": "object",
+ "properties": {
+ "assignee": {
+ "description": "deprecated",
+ "type": "string",
+ "x-go-name": "Assignee"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Assignees"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "milestone": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Milestone"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "state": {
+ "type": "string",
+ "x-go-name": "State"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "unset_due_date": {
+ "type": "boolean",
+ "x-go-name": "RemoveDeadline"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditLabelOption": {
+ "description": "EditLabelOption options for editing a label",
+ "type": "object",
+ "properties": {
+ "color": {
+ "type": "string",
+ "x-go-name": "Color",
+ "example": "#00aabb"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "exclusive": {
+ "type": "boolean",
+ "x-go-name": "Exclusive",
+ "example": false
+ },
+ "is_archived": {
+ "type": "boolean",
+ "x-go-name": "IsArchived",
+ "example": false
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditMilestoneOption": {
+ "description": "EditMilestoneOption options for editing a milestone",
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "due_on": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "state": {
+ "type": "string",
+ "x-go-name": "State"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditOrgOption": {
+ "description": "EditOrgOption options for editing an organization",
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "email": {
+ "type": "string",
+ "x-go-name": "Email"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "repo_admin_change_team_access": {
+ "type": "boolean",
+ "x-go-name": "RepoAdminChangeTeamAccess"
+ },
+ "visibility": {
+ "description": "possible values are `public`, `limited` or `private`",
+ "type": "string",
+ "enum": [
+ "public",
+ "limited",
+ "private"
+ ],
+ "x-go-name": "Visibility"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditPullRequestOption": {
+ "description": "EditPullRequestOption options when modify pull request",
+ "type": "object",
+ "properties": {
+ "allow_maintainer_edit": {
+ "type": "boolean",
+ "x-go-name": "AllowMaintainerEdit"
+ },
+ "assignee": {
+ "type": "string",
+ "x-go-name": "Assignee"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Assignees"
+ },
+ "base": {
+ "type": "string",
+ "x-go-name": "Base"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "labels": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "x-go-name": "Labels"
+ },
+ "milestone": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Milestone"
+ },
+ "state": {
+ "type": "string",
+ "x-go-name": "State"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "unset_due_date": {
+ "type": "boolean",
+ "x-go-name": "RemoveDeadline"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditReactionOption": {
+ "description": "EditReactionOption contain the reaction type",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "x-go-name": "Reaction"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditReleaseOption": {
+ "description": "EditReleaseOption options when editing a release",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Note"
+ },
+ "draft": {
+ "type": "boolean",
+ "x-go-name": "IsDraft"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "prerelease": {
+ "type": "boolean",
+ "x-go-name": "IsPrerelease"
+ },
+ "tag_name": {
+ "type": "string",
+ "x-go-name": "TagName"
+ },
+ "target_commitish": {
+ "type": "string",
+ "x-go-name": "Target"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditRepoOption": {
+ "description": "EditRepoOption options when editing a repository's properties",
+ "type": "object",
+ "properties": {
+ "allow_manual_merge": {
+ "description": "either `true` to allow mark pr as merged manually, or `false` to prevent it.",
+ "type": "boolean",
+ "x-go-name": "AllowManualMerge"
+ },
+ "allow_merge_commits": {
+ "description": "either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.",
+ "type": "boolean",
+ "x-go-name": "AllowMerge"
+ },
+ "allow_rebase": {
+ "description": "either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.",
+ "type": "boolean",
+ "x-go-name": "AllowRebase"
+ },
+ "allow_rebase_explicit": {
+ "description": "either `true` to allow rebase with explicit merge commits (--no-ff), or `false` to prevent rebase with explicit merge commits.",
+ "type": "boolean",
+ "x-go-name": "AllowRebaseMerge"
+ },
+ "allow_rebase_update": {
+ "description": "either `true` to allow updating pull request branch by rebase, or `false` to prevent it.",
+ "type": "boolean",
+ "x-go-name": "AllowRebaseUpdate"
+ },
+ "allow_squash_merge": {
+ "description": "either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.",
+ "type": "boolean",
+ "x-go-name": "AllowSquash"
+ },
+ "archived": {
+ "description": "set to `true` to archive this repository.",
+ "type": "boolean",
+ "x-go-name": "Archived"
+ },
+ "autodetect_manual_merge": {
+ "description": "either `true` to enable AutodetectManualMerge, or `false` to prevent it. Note: In some special cases, misjudgments can occur.",
+ "type": "boolean",
+ "x-go-name": "AutodetectManualMerge"
+ },
+ "default_allow_maintainer_edit": {
+ "description": "set to `true` to allow edits from maintainers by default",
+ "type": "boolean",
+ "x-go-name": "DefaultAllowMaintainerEdit"
+ },
+ "default_branch": {
+ "description": "sets the default branch for this repository.",
+ "type": "string",
+ "x-go-name": "DefaultBranch"
+ },
+ "default_delete_branch_after_merge": {
+ "description": "set to `true` to delete pr branch after merge by default",
+ "type": "boolean",
+ "x-go-name": "DefaultDeleteBranchAfterMerge"
+ },
+ "default_merge_style": {
+ "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", or \"squash\".",
+ "type": "string",
+ "x-go-name": "DefaultMergeStyle"
+ },
+ "description": {
+ "description": "a short description of the repository.",
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "enable_prune": {
+ "description": "enable prune - remove obsolete remote-tracking references",
+ "type": "boolean",
+ "x-go-name": "EnablePrune"
+ },
+ "external_tracker": {
+ "$ref": "#/definitions/ExternalTracker"
+ },
+ "external_wiki": {
+ "$ref": "#/definitions/ExternalWiki"
+ },
+ "has_actions": {
+ "description": "either `true` to enable actions unit, or `false` to disable them.",
+ "type": "boolean",
+ "x-go-name": "HasActions"
+ },
+ "has_issues": {
+ "description": "either `true` to enable issues for this repository or `false` to disable them.",
+ "type": "boolean",
+ "x-go-name": "HasIssues"
+ },
+ "has_packages": {
+ "description": "either `true` to enable packages unit, or `false` to disable them.",
+ "type": "boolean",
+ "x-go-name": "HasPackages"
+ },
+ "has_projects": {
+ "description": "either `true` to enable project unit, or `false` to disable them.",
+ "type": "boolean",
+ "x-go-name": "HasProjects"
+ },
+ "has_pull_requests": {
+ "description": "either `true` to allow pull requests, or `false` to prevent pull request.",
+ "type": "boolean",
+ "x-go-name": "HasPullRequests"
+ },
+ "has_releases": {
+ "description": "either `true` to enable releases unit, or `false` to disable them.",
+ "type": "boolean",
+ "x-go-name": "HasReleases"
+ },
+ "has_wiki": {
+ "description": "either `true` to enable the wiki for this repository or `false` to disable it.",
+ "type": "boolean",
+ "x-go-name": "HasWiki"
+ },
+ "ignore_whitespace_conflicts": {
+ "description": "either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace.",
+ "type": "boolean",
+ "x-go-name": "IgnoreWhitespaceConflicts"
+ },
+ "internal_tracker": {
+ "$ref": "#/definitions/InternalTracker"
+ },
+ "mirror_interval": {
+ "description": "set to a string like `8h30m0s` to set the mirror interval time",
+ "type": "string",
+ "x-go-name": "MirrorInterval"
+ },
+ "name": {
+ "description": "name of the repository",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "Name"
+ },
+ "private": {
+ "description": "either `true` to make the repository private or `false` to make it public.\nNote: you will get a 422 error if the organization restricts changing repository visibility to organization\nowners and a non-owner tries to change the value of private.",
+ "type": "boolean",
+ "x-go-name": "Private"
+ },
+ "template": {
+ "description": "either `true` to make this repository a template or `false` to make it a normal repository",
+ "type": "boolean",
+ "x-go-name": "Template"
+ },
+ "website": {
+ "description": "a URL with more information about the repository.",
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditTeamOption": {
+ "description": "EditTeamOption options for editing a team",
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "can_create_org_repo": {
+ "type": "boolean",
+ "x-go-name": "CanCreateOrgRepo"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "permission": {
+ "type": "string",
+ "enum": [
+ "read",
+ "write",
+ "admin"
+ ],
+ "x-go-name": "Permission"
+ },
+ "units": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Units",
+ "example": [
+ "repo.code",
+ "repo.issues",
+ "repo.ext_issues",
+ "repo.wiki",
+ "repo.pulls",
+ "repo.releases",
+ "repo.projects",
+ "repo.ext_wiki"
+ ]
+ },
+ "units_map": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-name": "UnitsMap",
+ "example": {
+ "repo.code": "read",
+ "repo.ext_issues": "none",
+ "repo.ext_wiki": "none",
+ "repo.issues": "write",
+ "repo.projects": "none",
+ "repo.pulls": "owner",
+ "repo.releases": "none",
+ "repo.wiki": "admin"
+ }
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "EditUserOption": {
+ "description": "EditUserOption edit user options",
+ "type": "object",
+ "required": [
+ "source_id",
+ "login_name"
+ ],
+ "properties": {
+ "active": {
+ "type": "boolean",
+ "x-go-name": "Active"
+ },
+ "admin": {
+ "type": "boolean",
+ "x-go-name": "Admin"
+ },
+ "allow_create_organization": {
+ "type": "boolean",
+ "x-go-name": "AllowCreateOrganization"
+ },
+ "allow_git_hook": {
+ "type": "boolean",
+ "x-go-name": "AllowGitHook"
+ },
+ "allow_import_local": {
+ "type": "boolean",
+ "x-go-name": "AllowImportLocal"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "login_name": {
+ "type": "string",
+ "x-go-name": "LoginName"
+ },
+ "max_repo_creation": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "MaxRepoCreation"
+ },
+ "must_change_password": {
+ "type": "boolean",
+ "x-go-name": "MustChangePassword"
+ },
+ "password": {
+ "type": "string",
+ "x-go-name": "Password"
+ },
+ "prohibit_login": {
+ "type": "boolean",
+ "x-go-name": "ProhibitLogin"
+ },
+ "restricted": {
+ "type": "boolean",
+ "x-go-name": "Restricted"
+ },
+ "source_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "SourceID"
+ },
+ "visibility": {
+ "type": "string",
+ "x-go-name": "Visibility"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Email": {
+ "description": "Email an email address belonging to a user",
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "primary": {
+ "type": "boolean",
+ "x-go-name": "Primary"
+ },
+ "user_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "UserID"
+ },
+ "username": {
+ "type": "string",
+ "x-go-name": "UserName"
+ },
+ "verified": {
+ "type": "boolean",
+ "x-go-name": "Verified"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ExternalTracker": {
+ "description": "ExternalTracker represents settings for external tracker",
+ "type": "object",
+ "properties": {
+ "external_tracker_format": {
+ "description": "External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.",
+ "type": "string",
+ "x-go-name": "ExternalTrackerFormat"
+ },
+ "external_tracker_regexp_pattern": {
+ "description": "External Issue Tracker issue regular expression",
+ "type": "string",
+ "x-go-name": "ExternalTrackerRegexpPattern"
+ },
+ "external_tracker_style": {
+ "description": "External Issue Tracker Number Format, either `numeric`, `alphanumeric`, or `regexp`",
+ "type": "string",
+ "x-go-name": "ExternalTrackerStyle"
+ },
+ "external_tracker_url": {
+ "description": "URL of external issue tracker.",
+ "type": "string",
+ "x-go-name": "ExternalTrackerURL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ExternalWiki": {
+ "description": "ExternalWiki represents setting for external wiki",
+ "type": "object",
+ "properties": {
+ "external_wiki_url": {
+ "description": "URL of external wiki.",
+ "type": "string",
+ "x-go-name": "ExternalWikiURL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "FileCommitResponse": {
+ "type": "object",
+ "title": "FileCommitResponse contains information generated from a Git commit for a repo's file.",
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "committer": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "parents": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CommitMeta"
+ },
+ "x-go-name": "Parents"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "tree": {
+ "$ref": "#/definitions/CommitMeta"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "FileDeleteResponse": {
+ "description": "FileDeleteResponse contains information about a repo's file that was deleted",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/FileCommitResponse"
+ },
+ "content": {
+ "x-go-name": "Content"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "FileLinksResponse": {
+ "description": "FileLinksResponse contains the links for a repo's file",
+ "type": "object",
+ "properties": {
+ "git": {
+ "type": "string",
+ "x-go-name": "GitURL"
+ },
+ "html": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "self": {
+ "type": "string",
+ "x-go-name": "Self"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "FileResponse": {
+ "description": "FileResponse contains information about a repo's file",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/FileCommitResponse"
+ },
+ "content": {
+ "$ref": "#/definitions/ContentsResponse"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "FilesResponse": {
+ "description": "FilesResponse contains information about multiple files from a repo",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/FileCommitResponse"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ContentsResponse"
+ },
+ "x-go-name": "Files"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GPGKey": {
+ "description": "GPGKey a user GPG key to sign commit and tag in repository",
+ "type": "object",
+ "properties": {
+ "can_certify": {
+ "type": "boolean",
+ "x-go-name": "CanCertify"
+ },
+ "can_encrypt_comms": {
+ "type": "boolean",
+ "x-go-name": "CanEncryptComms"
+ },
+ "can_encrypt_storage": {
+ "type": "boolean",
+ "x-go-name": "CanEncryptStorage"
+ },
+ "can_sign": {
+ "type": "boolean",
+ "x-go-name": "CanSign"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "emails": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GPGKeyEmail"
+ },
+ "x-go-name": "Emails"
+ },
+ "expires_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Expires"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "key_id": {
+ "type": "string",
+ "x-go-name": "KeyID"
+ },
+ "primary_key_id": {
+ "type": "string",
+ "x-go-name": "PrimaryKeyID"
+ },
+ "public_key": {
+ "type": "string",
+ "x-go-name": "PublicKey"
+ },
+ "subkeys": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GPGKey"
+ },
+ "x-go-name": "SubsKey"
+ },
+ "verified": {
+ "type": "boolean",
+ "x-go-name": "Verified"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GPGKeyEmail": {
+ "description": "GPGKeyEmail an email attached to a GPGKey",
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "x-go-name": "Email"
+ },
+ "verified": {
+ "type": "boolean",
+ "x-go-name": "Verified"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GeneralAPISettings": {
+ "description": "GeneralAPISettings contains global api settings exposed by it",
+ "type": "object",
+ "properties": {
+ "default_git_trees_per_page": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "DefaultGitTreesPerPage"
+ },
+ "default_max_blob_size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "DefaultMaxBlobSize"
+ },
+ "default_paging_num": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "DefaultPagingNum"
+ },
+ "max_response_items": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "MaxResponseItems"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GeneralAttachmentSettings": {
+ "description": "GeneralAttachmentSettings contains global Attachment settings exposed by API",
+ "type": "object",
+ "properties": {
+ "allowed_types": {
+ "type": "string",
+ "x-go-name": "AllowedTypes"
+ },
+ "enabled": {
+ "type": "boolean",
+ "x-go-name": "Enabled"
+ },
+ "max_files": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "MaxFiles"
+ },
+ "max_size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "MaxSize"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GeneralRepoSettings": {
+ "description": "GeneralRepoSettings contains global repository settings exposed by API",
+ "type": "object",
+ "properties": {
+ "http_git_disabled": {
+ "type": "boolean",
+ "x-go-name": "HTTPGitDisabled"
+ },
+ "lfs_disabled": {
+ "type": "boolean",
+ "x-go-name": "LFSDisabled"
+ },
+ "migrations_disabled": {
+ "type": "boolean",
+ "x-go-name": "MigrationsDisabled"
+ },
+ "mirrors_disabled": {
+ "type": "boolean",
+ "x-go-name": "MirrorsDisabled"
+ },
+ "stars_disabled": {
+ "type": "boolean",
+ "x-go-name": "StarsDisabled"
+ },
+ "time_tracking_disabled": {
+ "type": "boolean",
+ "x-go-name": "TimeTrackingDisabled"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GeneralUISettings": {
+ "description": "GeneralUISettings contains global ui settings exposed by API",
+ "type": "object",
+ "properties": {
+ "allowed_reactions": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "AllowedReactions"
+ },
+ "custom_emojis": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "CustomEmojis"
+ },
+ "default_theme": {
+ "type": "string",
+ "x-go-name": "DefaultTheme"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GenerateRepoOption": {
+ "description": "GenerateRepoOption options when creating repository using a template",
+ "type": "object",
+ "required": [
+ "owner",
+ "name"
+ ],
+ "properties": {
+ "avatar": {
+ "description": "include avatar of the template repo",
+ "type": "boolean",
+ "x-go-name": "Avatar"
+ },
+ "default_branch": {
+ "description": "Default branch of the new repository",
+ "type": "string",
+ "x-go-name": "DefaultBranch"
+ },
+ "description": {
+ "description": "Description of the repository to create",
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "git_content": {
+ "description": "include git content of default branch in template repo",
+ "type": "boolean",
+ "x-go-name": "GitContent"
+ },
+ "git_hooks": {
+ "description": "include git hooks in template repo",
+ "type": "boolean",
+ "x-go-name": "GitHooks"
+ },
+ "labels": {
+ "description": "include labels in template repo",
+ "type": "boolean",
+ "x-go-name": "Labels"
+ },
+ "name": {
+ "description": "Name of the repository to create",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "Name"
+ },
+ "owner": {
+ "description": "The organization or person who will own the new repository",
+ "type": "string",
+ "x-go-name": "Owner"
+ },
+ "private": {
+ "description": "Whether the repository is private",
+ "type": "boolean",
+ "x-go-name": "Private"
+ },
+ "protected_branch": {
+ "description": "include protected branches in template repo",
+ "type": "boolean",
+ "x-go-name": "ProtectedBranch"
+ },
+ "topics": {
+ "description": "include topics in template repo",
+ "type": "boolean",
+ "x-go-name": "Topics"
+ },
+ "webhooks": {
+ "description": "include webhooks in template repo",
+ "type": "boolean",
+ "x-go-name": "Webhooks"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitBlobResponse": {
+ "description": "GitBlobResponse represents a git blob",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "encoding": {
+ "type": "string",
+ "x-go-name": "Encoding"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Size"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitEntry": {
+ "description": "GitEntry represents a git tree",
+ "type": "object",
+ "properties": {
+ "mode": {
+ "type": "string",
+ "x-go-name": "Mode"
+ },
+ "path": {
+ "type": "string",
+ "x-go-name": "Path"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Size"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitHook": {
+ "description": "GitHook represents a Git repository hook",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "is_active": {
+ "type": "boolean",
+ "x-go-name": "IsActive"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitObject": {
+ "type": "object",
+ "title": "GitObject represents a Git object.",
+ "properties": {
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitTreeResponse": {
+ "description": "GitTreeResponse returns a git tree",
+ "type": "object",
+ "properties": {
+ "page": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Page"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "total_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "TotalCount"
+ },
+ "tree": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GitEntry"
+ },
+ "x-go-name": "Entries"
+ },
+ "truncated": {
+ "type": "boolean",
+ "x-go-name": "Truncated"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "GitignoreTemplateInfo": {
+ "description": "GitignoreTemplateInfo name and text of a gitignore template",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "source": {
+ "type": "string",
+ "x-go-name": "Source"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Hook": {
+ "description": "Hook a hook is a web hook when one repository changed",
+ "type": "object",
+ "properties": {
+ "active": {
+ "type": "boolean",
+ "x-go-name": "Active"
+ },
+ "authorization_header": {
+ "type": "string",
+ "x-go-name": "AuthorizationHeader"
+ },
+ "branch_filter": {
+ "type": "string",
+ "x-go-name": "BranchFilter"
+ },
+ "config": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-name": "Config"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "events": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Events"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Identity": {
+ "description": "Identity for a person's identity like an author or committer",
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "InternalTracker": {
+ "description": "InternalTracker represents settings for internal tracker",
+ "type": "object",
+ "properties": {
+ "allow_only_contributors_to_track_time": {
+ "description": "Let only contributors track time (Built-in issue tracker)",
+ "type": "boolean",
+ "x-go-name": "AllowOnlyContributorsToTrackTime"
+ },
+ "enable_issue_dependencies": {
+ "description": "Enable dependencies for issues and pull requests (Built-in issue tracker)",
+ "type": "boolean",
+ "x-go-name": "EnableIssueDependencies"
+ },
+ "enable_time_tracker": {
+ "description": "Enable time tracking (Built-in issue tracker)",
+ "type": "boolean",
+ "x-go-name": "EnableTimeTracker"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Issue": {
+ "description": "Issue represents an issue in a repository",
+ "type": "object",
+ "properties": {
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Attachment"
+ },
+ "x-go-name": "Attachments"
+ },
+ "assignee": {
+ "$ref": "#/definitions/User"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/User"
+ },
+ "x-go-name": "Assignees"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "closed_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Closed"
+ },
+ "comments": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Comments"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "is_locked": {
+ "type": "boolean",
+ "x-go-name": "IsLocked"
+ },
+ "labels": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Label"
+ },
+ "x-go-name": "Labels"
+ },
+ "milestone": {
+ "$ref": "#/definitions/Milestone"
+ },
+ "number": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Index"
+ },
+ "original_author": {
+ "type": "string",
+ "x-go-name": "OriginalAuthor"
+ },
+ "original_author_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OriginalAuthorID"
+ },
+ "pin_order": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "PinOrder"
+ },
+ "pull_request": {
+ "$ref": "#/definitions/PullRequestMeta"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "repository": {
+ "$ref": "#/definitions/RepositoryMeta"
+ },
+ "state": {
+ "$ref": "#/definitions/StateType"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueConfig": {
+ "type": "object",
+ "properties": {
+ "blank_issues_enabled": {
+ "type": "boolean",
+ "x-go-name": "BlankIssuesEnabled"
+ },
+ "contact_links": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/IssueConfigContactLink"
+ },
+ "x-go-name": "ContactLinks"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueConfigContactLink": {
+ "type": "object",
+ "properties": {
+ "about": {
+ "type": "string",
+ "x-go-name": "About"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueConfigValidation": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "valid": {
+ "type": "boolean",
+ "x-go-name": "Valid"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueDeadline": {
+ "description": "IssueDeadline represents an issue deadline",
+ "type": "object",
+ "properties": {
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueFormField": {
+ "description": "IssueFormField represents a form field",
+ "type": "object",
+ "properties": {
+ "attributes": {
+ "type": "object",
+ "additionalProperties": {},
+ "x-go-name": "Attributes"
+ },
+ "id": {
+ "type": "string",
+ "x-go-name": "ID"
+ },
+ "type": {
+ "$ref": "#/definitions/IssueFormFieldType"
+ },
+ "validations": {
+ "type": "object",
+ "additionalProperties": {},
+ "x-go-name": "Validations"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueFormFieldType": {
+ "type": "string",
+ "title": "IssueFormFieldType defines issue form field type, can be \"markdown\", \"textarea\", \"input\", \"dropdown\" or \"checkboxes\"",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueLabelsOption": {
+ "description": "IssueLabelsOption a collection of labels",
+ "type": "object",
+ "properties": {
+ "labels": {
+ "description": "list of label IDs",
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "x-go-name": "Labels"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueMeta": {
+ "description": "IssueMeta basic issue information",
+ "type": "object",
+ "properties": {
+ "index": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Index"
+ },
+ "owner": {
+ "type": "string",
+ "x-go-name": "Owner"
+ },
+ "repo": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueTemplate": {
+ "description": "IssueTemplate represents an issue template for a repository",
+ "type": "object",
+ "properties": {
+ "about": {
+ "type": "string",
+ "x-go-name": "About"
+ },
+ "body": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/IssueFormField"
+ },
+ "x-go-name": "Fields"
+ },
+ "content": {
+ "type": "string",
+ "x-go-name": "Content"
+ },
+ "file_name": {
+ "type": "string",
+ "x-go-name": "FileName"
+ },
+ "labels": {
+ "$ref": "#/definitions/IssueTemplateLabels"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "IssueTemplateLabels": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Label": {
+ "description": "Label a label to an issue or a pr",
+ "type": "object",
+ "properties": {
+ "color": {
+ "type": "string",
+ "x-go-name": "Color",
+ "example": "00aabb"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "exclusive": {
+ "type": "boolean",
+ "x-go-name": "Exclusive",
+ "example": false
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "is_archived": {
+ "type": "boolean",
+ "x-go-name": "IsArchived",
+ "example": false
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "LabelTemplate": {
+ "description": "LabelTemplate info of a Label template",
+ "type": "object",
+ "properties": {
+ "color": {
+ "type": "string",
+ "x-go-name": "Color",
+ "example": "00aabb"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "exclusive": {
+ "type": "boolean",
+ "x-go-name": "Exclusive",
+ "example": false
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "LicenseTemplateInfo": {
+ "description": "LicensesInfo contains information about a License",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "implementation": {
+ "type": "string",
+ "x-go-name": "Implementation"
+ },
+ "key": {
+ "type": "string",
+ "x-go-name": "Key"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "LicensesTemplateListEntry": {
+ "description": "LicensesListEntry is used for the API",
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "x-go-name": "Key"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "MarkdownOption": {
+ "description": "MarkdownOption markdown options",
+ "type": "object",
+ "properties": {
+ "Context": {
+ "description": "Context to render\n\nin: body",
+ "type": "string"
+ },
+ "Mode": {
+ "description": "Mode to render (comment, gfm, markdown)\n\nin: body",
+ "type": "string"
+ },
+ "Text": {
+ "description": "Text markdown to render\n\nin: body",
+ "type": "string"
+ },
+ "Wiki": {
+ "description": "Is it a wiki page ?\n\nin: body",
+ "type": "boolean"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "MarkupOption": {
+ "description": "MarkupOption markup options",
+ "type": "object",
+ "properties": {
+ "Context": {
+ "description": "Context to render\n\nin: body",
+ "type": "string"
+ },
+ "FilePath": {
+ "description": "File path for detecting extension in file mode\n\nin: body",
+ "type": "string"
+ },
+ "Mode": {
+ "description": "Mode to render (comment, gfm, markdown, file)\n\nin: body",
+ "type": "string"
+ },
+ "Text": {
+ "description": "Text markup to render\n\nin: body",
+ "type": "string"
+ },
+ "Wiki": {
+ "description": "Is it a wiki page ?\n\nin: body",
+ "type": "boolean"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "MergePullRequestOption": {
+ "description": "MergePullRequestForm form for merging Pull Request",
+ "type": "object",
+ "required": [
+ "Do"
+ ],
+ "properties": {
+ "Do": {
+ "type": "string",
+ "enum": [
+ "merge",
+ "rebase",
+ "rebase-merge",
+ "squash",
+ "manually-merged"
+ ]
+ },
+ "MergeCommitID": {
+ "type": "string"
+ },
+ "MergeMessageField": {
+ "type": "string"
+ },
+ "MergeTitleField": {
+ "type": "string"
+ },
+ "delete_branch_after_merge": {
+ "type": "boolean",
+ "x-go-name": "DeleteBranchAfterMerge"
+ },
+ "force_merge": {
+ "type": "boolean",
+ "x-go-name": "ForceMerge"
+ },
+ "head_commit_id": {
+ "type": "string",
+ "x-go-name": "HeadCommitID"
+ },
+ "merge_when_checks_succeed": {
+ "type": "boolean",
+ "x-go-name": "MergeWhenChecksSucceed"
+ }
+ },
+ "x-go-name": "MergePullRequestForm",
+ "x-go-package": "code.gitea.io/gitea/services/forms"
+ },
+ "MigrateRepoOptions": {
+ "description": "MigrateRepoOptions options for migrating repository's\nthis is used to interact with api v1",
+ "type": "object",
+ "required": [
+ "clone_addr",
+ "repo_name"
+ ],
+ "properties": {
+ "auth_password": {
+ "type": "string",
+ "x-go-name": "AuthPassword"
+ },
+ "auth_token": {
+ "type": "string",
+ "x-go-name": "AuthToken"
+ },
+ "auth_username": {
+ "type": "string",
+ "x-go-name": "AuthUsername"
+ },
+ "clone_addr": {
+ "type": "string",
+ "x-go-name": "CloneAddr"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "issues": {
+ "type": "boolean",
+ "x-go-name": "Issues"
+ },
+ "labels": {
+ "type": "boolean",
+ "x-go-name": "Labels"
+ },
+ "lfs": {
+ "type": "boolean",
+ "x-go-name": "LFS"
+ },
+ "lfs_endpoint": {
+ "type": "string",
+ "x-go-name": "LFSEndpoint"
+ },
+ "milestones": {
+ "type": "boolean",
+ "x-go-name": "Milestones"
+ },
+ "mirror": {
+ "type": "boolean",
+ "x-go-name": "Mirror"
+ },
+ "mirror_interval": {
+ "type": "string",
+ "x-go-name": "MirrorInterval"
+ },
+ "private": {
+ "type": "boolean",
+ "x-go-name": "Private"
+ },
+ "pull_requests": {
+ "type": "boolean",
+ "x-go-name": "PullRequests"
+ },
+ "releases": {
+ "type": "boolean",
+ "x-go-name": "Releases"
+ },
+ "repo_name": {
+ "type": "string",
+ "x-go-name": "RepoName"
+ },
+ "repo_owner": {
+ "description": "Name of User or Organisation who will own Repo after migration",
+ "type": "string",
+ "x-go-name": "RepoOwner"
+ },
+ "service": {
+ "type": "string",
+ "enum": [
+ "git",
+ "github",
+ "gitea",
+ "gitlab",
+ "gogs",
+ "onedev",
+ "gitbucket",
+ "codebase"
+ ],
+ "x-go-name": "Service"
+ },
+ "uid": {
+ "description": "deprecated (only for backwards compatibility)",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RepoOwnerID"
+ },
+ "wiki": {
+ "type": "boolean",
+ "x-go-name": "Wiki"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Milestone": {
+ "description": "Milestone milestone is a collection of issues on one repository",
+ "type": "object",
+ "properties": {
+ "closed_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Closed"
+ },
+ "closed_issues": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ClosedIssues"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "due_on": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "open_issues": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OpenIssues"
+ },
+ "state": {
+ "$ref": "#/definitions/StateType"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NewIssuePinsAllowed": {
+ "description": "NewIssuePinsAllowed represents an API response that says if new Issue Pins are allowed",
+ "type": "object",
+ "properties": {
+ "issues": {
+ "type": "boolean",
+ "x-go-name": "Issues"
+ },
+ "pull_requests": {
+ "type": "boolean",
+ "x-go-name": "PullRequests"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NodeInfo": {
+ "description": "NodeInfo contains standardized way of exposing metadata about a server running one of the distributed social networks",
+ "type": "object",
+ "properties": {
+ "metadata": {
+ "type": "object",
+ "x-go-name": "Metadata"
+ },
+ "openRegistrations": {
+ "type": "boolean",
+ "x-go-name": "OpenRegistrations"
+ },
+ "protocols": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Protocols"
+ },
+ "services": {
+ "$ref": "#/definitions/NodeInfoServices"
+ },
+ "software": {
+ "$ref": "#/definitions/NodeInfoSoftware"
+ },
+ "usage": {
+ "$ref": "#/definitions/NodeInfoUsage"
+ },
+ "version": {
+ "type": "string",
+ "x-go-name": "Version"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NodeInfoServices": {
+ "description": "NodeInfoServices contains the third party sites this server can connect to via their application API",
+ "type": "object",
+ "properties": {
+ "inbound": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Inbound"
+ },
+ "outbound": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Outbound"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NodeInfoSoftware": {
+ "description": "NodeInfoSoftware contains Metadata about server software in use",
+ "type": "object",
+ "properties": {
+ "homepage": {
+ "type": "string",
+ "x-go-name": "Homepage"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "repository": {
+ "type": "string",
+ "x-go-name": "Repository"
+ },
+ "version": {
+ "type": "string",
+ "x-go-name": "Version"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NodeInfoUsage": {
+ "description": "NodeInfoUsage contains usage statistics for this server",
+ "type": "object",
+ "properties": {
+ "localComments": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "LocalComments"
+ },
+ "localPosts": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "LocalPosts"
+ },
+ "users": {
+ "$ref": "#/definitions/NodeInfoUsageUsers"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NodeInfoUsageUsers": {
+ "description": "NodeInfoUsageUsers contains statistics about the users of this server",
+ "type": "object",
+ "properties": {
+ "activeHalfyear": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ActiveHalfyear"
+ },
+ "activeMonth": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ActiveMonth"
+ },
+ "total": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Total"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Note": {
+ "description": "Note contains information related to a git note",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/Commit"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NotificationCount": {
+ "description": "NotificationCount number of unread notifications",
+ "type": "object",
+ "properties": {
+ "new": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "New"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NotificationSubject": {
+ "description": "NotificationSubject contains the notification subject (Issue/Pull/Commit)",
+ "type": "object",
+ "properties": {
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "latest_comment_html_url": {
+ "type": "string",
+ "x-go-name": "LatestCommentHTMLURL"
+ },
+ "latest_comment_url": {
+ "type": "string",
+ "x-go-name": "LatestCommentURL"
+ },
+ "state": {
+ "$ref": "#/definitions/StateType"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "type": {
+ "$ref": "#/definitions/NotifySubjectType"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NotificationThread": {
+ "description": "NotificationThread expose Notification on API",
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "pinned": {
+ "type": "boolean",
+ "x-go-name": "Pinned"
+ },
+ "repository": {
+ "$ref": "#/definitions/Repository"
+ },
+ "subject": {
+ "$ref": "#/definitions/NotificationSubject"
+ },
+ "unread": {
+ "type": "boolean",
+ "x-go-name": "Unread"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "UpdatedAt"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "NotifySubjectType": {
+ "description": "NotifySubjectType represent type of notification subject",
+ "type": "string",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "OAuth2Application": {
+ "type": "object",
+ "title": "OAuth2Application represents an OAuth2 application.",
+ "properties": {
+ "client_id": {
+ "type": "string",
+ "x-go-name": "ClientID"
+ },
+ "client_secret": {
+ "type": "string",
+ "x-go-name": "ClientSecret"
+ },
+ "confidential_client": {
+ "type": "boolean",
+ "x-go-name": "ConfidentialClient"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "redirect_uris": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "RedirectURIs"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Organization": {
+ "description": "Organization represents an organization",
+ "type": "object",
+ "properties": {
+ "avatar_url": {
+ "type": "string",
+ "x-go-name": "AvatarURL"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "email": {
+ "type": "string",
+ "x-go-name": "Email"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "repo_admin_change_team_access": {
+ "type": "boolean",
+ "x-go-name": "RepoAdminChangeTeamAccess"
+ },
+ "username": {
+ "description": "deprecated",
+ "type": "string",
+ "x-go-name": "UserName"
+ },
+ "visibility": {
+ "type": "string",
+ "x-go-name": "Visibility"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "OrganizationPermissions": {
+ "description": "OrganizationPermissions list different users permissions on an organization",
+ "type": "object",
+ "properties": {
+ "can_create_repository": {
+ "type": "boolean",
+ "x-go-name": "CanCreateRepository"
+ },
+ "can_read": {
+ "type": "boolean",
+ "x-go-name": "CanRead"
+ },
+ "can_write": {
+ "type": "boolean",
+ "x-go-name": "CanWrite"
+ },
+ "is_admin": {
+ "type": "boolean",
+ "x-go-name": "IsAdmin"
+ },
+ "is_owner": {
+ "type": "boolean",
+ "x-go-name": "IsOwner"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PRBranchInfo": {
+ "description": "PRBranchInfo information about a branch",
+ "type": "object",
+ "properties": {
+ "label": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "repo": {
+ "$ref": "#/definitions/Repository"
+ },
+ "repo_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RepoID"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "Sha"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Package": {
+ "description": "Package represents a package",
+ "type": "object",
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "CreatedAt"
+ },
+ "creator": {
+ "$ref": "#/definitions/User"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "owner": {
+ "$ref": "#/definitions/User"
+ },
+ "repository": {
+ "$ref": "#/definitions/Repository"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "version": {
+ "type": "string",
+ "x-go-name": "Version"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PackageFile": {
+ "description": "PackageFile represents a package file",
+ "type": "object",
+ "properties": {
+ "Size": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "md5": {
+ "type": "string",
+ "x-go-name": "HashMD5"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "sha1": {
+ "type": "string",
+ "x-go-name": "HashSHA1"
+ },
+ "sha256": {
+ "type": "string",
+ "x-go-name": "HashSHA256"
+ },
+ "sha512": {
+ "type": "string",
+ "x-go-name": "HashSHA512"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PayloadCommit": {
+ "description": "PayloadCommit represents a commit",
+ "type": "object",
+ "properties": {
+ "added": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Added"
+ },
+ "author": {
+ "$ref": "#/definitions/PayloadUser"
+ },
+ "committer": {
+ "$ref": "#/definitions/PayloadUser"
+ },
+ "id": {
+ "description": "sha1 hash of the commit",
+ "type": "string",
+ "x-go-name": "ID"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "modified": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Modified"
+ },
+ "removed": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Removed"
+ },
+ "timestamp": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Timestamp"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PayloadCommitVerification": {
+ "description": "PayloadCommitVerification represents the GPG verification of a commit",
+ "type": "object",
+ "properties": {
+ "payload": {
+ "type": "string",
+ "x-go-name": "Payload"
+ },
+ "reason": {
+ "type": "string",
+ "x-go-name": "Reason"
+ },
+ "signature": {
+ "type": "string",
+ "x-go-name": "Signature"
+ },
+ "signer": {
+ "$ref": "#/definitions/PayloadUser"
+ },
+ "verified": {
+ "type": "boolean",
+ "x-go-name": "Verified"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PayloadUser": {
+ "description": "PayloadUser represents the author or committer of a commit",
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "name": {
+ "description": "Full name of the commit author",
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "username": {
+ "type": "string",
+ "x-go-name": "UserName"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Permission": {
+ "description": "Permission represents a set of permissions",
+ "type": "object",
+ "properties": {
+ "admin": {
+ "type": "boolean",
+ "x-go-name": "Admin"
+ },
+ "pull": {
+ "type": "boolean",
+ "x-go-name": "Pull"
+ },
+ "push": {
+ "type": "boolean",
+ "x-go-name": "Push"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PublicKey": {
+ "description": "PublicKey publickey is a user key to push code to repository",
+ "type": "object",
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "fingerprint": {
+ "type": "string",
+ "x-go-name": "Fingerprint"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "key": {
+ "type": "string",
+ "x-go-name": "Key"
+ },
+ "key_type": {
+ "type": "string",
+ "x-go-name": "KeyType"
+ },
+ "read_only": {
+ "type": "boolean",
+ "x-go-name": "ReadOnly"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PullRequest": {
+ "description": "PullRequest represents a pull request",
+ "type": "object",
+ "properties": {
+ "allow_maintainer_edit": {
+ "type": "boolean",
+ "x-go-name": "AllowMaintainerEdit"
+ },
+ "assignee": {
+ "$ref": "#/definitions/User"
+ },
+ "assignees": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/User"
+ },
+ "x-go-name": "Assignees"
+ },
+ "base": {
+ "$ref": "#/definitions/PRBranchInfo"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "closed_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Closed"
+ },
+ "comments": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Comments"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "diff_url": {
+ "type": "string",
+ "x-go-name": "DiffURL"
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Deadline"
+ },
+ "head": {
+ "$ref": "#/definitions/PRBranchInfo"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "is_locked": {
+ "type": "boolean",
+ "x-go-name": "IsLocked"
+ },
+ "labels": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Label"
+ },
+ "x-go-name": "Labels"
+ },
+ "merge_base": {
+ "type": "string",
+ "x-go-name": "MergeBase"
+ },
+ "merge_commit_sha": {
+ "type": "string",
+ "x-go-name": "MergedCommitID"
+ },
+ "mergeable": {
+ "type": "boolean",
+ "x-go-name": "Mergeable"
+ },
+ "merged": {
+ "type": "boolean",
+ "x-go-name": "HasMerged"
+ },
+ "merged_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Merged"
+ },
+ "merged_by": {
+ "$ref": "#/definitions/User"
+ },
+ "milestone": {
+ "$ref": "#/definitions/Milestone"
+ },
+ "number": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Index"
+ },
+ "patch_url": {
+ "type": "string",
+ "x-go-name": "PatchURL"
+ },
+ "pin_order": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "PinOrder"
+ },
+ "requested_reviewers": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/User"
+ },
+ "x-go-name": "RequestedReviewers"
+ },
+ "state": {
+ "$ref": "#/definitions/StateType"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PullRequestMeta": {
+ "description": "PullRequestMeta PR info if an issue is a PR",
+ "type": "object",
+ "properties": {
+ "merged": {
+ "type": "boolean",
+ "x-go-name": "HasMerged"
+ },
+ "merged_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Merged"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PullReview": {
+ "description": "PullReview represents a pull request review",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "comments_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "CodeCommentsCount"
+ },
+ "commit_id": {
+ "type": "string",
+ "x-go-name": "CommitID"
+ },
+ "dismissed": {
+ "type": "boolean",
+ "x-go-name": "Dismissed"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "official": {
+ "type": "boolean",
+ "x-go-name": "Official"
+ },
+ "pull_request_url": {
+ "type": "string",
+ "x-go-name": "HTMLPullURL"
+ },
+ "stale": {
+ "type": "boolean",
+ "x-go-name": "Stale"
+ },
+ "state": {
+ "$ref": "#/definitions/ReviewStateType"
+ },
+ "submitted_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Submitted"
+ },
+ "team": {
+ "$ref": "#/definitions/Team"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PullReviewComment": {
+ "description": "PullReviewComment represents a comment on a pull request review",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "commit_id": {
+ "type": "string",
+ "x-go-name": "CommitID"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "diff_hunk": {
+ "type": "string",
+ "x-go-name": "DiffHunk"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "original_commit_id": {
+ "type": "string",
+ "x-go-name": "OrigCommitID"
+ },
+ "original_position": {
+ "type": "integer",
+ "format": "uint64",
+ "x-go-name": "OldLineNum"
+ },
+ "path": {
+ "type": "string",
+ "x-go-name": "Path"
+ },
+ "position": {
+ "type": "integer",
+ "format": "uint64",
+ "x-go-name": "LineNum"
+ },
+ "pull_request_review_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ReviewID"
+ },
+ "pull_request_url": {
+ "type": "string",
+ "x-go-name": "HTMLPullURL"
+ },
+ "resolver": {
+ "$ref": "#/definitions/User"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PullReviewRequestOptions": {
+ "description": "PullReviewRequestOptions are options to add or remove pull review requests",
+ "type": "object",
+ "properties": {
+ "reviewers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Reviewers"
+ },
+ "team_reviewers": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "TeamReviewers"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "PushMirror": {
+ "description": "PushMirror represents information of a push mirror",
+ "type": "object",
+ "properties": {
+ "created": {
+ "type": "string",
+ "x-go-name": "CreatedUnix"
+ },
+ "interval": {
+ "type": "string",
+ "x-go-name": "Interval"
+ },
+ "last_error": {
+ "type": "string",
+ "x-go-name": "LastError"
+ },
+ "last_update": {
+ "type": "string",
+ "x-go-name": "LastUpdateUnix"
+ },
+ "remote_address": {
+ "type": "string",
+ "x-go-name": "RemoteAddress"
+ },
+ "remote_name": {
+ "type": "string",
+ "x-go-name": "RemoteName"
+ },
+ "repo_name": {
+ "type": "string",
+ "x-go-name": "RepoName"
+ },
+ "sync_on_commit": {
+ "type": "boolean",
+ "x-go-name": "SyncOnCommit"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Reaction": {
+ "description": "Reaction contain one reaction",
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string",
+ "x-go-name": "Reaction"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Reference": {
+ "type": "object",
+ "title": "Reference represents a Git reference.",
+ "properties": {
+ "object": {
+ "$ref": "#/definitions/GitObject"
+ },
+ "ref": {
+ "type": "string",
+ "x-go-name": "Ref"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Release": {
+ "description": "Release represents a repository release",
+ "type": "object",
+ "properties": {
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Attachment"
+ },
+ "x-go-name": "Attachments"
+ },
+ "author": {
+ "$ref": "#/definitions/User"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Note"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "CreatedAt"
+ },
+ "draft": {
+ "type": "boolean",
+ "x-go-name": "IsDraft"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Title"
+ },
+ "prerelease": {
+ "type": "boolean",
+ "x-go-name": "IsPrerelease"
+ },
+ "published_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "PublishedAt"
+ },
+ "tag_name": {
+ "type": "string",
+ "x-go-name": "TagName"
+ },
+ "tarball_url": {
+ "type": "string",
+ "x-go-name": "TarURL"
+ },
+ "target_commitish": {
+ "type": "string",
+ "x-go-name": "Target"
+ },
+ "upload_url": {
+ "type": "string",
+ "x-go-name": "UploadURL"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "zipball_url": {
+ "type": "string",
+ "x-go-name": "ZipURL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RenameUserOption": {
+ "description": "RenameUserOption options when renaming a user",
+ "type": "object",
+ "required": [
+ "new_username"
+ ],
+ "properties": {
+ "new_username": {
+ "description": "New username for this user. This name cannot be in use yet by any other user.",
+ "type": "string",
+ "uniqueItems": true,
+ "x-go-name": "NewName"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RepoCollaboratorPermission": {
+ "description": "RepoCollaboratorPermission to get repository permission for a collaborator",
+ "type": "object",
+ "properties": {
+ "permission": {
+ "type": "string",
+ "x-go-name": "Permission"
+ },
+ "role_name": {
+ "type": "string",
+ "x-go-name": "RoleName"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RepoCommit": {
+ "type": "object",
+ "title": "RepoCommit contains information of a commit in the context of a repository.",
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "committer": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "tree": {
+ "$ref": "#/definitions/CommitMeta"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "verification": {
+ "$ref": "#/definitions/PayloadCommitVerification"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RepoTopicOptions": {
+ "description": "RepoTopicOptions a collection of repo topic names",
+ "type": "object",
+ "properties": {
+ "topics": {
+ "description": "list of topic names",
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Topics"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RepoTransfer": {
+ "description": "RepoTransfer represents a pending repo transfer",
+ "type": "object",
+ "properties": {
+ "doer": {
+ "$ref": "#/definitions/User"
+ },
+ "recipient": {
+ "$ref": "#/definitions/User"
+ },
+ "teams": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Team"
+ },
+ "x-go-name": "Teams"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Repository": {
+ "description": "Repository represents a repository",
+ "type": "object",
+ "properties": {
+ "allow_merge_commits": {
+ "type": "boolean",
+ "x-go-name": "AllowMerge"
+ },
+ "allow_rebase": {
+ "type": "boolean",
+ "x-go-name": "AllowRebase"
+ },
+ "allow_rebase_explicit": {
+ "type": "boolean",
+ "x-go-name": "AllowRebaseMerge"
+ },
+ "allow_rebase_update": {
+ "type": "boolean",
+ "x-go-name": "AllowRebaseUpdate"
+ },
+ "allow_squash_merge": {
+ "type": "boolean",
+ "x-go-name": "AllowSquash"
+ },
+ "archived": {
+ "type": "boolean",
+ "x-go-name": "Archived"
+ },
+ "archived_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "ArchivedAt"
+ },
+ "avatar_url": {
+ "type": "string",
+ "x-go-name": "AvatarURL"
+ },
+ "clone_url": {
+ "type": "string",
+ "x-go-name": "CloneURL"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "default_allow_maintainer_edit": {
+ "type": "boolean",
+ "x-go-name": "DefaultAllowMaintainerEdit"
+ },
+ "default_branch": {
+ "type": "string",
+ "x-go-name": "DefaultBranch"
+ },
+ "default_delete_branch_after_merge": {
+ "type": "boolean",
+ "x-go-name": "DefaultDeleteBranchAfterMerge"
+ },
+ "default_merge_style": {
+ "type": "string",
+ "x-go-name": "DefaultMergeStyle"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "empty": {
+ "type": "boolean",
+ "x-go-name": "Empty"
+ },
+ "external_tracker": {
+ "$ref": "#/definitions/ExternalTracker"
+ },
+ "external_wiki": {
+ "$ref": "#/definitions/ExternalWiki"
+ },
+ "fork": {
+ "type": "boolean",
+ "x-go-name": "Fork"
+ },
+ "forks_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Forks"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "has_actions": {
+ "type": "boolean",
+ "x-go-name": "HasActions"
+ },
+ "has_issues": {
+ "type": "boolean",
+ "x-go-name": "HasIssues"
+ },
+ "has_packages": {
+ "type": "boolean",
+ "x-go-name": "HasPackages"
+ },
+ "has_projects": {
+ "type": "boolean",
+ "x-go-name": "HasProjects"
+ },
+ "has_pull_requests": {
+ "type": "boolean",
+ "x-go-name": "HasPullRequests"
+ },
+ "has_releases": {
+ "type": "boolean",
+ "x-go-name": "HasReleases"
+ },
+ "has_wiki": {
+ "type": "boolean",
+ "x-go-name": "HasWiki"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "ignore_whitespace_conflicts": {
+ "type": "boolean",
+ "x-go-name": "IgnoreWhitespaceConflicts"
+ },
+ "internal": {
+ "type": "boolean",
+ "x-go-name": "Internal"
+ },
+ "internal_tracker": {
+ "$ref": "#/definitions/InternalTracker"
+ },
+ "language": {
+ "type": "string",
+ "x-go-name": "Language"
+ },
+ "languages_url": {
+ "type": "string",
+ "x-go-name": "LanguagesURL"
+ },
+ "link": {
+ "type": "string",
+ "x-go-name": "Link"
+ },
+ "mirror": {
+ "type": "boolean",
+ "x-go-name": "Mirror"
+ },
+ "mirror_interval": {
+ "type": "string",
+ "x-go-name": "MirrorInterval"
+ },
+ "mirror_updated": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "MirrorUpdated"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "open_issues_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OpenIssues"
+ },
+ "open_pr_counter": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OpenPulls"
+ },
+ "original_url": {
+ "type": "string",
+ "x-go-name": "OriginalURL"
+ },
+ "owner": {
+ "$ref": "#/definitions/User"
+ },
+ "parent": {
+ "$ref": "#/definitions/Repository"
+ },
+ "permissions": {
+ "$ref": "#/definitions/Permission"
+ },
+ "private": {
+ "type": "boolean",
+ "x-go-name": "Private"
+ },
+ "release_counter": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Releases"
+ },
+ "repo_transfer": {
+ "$ref": "#/definitions/RepoTransfer"
+ },
+ "size": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Size"
+ },
+ "ssh_url": {
+ "type": "string",
+ "x-go-name": "SSHURL"
+ },
+ "stars_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Stars"
+ },
+ "template": {
+ "type": "boolean",
+ "x-go-name": "Template"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ },
+ "watchers_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Watchers"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "RepositoryMeta": {
+ "description": "RepositoryMeta basic repository information",
+ "type": "object",
+ "properties": {
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "owner": {
+ "type": "string",
+ "x-go-name": "Owner"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ReviewStateType": {
+ "description": "ReviewStateType review state type",
+ "type": "string",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "SearchResults": {
+ "description": "SearchResults results of a successful search",
+ "type": "object",
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Repository"
+ },
+ "x-go-name": "Data"
+ },
+ "ok": {
+ "type": "boolean",
+ "x-go-name": "OK"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Secret": {
+ "description": "Secret represents a secret",
+ "type": "object",
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "name": {
+ "description": "the secret's name",
+ "type": "string",
+ "x-go-name": "Name"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "ServerVersion": {
+ "description": "ServerVersion wraps the version of the server",
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "string",
+ "x-go-name": "Version"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "StateType": {
+ "description": "StateType issue state type",
+ "type": "string",
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "StopWatch": {
+ "description": "StopWatch represent a running stopwatch",
+ "type": "object",
+ "properties": {
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "duration": {
+ "type": "string",
+ "x-go-name": "Duration"
+ },
+ "issue_index": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "IssueIndex"
+ },
+ "issue_title": {
+ "type": "string",
+ "x-go-name": "IssueTitle"
+ },
+ "repo_name": {
+ "type": "string",
+ "x-go-name": "RepoName"
+ },
+ "repo_owner_name": {
+ "type": "string",
+ "x-go-name": "RepoOwnerName"
+ },
+ "seconds": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Seconds"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "SubmitPullReviewOptions": {
+ "description": "SubmitPullReviewOptions are options to submit a pending pull review",
+ "type": "object",
+ "properties": {
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "event": {
+ "$ref": "#/definitions/ReviewStateType"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Tag": {
+ "description": "Tag represents a repository tag",
+ "type": "object",
+ "properties": {
+ "commit": {
+ "$ref": "#/definitions/CommitMeta"
+ },
+ "id": {
+ "type": "string",
+ "x-go-name": "ID"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "tarball_url": {
+ "type": "string",
+ "x-go-name": "TarballURL"
+ },
+ "zipball_url": {
+ "type": "string",
+ "x-go-name": "ZipballURL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "Team": {
+ "description": "Team represents a team in an organization",
+ "type": "object",
+ "properties": {
+ "can_create_org_repo": {
+ "type": "boolean",
+ "x-go-name": "CanCreateOrgRepo"
+ },
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "includes_all_repositories": {
+ "type": "boolean",
+ "x-go-name": "IncludesAllRepositories"
+ },
+ "name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "organization": {
+ "$ref": "#/definitions/Organization"
+ },
+ "permission": {
+ "type": "string",
+ "enum": [
+ "none",
+ "read",
+ "write",
+ "admin",
+ "owner"
+ ],
+ "x-go-name": "Permission"
+ },
+ "units": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "Units",
+ "example": [
+ "repo.code",
+ "repo.issues",
+ "repo.ext_issues",
+ "repo.wiki",
+ "repo.pulls",
+ "repo.releases",
+ "repo.projects",
+ "repo.ext_wiki"
+ ]
+ },
+ "units_map": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "x-go-name": "UnitsMap",
+ "example": {
+ "repo.code": "read",
+ "repo.ext_issues": "none",
+ "repo.ext_wiki": "none",
+ "repo.issues": "write",
+ "repo.projects": "none",
+ "repo.pulls": "owner",
+ "repo.releases": "none",
+ "repo.wiki": "admin"
+ }
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "TimeStamp": {
+ "description": "TimeStamp defines a timestamp",
+ "type": "integer",
+ "format": "int64",
+ "x-go-package": "code.gitea.io/gitea/modules/timeutil"
+ },
+ "TimelineComment": {
+ "description": "TimelineComment represents a timeline comment (comment of any type) on a commit or issue",
+ "type": "object",
+ "properties": {
+ "assignee": {
+ "$ref": "#/definitions/User"
+ },
+ "assignee_team": {
+ "$ref": "#/definitions/Team"
+ },
+ "body": {
+ "type": "string",
+ "x-go-name": "Body"
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "dependent_issue": {
+ "$ref": "#/definitions/Issue"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "issue_url": {
+ "type": "string",
+ "x-go-name": "IssueURL"
+ },
+ "label": {
+ "$ref": "#/definitions/Label"
+ },
+ "milestone": {
+ "$ref": "#/definitions/Milestone"
+ },
+ "new_ref": {
+ "type": "string",
+ "x-go-name": "NewRef"
+ },
+ "new_title": {
+ "type": "string",
+ "x-go-name": "NewTitle"
+ },
+ "old_milestone": {
+ "$ref": "#/definitions/Milestone"
+ },
+ "old_project_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "OldProjectID"
+ },
+ "old_ref": {
+ "type": "string",
+ "x-go-name": "OldRef"
+ },
+ "old_title": {
+ "type": "string",
+ "x-go-name": "OldTitle"
+ },
+ "project_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ProjectID"
+ },
+ "pull_request_url": {
+ "type": "string",
+ "x-go-name": "PRURL"
+ },
+ "ref_action": {
+ "type": "string",
+ "x-go-name": "RefAction"
+ },
+ "ref_comment": {
+ "$ref": "#/definitions/Comment"
+ },
+ "ref_commit_sha": {
+ "description": "commit SHA where issue/PR was referenced",
+ "type": "string",
+ "x-go-name": "RefCommitSHA"
+ },
+ "ref_issue": {
+ "$ref": "#/definitions/Issue"
+ },
+ "removed_assignee": {
+ "description": "whether the assignees were removed or added",
+ "type": "boolean",
+ "x-go-name": "RemovedAssignee"
+ },
+ "resolve_doer": {
+ "$ref": "#/definitions/User"
+ },
+ "review_id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ReviewID"
+ },
+ "tracked_time": {
+ "$ref": "#/definitions/TrackedTime"
+ },
+ "type": {
+ "type": "string",
+ "x-go-name": "Type"
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ },
+ "user": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "TopicName": {
+ "description": "TopicName a list of repo topic names",
+ "type": "object",
+ "properties": {
+ "topics": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "x-go-name": "TopicNames"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "TopicResponse": {
+ "description": "TopicResponse for returning topics",
+ "type": "object",
+ "properties": {
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "repo_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "RepoCount"
+ },
+ "topic_name": {
+ "type": "string",
+ "x-go-name": "Name"
+ },
+ "updated": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Updated"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "TrackedTime": {
+ "description": "TrackedTime worked time for an issue / pr",
+ "type": "object",
+ "properties": {
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "issue": {
+ "$ref": "#/definitions/Issue"
+ },
+ "issue_id": {
+ "description": "deprecated (only for backwards compatibility)",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "IssueID"
+ },
+ "time": {
+ "description": "Time in seconds",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Time"
+ },
+ "user_id": {
+ "description": "deprecated (only for backwards compatibility)",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "UserID"
+ },
+ "user_name": {
+ "type": "string",
+ "x-go-name": "UserName"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "TransferRepoOption": {
+ "description": "TransferRepoOption options when transfer a repository's ownership",
+ "type": "object",
+ "required": [
+ "new_owner"
+ ],
+ "properties": {
+ "new_owner": {
+ "type": "string",
+ "x-go-name": "NewOwner"
+ },
+ "team_ids": {
+ "description": "ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.",
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "x-go-name": "TeamIDs"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "UpdateFileOptions": {
+ "description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
+ "type": "object",
+ "required": [
+ "sha",
+ "content"
+ ],
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/Identity"
+ },
+ "branch": {
+ "description": "branch (optional) to base this file from. if not given, the default branch is used",
+ "type": "string",
+ "x-go-name": "BranchName"
+ },
+ "committer": {
+ "$ref": "#/definitions/Identity"
+ },
+ "content": {
+ "description": "content must be base64 encoded",
+ "type": "string",
+ "x-go-name": "ContentBase64"
+ },
+ "dates": {
+ "$ref": "#/definitions/CommitDateOptions"
+ },
+ "from_path": {
+ "description": "from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL",
+ "type": "string",
+ "x-go-name": "FromPath"
+ },
+ "message": {
+ "description": "message (optional) for the commit of this file. if not supplied, a default message will be used",
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "new_branch": {
+ "description": "new_branch (optional) will make a new branch from `branch` before creating the file",
+ "type": "string",
+ "x-go-name": "NewBranchName"
+ },
+ "sha": {
+ "description": "sha is the SHA for the file that already exists",
+ "type": "string",
+ "x-go-name": "SHA"
+ },
+ "signoff": {
+ "description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
+ "type": "boolean",
+ "x-go-name": "Signoff"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "UpdateRepoAvatarOption": {
+ "description": "UpdateRepoAvatarUserOption options when updating the repo avatar",
+ "type": "object",
+ "properties": {
+ "image": {
+ "description": "image must be base64 encoded",
+ "type": "string",
+ "x-go-name": "Image"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "UpdateUserAvatarOption": {
+ "description": "UpdateUserAvatarUserOption options when updating the user avatar",
+ "type": "object",
+ "properties": {
+ "image": {
+ "description": "image must be base64 encoded",
+ "type": "string",
+ "x-go-name": "Image"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "User": {
+ "description": "User represents a user",
+ "type": "object",
+ "properties": {
+ "active": {
+ "description": "Is user active",
+ "type": "boolean",
+ "x-go-name": "IsActive"
+ },
+ "avatar_url": {
+ "description": "URL to the user's avatar",
+ "type": "string",
+ "x-go-name": "AvatarURL"
+ },
+ "created": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "Created"
+ },
+ "description": {
+ "description": "the user's description",
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "email": {
+ "type": "string",
+ "format": "email",
+ "x-go-name": "Email"
+ },
+ "followers_count": {
+ "description": "user counts",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Followers"
+ },
+ "following_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Following"
+ },
+ "full_name": {
+ "description": "the user's full name",
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "id": {
+ "description": "the user's id",
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "ID"
+ },
+ "is_admin": {
+ "description": "Is the user an administrator",
+ "type": "boolean",
+ "x-go-name": "IsAdmin"
+ },
+ "language": {
+ "description": "User locale",
+ "type": "string",
+ "x-go-name": "Language"
+ },
+ "last_login": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "LastLogin"
+ },
+ "location": {
+ "description": "the user's location",
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "login": {
+ "description": "the user's username",
+ "type": "string",
+ "x-go-name": "UserName"
+ },
+ "login_name": {
+ "description": "the user's authentication sign-in name.",
+ "type": "string",
+ "default": "empty",
+ "x-go-name": "LoginName"
+ },
+ "prohibit_login": {
+ "description": "Is user login prohibited",
+ "type": "boolean",
+ "x-go-name": "ProhibitLogin"
+ },
+ "restricted": {
+ "description": "Is user restricted",
+ "type": "boolean",
+ "x-go-name": "Restricted"
+ },
+ "starred_repos_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "StarredRepos"
+ },
+ "visibility": {
+ "description": "User visibility level option: public, limited, private",
+ "type": "string",
+ "x-go-name": "Visibility"
+ },
+ "website": {
+ "description": "the user's website",
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "UserHeatmapData": {
+ "description": "UserHeatmapData represents the data needed to create a heatmap",
+ "type": "object",
+ "properties": {
+ "contributions": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Contributions"
+ },
+ "timestamp": {
+ "$ref": "#/definitions/TimeStamp"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/models/activities"
+ },
+ "UserSettings": {
+ "description": "UserSettings represents user settings",
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "diff_view_style": {
+ "type": "string",
+ "x-go-name": "DiffViewStyle"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "hide_activity": {
+ "type": "boolean",
+ "x-go-name": "HideActivity"
+ },
+ "hide_email": {
+ "description": "Privacy",
+ "type": "boolean",
+ "x-go-name": "HideEmail"
+ },
+ "language": {
+ "type": "string",
+ "x-go-name": "Language"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "theme": {
+ "type": "string",
+ "x-go-name": "Theme"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "UserSettingsOptions": {
+ "description": "UserSettingsOptions represents options to change user settings",
+ "type": "object",
+ "properties": {
+ "description": {
+ "type": "string",
+ "x-go-name": "Description"
+ },
+ "diff_view_style": {
+ "type": "string",
+ "x-go-name": "DiffViewStyle"
+ },
+ "full_name": {
+ "type": "string",
+ "x-go-name": "FullName"
+ },
+ "hide_activity": {
+ "type": "boolean",
+ "x-go-name": "HideActivity"
+ },
+ "hide_email": {
+ "description": "Privacy",
+ "type": "boolean",
+ "x-go-name": "HideEmail"
+ },
+ "language": {
+ "type": "string",
+ "x-go-name": "Language"
+ },
+ "location": {
+ "type": "string",
+ "x-go-name": "Location"
+ },
+ "theme": {
+ "type": "string",
+ "x-go-name": "Theme"
+ },
+ "website": {
+ "type": "string",
+ "x-go-name": "Website"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "WatchInfo": {
+ "description": "WatchInfo represents an API watch status of one repository",
+ "type": "object",
+ "properties": {
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "x-go-name": "CreatedAt"
+ },
+ "ignored": {
+ "type": "boolean",
+ "x-go-name": "Ignored"
+ },
+ "reason": {
+ "x-go-name": "Reason"
+ },
+ "repository_url": {
+ "type": "string",
+ "x-go-name": "RepositoryURL"
+ },
+ "subscribed": {
+ "type": "boolean",
+ "x-go-name": "Subscribed"
+ },
+ "url": {
+ "type": "string",
+ "x-go-name": "URL"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "WikiCommit": {
+ "description": "WikiCommit page commit/revision",
+ "type": "object",
+ "properties": {
+ "author": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "commiter": {
+ "$ref": "#/definitions/CommitUser"
+ },
+ "message": {
+ "type": "string",
+ "x-go-name": "Message"
+ },
+ "sha": {
+ "type": "string",
+ "x-go-name": "ID"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "WikiCommitList": {
+ "description": "WikiCommitList commit/revision list",
+ "type": "object",
+ "properties": {
+ "commits": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/WikiCommit"
+ },
+ "x-go-name": "WikiCommits"
+ },
+ "count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "Count"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "WikiPage": {
+ "description": "WikiPage a wiki page",
+ "type": "object",
+ "properties": {
+ "commit_count": {
+ "type": "integer",
+ "format": "int64",
+ "x-go-name": "CommitCount"
+ },
+ "content_base64": {
+ "description": "Page content, base64 encoded",
+ "type": "string",
+ "x-go-name": "ContentBase64"
+ },
+ "footer": {
+ "type": "string",
+ "x-go-name": "Footer"
+ },
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "last_commit": {
+ "$ref": "#/definitions/WikiCommit"
+ },
+ "sidebar": {
+ "type": "string",
+ "x-go-name": "Sidebar"
+ },
+ "sub_url": {
+ "type": "string",
+ "x-go-name": "SubURL"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ },
+ "WikiPageMetaData": {
+ "description": "WikiPageMetaData wiki page meta information",
+ "type": "object",
+ "properties": {
+ "html_url": {
+ "type": "string",
+ "x-go-name": "HTMLURL"
+ },
+ "last_commit": {
+ "$ref": "#/definitions/WikiCommit"
+ },
+ "sub_url": {
+ "type": "string",
+ "x-go-name": "SubURL"
+ },
+ "title": {
+ "type": "string",
+ "x-go-name": "Title"
+ }
+ },
+ "x-go-package": "code.gitea.io/gitea/modules/structs"
+ }
+ },
+ "responses": {
+ "AccessToken": {
+ "description": "AccessToken represents an API access token.",
+ "schema": {
+ "$ref": "#/definitions/AccessToken"
+ }
+ },
+ "AccessTokenList": {
+ "description": "AccessTokenList represents a list of API access token.",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/AccessToken"
+ }
+ }
+ },
+ "ActivityFeedsList": {
+ "description": "ActivityFeedsList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Activity"
+ }
+ }
+ },
+ "ActivityPub": {
+ "description": "ActivityPub",
+ "schema": {
+ "$ref": "#/definitions/ActivityPub"
+ }
+ },
+ "AnnotatedTag": {
+ "description": "AnnotatedTag",
+ "schema": {
+ "$ref": "#/definitions/AnnotatedTag"
+ }
+ },
+ "Attachment": {
+ "description": "Attachment",
+ "schema": {
+ "$ref": "#/definitions/Attachment"
+ }
+ },
+ "AttachmentList": {
+ "description": "AttachmentList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Attachment"
+ }
+ }
+ },
+ "BlockedUserList": {
+ "description": "BlockedUserList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/BlockedUser"
+ }
+ }
+ },
+ "Branch": {
+ "description": "Branch",
+ "schema": {
+ "$ref": "#/definitions/Branch"
+ }
+ },
+ "BranchList": {
+ "description": "BranchList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Branch"
+ }
+ }
+ },
+ "BranchProtection": {
+ "description": "BranchProtection",
+ "schema": {
+ "$ref": "#/definitions/BranchProtection"
+ }
+ },
+ "BranchProtectionList": {
+ "description": "BranchProtectionList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/BranchProtection"
+ }
+ }
+ },
+ "ChangedFileList": {
+ "description": "ChangedFileList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ChangedFile"
+ }
+ },
+ "headers": {
+ "X-HasMore": {
+ "type": "boolean",
+ "description": "True if there is another page"
+ },
+ "X-Page": {
+ "type": "integer",
+ "format": "int64",
+ "description": "The current page"
+ },
+ "X-PageCount": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Total number of pages"
+ },
+ "X-PerPage": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Commits per page"
+ },
+ "X-Total": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Total commit count"
+ }
+ }
+ },
+ "CombinedStatus": {
+ "description": "CombinedStatus",
+ "schema": {
+ "$ref": "#/definitions/CombinedStatus"
+ }
+ },
+ "Comment": {
+ "description": "Comment",
+ "schema": {
+ "$ref": "#/definitions/Comment"
+ }
+ },
+ "CommentList": {
+ "description": "CommentList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Comment"
+ }
+ }
+ },
+ "Commit": {
+ "description": "Commit",
+ "schema": {
+ "$ref": "#/definitions/Commit"
+ }
+ },
+ "CommitList": {
+ "description": "CommitList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Commit"
+ }
+ },
+ "headers": {
+ "X-HasMore": {
+ "type": "boolean",
+ "description": "True if there is another page"
+ },
+ "X-Page": {
+ "type": "integer",
+ "format": "int64",
+ "description": "The current page"
+ },
+ "X-PageCount": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Total number of pages"
+ },
+ "X-PerPage": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Commits per page"
+ },
+ "X-Total": {
+ "type": "integer",
+ "format": "int64",
+ "description": "Total commit count"
+ }
+ }
+ },
+ "CommitStatus": {
+ "description": "CommitStatus",
+ "schema": {
+ "$ref": "#/definitions/CommitStatus"
+ }
+ },
+ "CommitStatusList": {
+ "description": "CommitStatusList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/CommitStatus"
+ }
+ }
+ },
+ "ContentsListResponse": {
+ "description": "ContentsListResponse",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/ContentsResponse"
+ }
+ }
+ },
+ "ContentsResponse": {
+ "description": "ContentsResponse",
+ "schema": {
+ "$ref": "#/definitions/ContentsResponse"
+ }
+ },
+ "CronList": {
+ "description": "CronList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Cron"
+ }
+ }
+ },
+ "DeployKey": {
+ "description": "DeployKey",
+ "schema": {
+ "$ref": "#/definitions/DeployKey"
+ }
+ },
+ "DeployKeyList": {
+ "description": "DeployKeyList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/DeployKey"
+ }
+ }
+ },
+ "EmailList": {
+ "description": "EmailList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Email"
+ }
+ }
+ },
+ "EmptyRepository": {
+ "description": "EmptyRepository",
+ "schema": {
+ "$ref": "#/definitions/APIError"
+ }
+ },
+ "FileDeleteResponse": {
+ "description": "FileDeleteResponse",
+ "schema": {
+ "$ref": "#/definitions/FileDeleteResponse"
+ }
+ },
+ "FileResponse": {
+ "description": "FileResponse",
+ "schema": {
+ "$ref": "#/definitions/FileResponse"
+ }
+ },
+ "FilesResponse": {
+ "description": "FilesResponse",
+ "schema": {
+ "$ref": "#/definitions/FilesResponse"
+ }
+ },
+ "GPGKey": {
+ "description": "GPGKey",
+ "schema": {
+ "$ref": "#/definitions/GPGKey"
+ }
+ },
+ "GPGKeyList": {
+ "description": "GPGKeyList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GPGKey"
+ }
+ }
+ },
+ "GeneralAPISettings": {
+ "description": "GeneralAPISettings",
+ "schema": {
+ "$ref": "#/definitions/GeneralAPISettings"
+ }
+ },
+ "GeneralAttachmentSettings": {
+ "description": "GeneralAttachmentSettings",
+ "schema": {
+ "$ref": "#/definitions/GeneralAttachmentSettings"
+ }
+ },
+ "GeneralRepoSettings": {
+ "description": "GeneralRepoSettings",
+ "schema": {
+ "$ref": "#/definitions/GeneralRepoSettings"
+ }
+ },
+ "GeneralUISettings": {
+ "description": "GeneralUISettings",
+ "schema": {
+ "$ref": "#/definitions/GeneralUISettings"
+ }
+ },
+ "GitBlobResponse": {
+ "description": "GitBlobResponse",
+ "schema": {
+ "$ref": "#/definitions/GitBlobResponse"
+ }
+ },
+ "GitHook": {
+ "description": "GitHook",
+ "schema": {
+ "$ref": "#/definitions/GitHook"
+ }
+ },
+ "GitHookList": {
+ "description": "GitHookList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/GitHook"
+ }
+ }
+ },
+ "GitTreeResponse": {
+ "description": "GitTreeResponse",
+ "schema": {
+ "$ref": "#/definitions/GitTreeResponse"
+ }
+ },
+ "GitignoreTemplateInfo": {
+ "description": "GitignoreTemplateInfo",
+ "schema": {
+ "$ref": "#/definitions/GitignoreTemplateInfo"
+ }
+ },
+ "GitignoreTemplateList": {
+ "description": "GitignoreTemplateList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "Hook": {
+ "description": "Hook",
+ "schema": {
+ "$ref": "#/definitions/Hook"
+ }
+ },
+ "HookList": {
+ "description": "HookList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Hook"
+ }
+ }
+ },
+ "Issue": {
+ "description": "Issue",
+ "schema": {
+ "$ref": "#/definitions/Issue"
+ }
+ },
+ "IssueDeadline": {
+ "description": "IssueDeadline",
+ "schema": {
+ "$ref": "#/definitions/IssueDeadline"
+ }
+ },
+ "IssueList": {
+ "description": "IssueList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Issue"
+ }
+ }
+ },
+ "IssueTemplates": {
+ "description": "IssueTemplates",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/IssueTemplate"
+ }
+ }
+ },
+ "Label": {
+ "description": "Label",
+ "schema": {
+ "$ref": "#/definitions/Label"
+ }
+ },
+ "LabelList": {
+ "description": "LabelList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Label"
+ }
+ }
+ },
+ "LabelTemplateInfo": {
+ "description": "LabelTemplateInfo",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/LabelTemplate"
+ }
+ }
+ },
+ "LabelTemplateList": {
+ "description": "LabelTemplateList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "LanguageStatistics": {
+ "description": "LanguageStatistics",
+ "schema": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ },
+ "LicenseTemplateInfo": {
+ "description": "LicenseTemplateInfo",
+ "schema": {
+ "$ref": "#/definitions/LicenseTemplateInfo"
+ }
+ },
+ "LicenseTemplateList": {
+ "description": "LicenseTemplateList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/LicensesTemplateListEntry"
+ }
+ }
+ },
+ "MarkdownRender": {
+ "description": "MarkdownRender is a rendered markdown document",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "MarkupRender": {
+ "description": "MarkupRender is a rendered markup document",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "Milestone": {
+ "description": "Milestone",
+ "schema": {
+ "$ref": "#/definitions/Milestone"
+ }
+ },
+ "MilestoneList": {
+ "description": "MilestoneList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Milestone"
+ }
+ }
+ },
+ "NodeInfo": {
+ "description": "NodeInfo",
+ "schema": {
+ "$ref": "#/definitions/NodeInfo"
+ }
+ },
+ "Note": {
+ "description": "Note",
+ "schema": {
+ "$ref": "#/definitions/Note"
+ }
+ },
+ "NotificationCount": {
+ "description": "Number of unread notifications",
+ "schema": {
+ "$ref": "#/definitions/NotificationCount"
+ }
+ },
+ "NotificationThread": {
+ "description": "NotificationThread",
+ "schema": {
+ "$ref": "#/definitions/NotificationThread"
+ }
+ },
+ "NotificationThreadList": {
+ "description": "NotificationThreadList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/NotificationThread"
+ }
+ }
+ },
+ "OAuth2Application": {
+ "description": "OAuth2Application",
+ "schema": {
+ "$ref": "#/definitions/OAuth2Application"
+ }
+ },
+ "OAuth2ApplicationList": {
+ "description": "OAuth2ApplicationList represents a list of OAuth2 applications.",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/OAuth2Application"
+ }
+ }
+ },
+ "Organization": {
+ "description": "Organization",
+ "schema": {
+ "$ref": "#/definitions/Organization"
+ }
+ },
+ "OrganizationList": {
+ "description": "OrganizationList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Organization"
+ }
+ }
+ },
+ "OrganizationPermissions": {
+ "description": "OrganizationPermissions",
+ "schema": {
+ "$ref": "#/definitions/OrganizationPermissions"
+ }
+ },
+ "Package": {
+ "description": "Package",
+ "schema": {
+ "$ref": "#/definitions/Package"
+ }
+ },
+ "PackageFileList": {
+ "description": "PackageFileList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PackageFile"
+ }
+ }
+ },
+ "PackageList": {
+ "description": "PackageList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Package"
+ }
+ }
+ },
+ "PublicKey": {
+ "description": "PublicKey",
+ "schema": {
+ "$ref": "#/definitions/PublicKey"
+ }
+ },
+ "PublicKeyList": {
+ "description": "PublicKeyList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PublicKey"
+ }
+ }
+ },
+ "PullRequest": {
+ "description": "PullRequest",
+ "schema": {
+ "$ref": "#/definitions/PullRequest"
+ }
+ },
+ "PullRequestList": {
+ "description": "PullRequestList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PullRequest"
+ }
+ }
+ },
+ "PullReview": {
+ "description": "PullReview",
+ "schema": {
+ "$ref": "#/definitions/PullReview"
+ }
+ },
+ "PullReviewComment": {
+ "description": "PullComment",
+ "schema": {
+ "$ref": "#/definitions/PullReviewComment"
+ }
+ },
+ "PullReviewCommentList": {
+ "description": "PullCommentList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PullReviewComment"
+ }
+ }
+ },
+ "PullReviewList": {
+ "description": "PullReviewList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PullReview"
+ }
+ }
+ },
+ "PushMirror": {
+ "description": "PushMirror",
+ "schema": {
+ "$ref": "#/definitions/PushMirror"
+ }
+ },
+ "PushMirrorList": {
+ "description": "PushMirrorList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/PushMirror"
+ }
+ }
+ },
+ "Reaction": {
+ "description": "Reaction",
+ "schema": {
+ "$ref": "#/definitions/Reaction"
+ }
+ },
+ "ReactionList": {
+ "description": "ReactionList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Reaction"
+ }
+ }
+ },
+ "Reference": {
+ "description": "Reference",
+ "schema": {
+ "$ref": "#/definitions/Reference"
+ }
+ },
+ "ReferenceList": {
+ "description": "ReferenceList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Reference"
+ }
+ }
+ },
+ "Release": {
+ "description": "Release",
+ "schema": {
+ "$ref": "#/definitions/Release"
+ }
+ },
+ "ReleaseList": {
+ "description": "ReleaseList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Release"
+ }
+ }
+ },
+ "RepoCollaboratorPermission": {
+ "description": "RepoCollaboratorPermission",
+ "schema": {
+ "$ref": "#/definitions/RepoCollaboratorPermission"
+ }
+ },
+ "RepoIssueConfig": {
+ "description": "RepoIssueConfig",
+ "schema": {
+ "$ref": "#/definitions/IssueConfig"
+ }
+ },
+ "RepoIssueConfigValidation": {
+ "description": "RepoIssueConfigValidation",
+ "schema": {
+ "$ref": "#/definitions/IssueConfigValidation"
+ }
+ },
+ "RepoNewIssuePinsAllowed": {
+ "description": "RepoNewIssuePinsAllowed",
+ "schema": {
+ "$ref": "#/definitions/NewIssuePinsAllowed"
+ }
+ },
+ "Repository": {
+ "description": "Repository",
+ "schema": {
+ "$ref": "#/definitions/Repository"
+ }
+ },
+ "RepositoryList": {
+ "description": "RepositoryList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Repository"
+ }
+ }
+ },
+ "SearchResults": {
+ "description": "SearchResults",
+ "schema": {
+ "$ref": "#/definitions/SearchResults"
+ }
+ },
+ "Secret": {
+ "description": "Secret",
+ "schema": {
+ "$ref": "#/definitions/Secret"
+ }
+ },
+ "SecretList": {
+ "description": "SecretList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Secret"
+ }
+ }
+ },
+ "ServerVersion": {
+ "description": "ServerVersion",
+ "schema": {
+ "$ref": "#/definitions/ServerVersion"
+ }
+ },
+ "StopWatch": {
+ "description": "StopWatch",
+ "schema": {
+ "$ref": "#/definitions/StopWatch"
+ }
+ },
+ "StopWatchList": {
+ "description": "StopWatchList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/StopWatch"
+ }
+ }
+ },
+ "StringSlice": {
+ "description": "StringSlice",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "Tag": {
+ "description": "Tag",
+ "schema": {
+ "$ref": "#/definitions/Tag"
+ }
+ },
+ "TagList": {
+ "description": "TagList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Tag"
+ }
+ }
+ },
+ "Team": {
+ "description": "Team",
+ "schema": {
+ "$ref": "#/definitions/Team"
+ }
+ },
+ "TeamList": {
+ "description": "TeamList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Team"
+ }
+ }
+ },
+ "TimelineList": {
+ "description": "TimelineList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/TimelineComment"
+ }
+ }
+ },
+ "TopicListResponse": {
+ "description": "TopicListResponse",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/TopicResponse"
+ }
+ }
+ },
+ "TopicNames": {
+ "description": "TopicNames",
+ "schema": {
+ "$ref": "#/definitions/TopicName"
+ }
+ },
+ "TrackedTime": {
+ "description": "TrackedTime",
+ "schema": {
+ "$ref": "#/definitions/TrackedTime"
+ }
+ },
+ "TrackedTimeList": {
+ "description": "TrackedTimeList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/TrackedTime"
+ }
+ }
+ },
+ "User": {
+ "description": "User",
+ "schema": {
+ "$ref": "#/definitions/User"
+ }
+ },
+ "UserHeatmapData": {
+ "description": "UserHeatmapData",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/UserHeatmapData"
+ }
+ }
+ },
+ "UserList": {
+ "description": "UserList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/User"
+ }
+ }
+ },
+ "UserSettings": {
+ "description": "UserSettings",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/UserSettings"
+ }
+ }
+ },
+ "WatchInfo": {
+ "description": "WatchInfo",
+ "schema": {
+ "$ref": "#/definitions/WatchInfo"
+ }
+ },
+ "WikiCommitList": {
+ "description": "WikiCommitList",
+ "schema": {
+ "$ref": "#/definitions/WikiCommitList"
+ }
+ },
+ "WikiPage": {
+ "description": "WikiPage",
+ "schema": {
+ "$ref": "#/definitions/WikiPage"
+ }
+ },
+ "WikiPageList": {
+ "description": "WikiPageList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/WikiPageMetaData"
+ }
+ }
+ },
+ "conflict": {
+ "description": "APIConflict is a conflict empty response"
+ },
+ "empty": {
+ "description": "APIEmpty is an empty response"
+ },
+ "error": {
+ "description": "APIError is error format response",
+ "headers": {
+ "message": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "forbidden": {
+ "description": "APIForbiddenError is a forbidden error response",
+ "headers": {
+ "message": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "invalidTopicsError": {
+ "description": "APIInvalidTopicsError is error format response to invalid topics",
+ "headers": {
+ "invalidTopics": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "message": {
+ "type": "string"
+ }
+ }
+ },
+ "notFound": {
+ "description": "APINotFound is a not found empty response"
+ },
+ "parameterBodies": {
+ "description": "parameterBodies",
+ "schema": {
+ "$ref": "#/definitions/CreateOrUpdateSecretOption"
+ }
+ },
+ "redirect": {
+ "description": "APIRedirect is a redirect response"
+ },
+ "string": {
+ "description": "APIString is a string response",
+ "schema": {
+ "type": "string"
+ }
+ },
+ "validationError": {
+ "description": "APIValidationError is error format response related to input validation",
+ "headers": {
+ "message": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "securityDefinitions": {
+ "AccessToken": {
+ "type": "apiKey",
+ "name": "access_token",
+ "in": "query"
+ },
+ "AuthorizationHeaderToken": {
+ "description": "API tokens must be prepended with \"token\" followed by a space.",
+ "type": "apiKey",
+ "name": "Authorization",
+ "in": "header"
+ },
+ "BasicAuth": {
+ "type": "basic"
+ },
+ "SudoHeader": {
+ "description": "Sudo API request as the user provided as the key. Admin privileges are required.",
+ "type": "apiKey",
+ "name": "Sudo",
+ "in": "header"
+ },
+ "SudoParam": {
+ "description": "Sudo API request as the user provided as the key. Admin privileges are required.",
+ "type": "apiKey",
+ "name": "sudo",
+ "in": "query"
+ },
+ "TOTPHeader": {
+ "description": "Must be used in combination with BasicAuth if two-factor authentication is enabled.",
+ "type": "apiKey",
+ "name": "X-FORGEJO-OTP",
+ "in": "header"
+ },
+ "Token": {
+ "type": "apiKey",
+ "name": "token",
+ "in": "query"
+ }
+ },
+ "security": [
+ {
+ "BasicAuth": []
+ },
+ {
+ "Token": []
+ },
+ {
+ "AccessToken": []
+ },
+ {
+ "AuthorizationHeaderToken": []
+ },
+ {
+ "SudoParam": []
+ },
+ {
+ "SudoHeader": []
+ },
+ {
+ "TOTPHeader": []
+ }
+ ]
+}
diff --git a/tests/ci_test.rs b/tests/ci_test.rs
index c7e3b90..c4d8a5d 100644
--- a/tests/ci_test.rs
+++ b/tests/ci_test.rs
@@ -1,60 +1,50 @@
-use eyre::{ensure, eyre, WrapErr};
-use forgejo_api::Forgejo;
+use forgejo_api::{structs::*, Forgejo};
-#[tokio::test]
-async fn ci() -> eyre::Result<()> {
- let url = url::Url::parse(&std::env::var("FORGEJO_API_CI_INSTANCE_URL")?)?;
- let token = std::env::var("FORGEJO_API_CI_TOKEN")?;
- let api = Forgejo::new(forgejo_api::Auth::Token(&token), url)?;
-
- let mut results = Vec::new();
-
- results.push(user(&api).await.wrap_err("user error"));
- results.push(repo(&api).await.wrap_err("repo error"));
- results.push(admin(&api).await.wrap_err("admin error"));
-
- let mut errors = 0;
- for report in results.into_iter().filter_map(Result::err) {
- errors += 1;
- for (i, err) in report.chain().enumerate() {
- println!("{i}. {err}");
- if let Some(err) = err.downcast_ref::<forgejo_api::ForgejoError>() {
- if let forgejo_api::ForgejoError::BadStructure(_, body) = err {
- println!("BODY: {body}");
- }
- }
- }
- }
- if errors > 0 {
- eyre::bail!("test failed");
- }
-
- Ok(())
+fn get_api() -> Forgejo {
+ let url = url::Url::parse(&std::env::var("FORGEJO_API_CI_INSTANCE_URL").unwrap()).unwrap();
+ let token = std::env::var("FORGEJO_API_CI_TOKEN").unwrap();
+ Forgejo::new(forgejo_api::Auth::Token(&token), url).unwrap()
}
-async fn user(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
- let myself = api.myself().await?;
- ensure!(myself.is_admin, "user should be admin");
- ensure!(
- myself.login == "TestingAdmin",
+#[tokio::test]
+async fn user() {
+ let api = get_api();
+
+ let myself = api.user_get_current().await.unwrap();
+ assert!(myself.is_admin.unwrap(), "user should be admin");
+ assert_eq!(
+ myself.login.as_ref().unwrap(),
+ "TestingAdmin",
"user should be named \"TestingAdmin\""
);
- let myself_indirect = api
- .get_user("TestingAdmin")
- .await?
- .ok_or_else(|| eyre!("\"TestingAdmin\" not found, but should have been."))?;
- ensure!(
- myself == myself_indirect,
+ let myself_indirect = api.user_get("TestingAdmin").await.unwrap();
+ assert_eq!(
+ myself, myself_indirect,
"result of `myself` does not match result of `get_user`"
);
- let following = api.get_following("TestingAdmin").await?;
- ensure!(following == Some(Vec::new()), "following list not empty");
- let followers = api.get_followers("TestingAdmin").await?;
- ensure!(followers == Some(Vec::new()), "follower list not empty");
+ let query = UserListFollowingQuery {
+ page: None,
+ limit: None,
+ };
+ let following = api
+ .user_list_following("TestingAdmin", query)
+ .await
+ .unwrap();
+ assert_eq!(following, Vec::new(), "following list not empty");
+
+ let query = UserListFollowersQuery {
+ page: None,
+ limit: None,
+ };
+ let followers = api
+ .user_list_followers("TestingAdmin", query)
+ .await
+ .unwrap();
+ assert_eq!(followers, Vec::new(), "follower list not empty");
- let url = url::Url::parse(&std::env::var("FORGEJO_API_CI_INSTANCE_URL")?)?;
+ let url = url::Url::parse(&std::env::var("FORGEJO_API_CI_INSTANCE_URL").unwrap()).unwrap();
let password_api = Forgejo::new(
forgejo_api::Auth::Password {
username: "TestingAdmin",
@@ -63,103 +53,133 @@ async fn user(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
},
url,
)
- .wrap_err("failed to log in using username and password")?;
+ .expect("failed to log in using username and password");
- ensure!(
- api.myself().await? == password_api.myself().await?,
+ assert!(
+ api.user_get_current().await.unwrap() == password_api.user_get_current().await.unwrap(),
"users not equal comparing token-auth and pass-auth"
);
-
- Ok(())
}
-async fn repo(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
- tokio::fs::create_dir("/test_repo").await?;
+#[tokio::test]
+async fn repo() {
+ let api = get_api();
+
+ tokio::fs::create_dir("./test_repo").await.unwrap();
let git = || {
let mut cmd = std::process::Command::new("git");
- cmd.current_dir("/test_repo");
+ cmd.current_dir("./test_repo");
cmd
};
let _ = git()
.args(["config", "--global", "init.defaultBranch", "main"])
- .status()?;
- let _ = git().args(["init"]).status()?;
+ .status()
+ .unwrap();
+ let _ = git().args(["init"]).status().unwrap();
let _ = git()
.args(["config", "user.name", "TestingAdmin"])
- .status()?;
+ .status()
+ .unwrap();
let _ = git()
.args(["config", "user.email", "admin@noreply.example.org"])
- .status()?;
- tokio::fs::write("/test_repo/README.md", "# Test\nThis is a test repo").await?;
- let _ = git().args(["add", "."]).status()?;
- let _ = git().args(["commit", "-m", "initial commit"]).status()?;
+ .status()
+ .unwrap();
+ tokio::fs::write("./test_repo/README.md", "# Test\nThis is a test repo")
+ .await
+ .unwrap();
+ let _ = git().args(["add", "."]).status().unwrap();
+ let _ = git()
+ .args(["commit", "-m", "initial commit"])
+ .status()
+ .unwrap();
- let repo_opt = forgejo_api::CreateRepoOption {
- auto_init: false,
- default_branch: "main".into(),
+ let repo_opt = CreateRepoOption {
+ auto_init: Some(false),
+ default_branch: Some("main".into()),
description: Some("Test Repo".into()),
- gitignores: "".into(),
- issue_labels: "".into(),
- license: "".into(),
+ gitignores: Some("".into()),
+ issue_labels: Some("".into()),
+ license: Some("".into()),
name: "test".into(),
- private: false,
- readme: "".into(),
- template: false,
- trust_model: forgejo_api::TrustModel::Default,
+ private: Some(false),
+ readme: None,
+ template: Some(false),
+ trust_model: Some(CreateRepoOptionTrustModel::Default),
};
- let remote_repo = api.create_repo(repo_opt).await?;
- ensure!(
- remote_repo.has_pull_requests,
+ let remote_repo = api.create_current_user_repo(repo_opt).await.unwrap();
+ assert!(
+ remote_repo.has_pull_requests.unwrap(),
"repo does not accept pull requests"
);
- ensure!(
- remote_repo.owner.login == "TestingAdmin",
+ assert!(
+ remote_repo.owner.as_ref().unwrap().login.as_ref().unwrap() == "TestingAdmin",
"repo owner is not \"TestingAdmin\""
);
- ensure!(remote_repo.name == "test", "repo owner is not \"test\"");
+ assert!(
+ remote_repo.name.as_ref().unwrap() == "test",
+ "repo owner is not \"test\""
+ );
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
- let mut remote_url = remote_repo.clone_url.clone();
+ let mut remote_url = remote_repo.clone_url.clone().unwrap();
remote_url.set_username("TestingAdmin").unwrap();
remote_url.set_password(Some("password")).unwrap();
let _ = git()
.args(["remote", "add", "origin", remote_url.as_str()])
- .status()?;
- let _ = git().args(["push", "-u", "origin", "main"]).status()?;
+ .status()
+ .unwrap();
+ let _ = git()
+ .args(["push", "-u", "origin", "main"])
+ .status()
+ .unwrap();
- let _ = git().args(["switch", "-c", "test"]).status()?;
+ let _ = git().args(["switch", "-c", "test"]).status().unwrap();
tokio::fs::write(
- "/test_repo/example.rs",
+ "./test_repo/example.rs",
"fn add_one(x: u32) -> u32 { x + 1 }",
)
- .await?;
- let _ = git().args(["add", "."]).status()?;
- let _ = git().args(["commit", "-m", "egg"]).status()?;
- let _ = git().args(["push", "-u", "origin", "test"]).status()?;
+ .await
+ .unwrap();
+ let _ = git().args(["add", "."]).status().unwrap();
+ let _ = git().args(["commit", "-m", "egg"]).status().unwrap();
+ let _ = git()
+ .args(["push", "-u", "origin", "test"])
+ .status()
+ .unwrap();
- let pr_opt = forgejo_api::CreatePullRequestOption {
+ let pr_opt = CreatePullRequestOption {
assignee: None,
- assignees: vec!["TestingAdmin".into()],
- base: "main".into(),
- body: "This is a test PR".into(),
+ assignees: Some(vec!["TestingAdmin".into()]),
+ base: Some("main".into()),
+ body: Some("This is a test PR".into()),
due_date: None,
- head: "test".into(),
- labels: Vec::new(),
+ head: Some("test".into()),
+ labels: None,
milestone: None,
- title: "test pr".into(),
+ title: Some("test pr".into()),
};
let pr = api
- .create_pr("TestingAdmin", "test", pr_opt)
+ .repo_create_pull_request("TestingAdmin", "test", pr_opt)
.await
- .wrap_err("couldn't create pr")?;
+ .expect("couldn't create pr");
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
let is_merged = api
- .is_merged("TestingAdmin", "test", pr.number)
+ .repo_pull_request_is_merged("TestingAdmin", "test", pr.number.unwrap())
+ .await
+ .is_ok();
+ assert!(!is_merged, "pr should not yet be merged");
+ let pr_files_query = RepoGetPullRequestFilesQuery {
+ skip_to: None,
+ whitespace: None,
+ page: None,
+ limit: None,
+ };
+ let (_, _) = api
+ .repo_get_pull_request_files("TestingAdmin", "test", pr.number.unwrap(), pr_files_query)
.await
- .wrap_err_with(|| eyre!("couldn't find unmerged pr {}", pr.number))?;
- ensure!(!is_merged, "pr should not yet be merged");
- let merge_opt = forgejo_api::MergePullRequestOption {
- act: forgejo_api::MergePrAction::Merge,
+ .unwrap();
+ let merge_opt = MergePullRequestOption {
+ r#do: MergePullRequestOptionDo::Merge,
merge_commit_id: None,
merge_message_field: None,
merge_title_field: None,
@@ -168,230 +188,279 @@ async fn repo(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
head_commit_id: None,
merge_when_checks_succeed: None,
};
- api.merge_pr("TestingAdmin", "test", pr.number, merge_opt)
+ api.repo_merge_pull_request("TestingAdmin", "test", pr.number.unwrap(), merge_opt)
.await
- .wrap_err_with(|| eyre!("couldn't merge pr {}", pr.number))?;
+ .expect("couldn't merge pr");
let is_merged = api
- .is_merged("TestingAdmin", "test", pr.number)
+ .repo_pull_request_is_merged("TestingAdmin", "test", pr.number.unwrap())
.await
- .wrap_err_with(|| eyre!("couldn't find merged pr {}", pr.number))?;
- ensure!(is_merged, "pr should be merged");
- let _ = git().args(["fetch"]).status()?;
- let _ = git().args(["pull"]).status()?;
-
- ensure!(
- api.get_releases("TestingAdmin", "test", forgejo_api::ReleaseQuery::default())
+ .is_ok();
+ assert!(is_merged, "pr should be merged");
+ let _ = git().args(["fetch"]).status().unwrap();
+ let _ = git().args(["pull"]).status().unwrap();
+
+ let query = RepoListReleasesQuery {
+ draft: None,
+ pre_release: None,
+ per_page: None,
+ page: None,
+ limit: None,
+ };
+ assert!(
+ api.repo_list_releases("TestingAdmin", "test", query)
.await
- .wrap_err("releases list not found")?
+ .unwrap()
.is_empty(),
"there should be no releases yet"
);
- let tag_opt = forgejo_api::CreateTagOption {
+ let tag_opt = CreateTagOption {
message: Some("This is a tag!".into()),
tag_name: "v1.0".into(),
target: None,
};
- api.create_tag("TestingAdmin", "test", tag_opt)
+ api.repo_create_tag("TestingAdmin", "test", tag_opt)
.await
- .wrap_err("failed to create tag")?;
+ .expect("failed to create tag");
- let release_opt = forgejo_api::CreateReleaseOption {
- body: "This is a release!".into(),
- draft: true,
- name: "v1.0".into(),
- prerelease: false,
+ let release_opt = CreateReleaseOption {
+ body: Some("This is a release!".into()),
+ draft: Some(true),
+ name: Some("v1.0".into()),
+ prerelease: Some(false),
tag_name: "v1.0".into(),
target_commitish: None,
};
let release = api
- .create_release("TestingAdmin", "test", release_opt)
+ .repo_create_release("TestingAdmin", "test", release_opt)
.await
- .wrap_err("failed to create release")?;
- let edit_release = forgejo_api::EditReleaseOption {
+ .expect("failed to create release");
+ let edit_release = EditReleaseOption {
+ body: None,
draft: Some(false),
- ..Default::default()
+ name: None,
+ prerelease: None,
+ tag_name: None,
+ target_commitish: None,
};
- api.edit_release("TestingAdmin", "test", release.id, edit_release)
+ api.repo_edit_release("TestingAdmin", "test", release.id.unwrap(), edit_release)
.await
- .wrap_err("failed to edit release")?;
+ .expect("failed to edit release");
let release_by_tag = api
- .get_release_by_tag("TestingAdmin", "test", "v1.0")
+ .repo_get_release_by_tag("TestingAdmin", "test", "v1.0")
.await
- .wrap_err("failed to find release")?;
+ .expect("failed to find release");
let release_latest = api
- .latest_release("TestingAdmin", "test")
+ .repo_get_latest_release("TestingAdmin", "test")
.await
- .wrap_err("failed to find latest release")?;
- ensure!(release_by_tag == release_latest, "releases not equal");
+ .expect("failed to find latest release");
+ assert!(release_by_tag == release_latest, "releases not equal");
let attachment = api
- .create_release_attachment(
+ .repo_create_release_attachment(
"TestingAdmin",
"test",
- release.id,
- "test.txt",
+ release.id.unwrap(),
b"This is a file!".to_vec(),
+ RepoCreateReleaseAttachmentQuery {
+ name: Some("test.txt".into()),
+ },
)
.await
- .wrap_err("failed to create release attachment")?;
- ensure!(
- api.download_release_attachment("TestingAdmin", "test", release.id, attachment.id)
- .await?
- .as_deref()
- == Some(b"This is a file!"),
+ .expect("failed to create release attachment");
+ assert!(
+ &*api
+ .download_release_attachment(
+ "TestingAdmin",
+ "test",
+ release.id.unwrap(),
+ attachment.id.unwrap()
+ )
+ .await
+ .unwrap()
+ == b"This is a file!",
"couldn't download attachment"
);
- ensure!(
- api.download_zip_archive("TestingAdmin", "test", "v1.0")
- .await?
- .is_some(),
- "couldn't download zip archive"
- );
- ensure!(
- api.download_tarball_archive("TestingAdmin", "test", "v1.0")
- .await?
- .is_some(),
- "couldn't download tape archive"
- );
-
- api.delete_release_attachment("TestingAdmin", "test", release.id, attachment.id)
+ let _zip_archive = api
+ .repo_get_archive("TestingAdmin", "test", "v1.0.zip")
.await
- .wrap_err("failed to deleted attachment")?;
-
- api.delete_release("TestingAdmin", "test", release.id)
+ .unwrap();
+ let _tar_archive = api
+ .repo_get_archive("TestingAdmin", "test", "v1.0.tar.gz")
.await
- .wrap_err("failed to delete release")?;
+ .unwrap();
+ // check these contents when their return value is fixed
+
+ api.repo_delete_release_attachment(
+ "TestingAdmin",
+ "test",
+ release.id.unwrap(),
+ attachment.id.unwrap(),
+ )
+ .await
+ .expect("failed to deleted attachment");
- api.delete_tag("TestingAdmin", "test", "v1.0")
+ api.repo_delete_release("TestingAdmin", "test", release.id.unwrap())
.await
- .wrap_err("failed to delete release")?;
+ .expect("failed to delete release");
- Ok(())
+ api.repo_delete_tag("TestingAdmin", "test", "v1.0")
+ .await
+ .expect("failed to delete release");
}
-async fn admin(api: &forgejo_api::Forgejo) -> eyre::Result<()> {
- let user_opt = forgejo_api::CreateUserOption {
+#[tokio::test]
+async fn admin() {
+ let api = get_api();
+
+ let user_opt = CreateUserOption {
created_at: None,
- email: "user@noreply.example.org".into(),
+ email: "pipis@noreply.example.org".into(),
full_name: None,
login_name: None,
- must_change_password: false,
- password: "userpass".into(),
- restricted: false,
- send_notify: true,
+ must_change_password: None,
+ password: Some("userpass".into()),
+ restricted: Some(false),
+ send_notify: Some(true),
source_id: None,
username: "Pipis".into(),
- visibility: "public".into(),
+ visibility: Some("public".into()),
};
let _ = api
.admin_create_user(user_opt)
.await
- .wrap_err("failed to create user")?;
+ .expect("failed to create user");
+ let query = AdminSearchUsersQuery {
+ source_id: None,
+ login_name: None,
+ page: None,
+ limit: None,
+ };
let users = api
- .admin_users(forgejo_api::AdminUserQuery::default())
+ .admin_search_users(query)
.await
- .wrap_err("failed to search users")?;
- ensure!(
- users.iter().find(|u| u.login == "Pipis").is_some(),
+ .expect("failed to search users");
+ assert!(
+ users
+ .iter()
+ .find(|u| u.login.as_ref().unwrap() == "Pipis")
+ .is_some(),
"could not find new user"
);
+ let query = AdminGetAllEmailsQuery {
+ page: None,
+ limit: None,
+ };
let users = api
- .admin_get_emails(forgejo_api::EmailListQuery::default())
+ .admin_get_all_emails(query)
.await
- .wrap_err("failed to search emails")?;
- ensure!(
+ .expect("failed to search emails");
+ assert!(
users
.iter()
- .find(|u| u.email == "user@noreply.example.org")
+ .find(|u| u.email.as_ref().unwrap() == "pipis@noreply.example.org")
.is_some(),
"could not find new user"
);
- let org_opt = forgejo_api::CreateOrgOption {
+ let org_opt = CreateOrgOption {
description: None,
+ email: None,
full_name: None,
location: None,
repo_admin_change_team_access: None,
username: "test-org".into(),
- visibility: forgejo_api::OrgVisibility::Public,
+ visibility: Some(CreateOrgOptionVisibility::Public),
website: None,
};
let _ = api
.admin_create_org("Pipis", org_opt)
.await
- .wrap_err("failed to create org")?;
- ensure!(
- !api.admin_get_orgs(forgejo_api::AdminOrganizationQuery::default())
- .await?
- .is_empty(),
+ .expect("failed to create org");
+ let query = AdminGetAllOrgsQuery {
+ page: None,
+ limit: None,
+ };
+ assert!(
+ !api.admin_get_all_orgs(query).await.unwrap().is_empty(),
"org list empty"
);
- let key_opt = forgejo_api::CreateKeyOption {
+ let key_opt = CreateKeyOption {
key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN68ehQAsbGEwlXPa2AxbAh1QxFQrtRel2jeC0hRlPc1 user@noreply.example.org".into(),
read_only: None,
title: "Example Key".into(),
};
let key = api
- .admin_add_key("Pipis", key_opt)
+ .admin_create_public_key("Pipis", key_opt)
.await
- .wrap_err("failed to create key")?;
- api.admin_delete_key("Pipis", key.id)
+ .expect("failed to create key");
+ api.admin_delete_user_public_key("Pipis", key.id.unwrap())
.await
- .wrap_err("failed to delete key")?;
+ .expect("failed to delete key");
- let rename_opt = forgejo_api::RenameUserOption {
+ let rename_opt = RenameUserOption {
new_username: "Bepis".into(),
};
api.admin_rename_user("Pipis", rename_opt)
.await
- .wrap_err("failed to rename user")?;
- api.admin_delete_user("Bepis", true)
+ .expect("failed to rename user");
+ let query = AdminDeleteUserQuery { purge: Some(true) };
+ api.admin_delete_user("Bepis", query)
.await
- .wrap_err("failed to delete user")?;
- ensure!(
- api.admin_delete_user("Ghost", true).await.is_err(),
+ .expect("failed to delete user");
+ let query = AdminDeleteUserQuery { purge: Some(true) };
+ assert!(
+ api.admin_delete_user("Ghost", query).await.is_err(),
"deleting fake user should fail"
);
+ let query = AdminCronListQuery {
+ page: None,
+ limit: None,
+ };
let crons = api
- .admin_get_crons(forgejo_api::CronQuery::default())
+ .admin_cron_list(query)
.await
- .wrap_err("failed to get crons list")?;
- api.admin_run_cron(&crons.get(0).ok_or_else(|| eyre!("no crons"))?.name)
+ .expect("failed to get crons list");
+ api.admin_cron_run(&crons.get(0).expect("no crons").name.as_ref().unwrap())
.await
- .wrap_err("failed to run cron")?;
+ .expect("failed to run cron");
- let hook_opt = forgejo_api::CreateHookOption {
+ let hook_opt = CreateHookOption {
active: None,
authorization_header: None,
branch_filter: None,
- config: forgejo_api::CreateHookOptionConfig {
- content_type: "json".into(),
- url: url::Url::parse("http://test.local/").unwrap(),
- other: Default::default(),
+ config: CreateHookOptionConfig {
+ // content_type: "json".into(),
+ // url: url::Url::parse("http://test.local/").unwrap(),
+ additional: [
+ ("content_type".into(), "json".into()),
+ ("url".into(), "http://test.local/".into()),
+ ]
+ .into(),
},
- events: Vec::new(),
- _type: forgejo_api::HookType::Forgejo,
+ events: Some(Vec::new()),
+ r#type: CreateHookOptionType::Gitea,
};
// yarr har har me matey this is me hook
let hook = api
.admin_create_hook(hook_opt)
.await
- .wrap_err("failed to create hook")?;
- let edit_hook = forgejo_api::EditHookOption {
+ .expect("failed to create hook");
+ let edit_hook = EditHookOption {
active: Some(true),
- ..Default::default()
+ authorization_header: None,
+ branch_filter: None,
+ config: None,
+ events: None,
};
- api.admin_edit_hook(hook.id, edit_hook)
+ api.admin_edit_hook(hook.id.unwrap(), edit_hook)
.await
- .wrap_err("failed to edit hook")?;
- api.admin_delete_hook(hook.id)
+ .expect("failed to edit hook");
+ api.admin_delete_hook(hook.id.unwrap())
.await
- .wrap_err("failed to delete hook")?;
-
- Ok(())
+ .expect("failed to delete hook");
}