From a5f6335b5f8e88205cfef4248e1d96d795a9be08 Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Sat, 7 Jun 2025 23:50:16 -0500 Subject: [PATCH] Add `Attachment` struct, new iface for create-rel The Attachment struct exists, but this makes it glaringly obvious that I've made a bad interface. The create_release_attachment should only accept one file at a time and the loop over all files should happen in main.rs I've changed the signature, removed the loops, and wired in the newer error handling routines. Needs fixing at call sites. --- src/api/release_attachment.rs | 64 +++++++++++++++++------------------ src/structs/mod.rs | 13 +++++++ 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/api/release_attachment.rs b/src/api/release_attachment.rs index 0a3def3..7918178 100644 --- a/src/api/release_attachment.rs +++ b/src/api/release_attachment.rs @@ -1,6 +1,6 @@ use std::fs; -use crate::ApiError; +use crate::structs::Attachment; pub fn check_release_match_repo() {} pub fn get_release_attachment() {} @@ -12,44 +12,44 @@ pub async fn create_release_attachment( gitea_url: &str, repo: &str, release_id: usize, - files: Vec, -) -> crate::Result<()> { + file: String, +) -> crate::Result { let request_url = format!("{gitea_url}/api/v1/repos/{repo}/releases/{release_id}/assets"); - // Ensure all files exists before starting the uploads - for file in &files { - match fs::exists(file) { - Ok(true) => continue, - Ok(false) => return Err(crate::Error::NoSuchFile), - Err(e) => { - eprintln!("Uh oh! The file-exists check couldn't be done: {e}"); - panic!("TODO: Deal with scenario where the file's existence cannot be checked (e.g.: no permission)"); - }, - } + match fs::exists(&file) { + Ok(true) => (), + Ok(false) => return Err(crate::Error::NoSuchFile), + Err(e) => { + eprintln!("Uh oh! The file-exists check couldn't be done: {e}"); + panic!("TODO: Deal with scenario where the file's existence cannot be checked (e.g.: no permission)"); + }, } - for file in files { - println!("Uploading file {}", &file); - let data = reqwest::multipart::Part::stream(fs::read(&file).unwrap()) - .file_name("attachment") - .mime_str("text/plain")?; + println!("Uploading file {}", &file); + let data = reqwest::multipart::Part::stream(fs::read(&file).unwrap()) + .file_name("attachment") + .mime_str("text/plain")?; - let form = reqwest::multipart::Form::new().part("attachment", data); + let form = reqwest::multipart::Form::new().part("attachment", data); - let response = client - .post(&request_url) - .multipart(form) - .query(&[("name", file.split("/").last())]) - .send() - .await?; - if response.status().is_success() { - // TODO: create a struct Attachment and return it to the caller. - } else if response.status().is_client_error() { - let mesg = crate::decode_client_error(response).await?; - return Err(crate::Error::ApiErrorMessage(mesg)); - } + let response = client + .post(&request_url) + .multipart(form) + .query(&[("name", file.split("/").last())]) + .send() + .await?; + if response.status().is_success() { + // TODO: create a struct Attachment and return it to the caller. + let attachment_desc = response + .json::() + .await + .map_err(|e| crate::Error::from(e))?; + return Ok(attachment_desc); + } else if response.status().is_client_error() { + let mesg = crate::decode_client_error(response).await?; + return Err(crate::Error::ApiErrorMessage(mesg)); } - Ok(()) + panic!("Reached end of release_attachment without matching a return path"); } pub fn edit_release_attachment() {} pub fn delete_release_attachment() {} diff --git a/src/structs/mod.rs b/src/structs/mod.rs index 357eccf..5623965 100644 --- a/src/structs/mod.rs +++ b/src/structs/mod.rs @@ -1,2 +1,15 @@ +use serde::{Deserialize, Serialize}; + pub mod release; pub mod repo; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Attachment { + id: usize, + name: String, + size: i64, + download_count: i64, + created: String, // TODO: Date-time struct + uuid: String, + download_url: String, +}