Merge pull request 'feat: implement ssh_url deserialization to url::Url
instead of String
' (#53) from Aviac/forgejo-api:feat/parse-ssh-url into main
Reviewed-on: https://codeberg.org/Cyborus/forgejo-api/pulls/53 Reviewed-by: Cyborus <cyborus@noreply.codeberg.org>
This commit is contained in:
commit
80cba9a6c3
|
@ -63,7 +63,7 @@ pub fn create_struct_for_definition(
|
|||
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" {
|
||||
if field_name.ends_with("url") && field_ty == "String" {
|
||||
field_ty = "url::Url".into()
|
||||
}
|
||||
if field_ty == name {
|
||||
|
@ -73,8 +73,17 @@ pub fn create_struct_for_definition(
|
|||
field_ty = format!("Option<{field_ty}>")
|
||||
}
|
||||
if field_ty == "Option<url::Url>" {
|
||||
if field_name == "ssh_url" {
|
||||
fields.push_str(
|
||||
"#[serde(deserialize_with = \"crate::deserialize_optional_ssh_url\")]\n",
|
||||
);
|
||||
} else {
|
||||
fields.push_str("#[serde(deserialize_with = \"crate::none_if_blank_url\")]\n");
|
||||
}
|
||||
}
|
||||
if field_ty == "url::Url" && field_name == "ssh_url" {
|
||||
fields.push_str("#[serde(deserialize_with = \"crate::deserialize_ssh_url\")]\n");
|
||||
}
|
||||
if field_ty == "time::OffsetDateTime" {
|
||||
fields.push_str("#[serde(with = \"time::serde::rfc3339\")]\n");
|
||||
}
|
||||
|
@ -106,8 +115,8 @@ pub fn create_struct_for_definition(
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(additonal_schema) = &schema.additional_properties {
|
||||
let prop_ty = crate::schema_ref_type_name(spec, additonal_schema)?;
|
||||
if let Some(additional_schema) = &schema.additional_properties {
|
||||
let prop_ty = crate::schema_ref_type_name(spec, additional_schema)?;
|
||||
fields.push_str("#[serde(flatten)]\n");
|
||||
fields.push_str("pub additional: BTreeMap<String, ");
|
||||
fields.push_str(&prop_ty);
|
||||
|
|
|
@ -2278,7 +2278,8 @@ pub struct Repository {
|
|||
pub release_counter: Option<u64>,
|
||||
pub repo_transfer: Option<RepoTransfer>,
|
||||
pub size: Option<u64>,
|
||||
pub ssh_url: Option<String>,
|
||||
#[serde(deserialize_with = "crate::deserialize_optional_ssh_url")]
|
||||
pub ssh_url: Option<url::Url>,
|
||||
pub stars_count: Option<u64>,
|
||||
pub template: Option<bool>,
|
||||
#[serde(with = "time::serde::rfc3339::option")]
|
||||
|
|
36
src/lib.rs
36
src/lib.rs
|
@ -1,4 +1,5 @@
|
|||
use reqwest::{Client, Request, StatusCode};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use soft_assert::*;
|
||||
use url::Url;
|
||||
use zeroize::Zeroize;
|
||||
|
@ -254,6 +255,41 @@ fn none_if_blank_url<'de, D: serde::Deserializer<'de>>(
|
|||
deserializer.deserialize_str(EmptyUrlVisitor)
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // not used yet, but it might appear in the future
|
||||
fn deserialize_ssh_url<'de, D, DE>(deserializer: D) -> Result<Url, DE>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
DE: serde::de::Error,
|
||||
{
|
||||
let raw_url: String = String::deserialize(deserializer).map_err(DE::custom)?;
|
||||
parse_ssh_url(&raw_url).map_err(DE::custom)
|
||||
}
|
||||
|
||||
fn deserialize_optional_ssh_url<'de, D, DE>(deserializer: D) -> Result<Option<Url>, DE>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
DE: serde::de::Error,
|
||||
{
|
||||
let raw_url: Option<String> = Option::deserialize(deserializer).map_err(DE::custom)?;
|
||||
raw_url
|
||||
.as_ref()
|
||||
.map(parse_ssh_url)
|
||||
.map(|res| res.map_err(DE::custom))
|
||||
.transpose()
|
||||
.or(Ok(None))
|
||||
}
|
||||
|
||||
fn parse_ssh_url(raw_url: &String) -> Result<Url, url::ParseError> {
|
||||
// in case of a non-standard ssh-port (not 22), the ssh url coming from the forgejo API
|
||||
// is actually parseable by the url crate, so try to do that first
|
||||
Url::parse(raw_url).or_else(|_| {
|
||||
// otherwise the ssh url is not parseable by the url crate and we try again after some
|
||||
// pre-processing
|
||||
let url = format!("ssh://{url}", url = raw_url.replace(":", "/"));
|
||||
Url::parse(url.as_str())
|
||||
})
|
||||
}
|
||||
|
||||
impl From<structs::DefaultMergeStyle> for structs::MergePullRequestOptionDo {
|
||||
fn from(value: structs::DefaultMergeStyle) -> Self {
|
||||
match value {
|
||||
|
|
|
@ -430,3 +430,9 @@ async fn admin() {
|
|||
.await
|
||||
.expect("failed to delete hook");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ssh_url_deserialization() {
|
||||
let data = include_str!("./repo_data.json");
|
||||
assert!(serde_json::from_str::<Repository>(data).is_ok());
|
||||
}
|
||||
|
|
91
tests/repo_data.json
Normal file
91
tests/repo_data.json
Normal file
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"id": 160106,
|
||||
"owner": {
|
||||
"id": 94809,
|
||||
"login": "Cyborus",
|
||||
"login_name": "",
|
||||
"full_name": "",
|
||||
"email": "cyborus@noreply.codeberg.org",
|
||||
"avatar_url": "https://codeberg.org/avatars/53e78f627539c6a0b96854028529779133724a5df2d2c229e5d0eb48aaa3d1fa",
|
||||
"language": "",
|
||||
"is_admin": false,
|
||||
"last_login": "0001-01-01T00:00:00Z",
|
||||
"created": "2023-04-30T00:54:15Z",
|
||||
"restricted": false,
|
||||
"active": false,
|
||||
"prohibit_login": false,
|
||||
"location": "",
|
||||
"pronouns": "",
|
||||
"website": "https://cyborus.xyz",
|
||||
"description": "I host my own Forgejo instance at https://code.cartoon-aa.xyz/",
|
||||
"visibility": "public",
|
||||
"followers_count": 4,
|
||||
"following_count": 4,
|
||||
"starred_repos_count": 8,
|
||||
"username": "Cyborus"
|
||||
},
|
||||
"name": "forgejo-api",
|
||||
"full_name": "Cyborus/forgejo-api",
|
||||
"description": "Rust crate to interact with the Forgejo API",
|
||||
"empty": false,
|
||||
"private": false,
|
||||
"fork": false,
|
||||
"template": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 1481,
|
||||
"language": "Rust",
|
||||
"languages_url": "https://codeberg.org/api/v1/repos/Cyborus/forgejo-api/languages",
|
||||
"html_url": "https://codeberg.org/Cyborus/forgejo-api",
|
||||
"url": "https://codeberg.org/api/v1/repos/Cyborus/forgejo-api",
|
||||
"link": "",
|
||||
"ssh_url": "git@codeberg.org:Cyborus/forgejo-api.git",
|
||||
"clone_url": "https://codeberg.org/Cyborus/forgejo-api.git",
|
||||
"original_url": "",
|
||||
"website": "",
|
||||
"stars_count": 4,
|
||||
"forks_count": 1,
|
||||
"watchers_count": 2,
|
||||
"open_issues_count": 2,
|
||||
"open_pr_counter": 0,
|
||||
"release_counter": 2,
|
||||
"default_branch": "main",
|
||||
"archived": false,
|
||||
"created_at": "2023-11-09T17:42:18Z",
|
||||
"updated_at": "2024-04-27T22:42:52Z",
|
||||
"archived_at": "1970-01-01T00:00:00Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": true
|
||||
},
|
||||
"has_issues": true,
|
||||
"internal_tracker": {
|
||||
"enable_time_tracker": true,
|
||||
"allow_only_contributors_to_track_time": true,
|
||||
"enable_issue_dependencies": true
|
||||
},
|
||||
"has_wiki": false,
|
||||
"wiki_branch": "master",
|
||||
"has_pull_requests": true,
|
||||
"has_projects": true,
|
||||
"has_releases": true,
|
||||
"has_packages": false,
|
||||
"has_actions": false,
|
||||
"ignore_whitespace_conflicts": false,
|
||||
"allow_merge_commits": true,
|
||||
"allow_rebase": true,
|
||||
"allow_rebase_explicit": true,
|
||||
"allow_squash_merge": true,
|
||||
"allow_fast_forward_only_merge": false,
|
||||
"allow_rebase_update": true,
|
||||
"default_delete_branch_after_merge": true,
|
||||
"default_merge_style": "merge",
|
||||
"default_allow_maintainer_edit": true,
|
||||
"avatar_url": "",
|
||||
"internal": false,
|
||||
"mirror_interval": "",
|
||||
"object_format_name": "sha1",
|
||||
"mirror_updated": "0001-01-01T00:00:00Z",
|
||||
"repo_transfer": null
|
||||
}
|
Loading…
Reference in a new issue