Skip to main content

gitea_sdk_rs/options/
release.rs

1// Copyright 2026 infinitete. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4
5//! Request option types for release and attachment API endpoints.
6
7use crate::pagination::{ListOptions, QueryEncode};
8use crate::{Deserialize, Serialize};
9
10// ── ListReleasesOptions (release.go) ─────────────────────────────────
11
12/// ListReleasesOptions options for listing repository's releases
13#[derive(Debug, Clone, Default)]
14/// Options for List Releases Option.
15pub struct ListReleasesOptions {
16    pub list_options: ListOptions,
17    pub is_draft: Option<bool>,
18    pub is_pre_release: Option<bool>,
19}
20
21impl QueryEncode for ListReleasesOptions {
22    fn query_encode(&self) -> String {
23        let mut out = self.list_options.query_encode();
24        if let Some(draft) = self.is_draft {
25            out.push_str(&format!("&draft={draft}"));
26        }
27        if let Some(pre) = self.is_pre_release {
28            out.push_str(&format!("&pre-release={pre}"));
29        }
30        out
31    }
32}
33
34// ── CreateReleaseOption (release.go) ────────────────────────────────
35
36/// CreateReleaseOption options when creating a release
37#[derive(Debug, Clone, Serialize, Deserialize)]
38/// Options for Create Release Option.
39pub struct CreateReleaseOption {
40    /// tag_name
41    #[serde(rename = "tag_name")]
42    pub tag_name: String,
43    /// target_commitish
44    #[serde(rename = "target_commitish", skip_serializing_if = "Option::is_none")]
45    pub target: Option<String>,
46    /// name
47    #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
48    pub title: Option<String>,
49    /// body
50    #[serde(rename = "body", skip_serializing_if = "Option::is_none")]
51    pub note: Option<String>,
52    /// draft
53    #[serde(default)]
54    pub is_draft: bool,
55    /// prerelease
56    #[serde(default)]
57    pub is_prerelease: bool,
58}
59
60impl CreateReleaseOption {
61    /// Validate the CreateReleaseOption struct
62    pub fn validate(&self) -> crate::Result<()> {
63        if self.tag_name.trim().is_empty() {
64            return Err(crate::Error::Validation("tag_name is required".to_string()));
65        }
66        if let Some(ref title) = self.title
67            && title.trim().is_empty()
68        {
69            return Err(crate::Error::Validation("title is empty".to_string()));
70        }
71        Ok(())
72    }
73}
74
75// ── EditReleaseOption (release.go) ──────────────────────────────────
76
77/// EditReleaseOption options when editing a release
78#[derive(Debug, Clone, Default, Serialize, Deserialize)]
79/// Options for Edit Release Option.
80pub struct EditReleaseOption {
81    /// tag_name
82    #[serde(rename = "tag_name", skip_serializing_if = "Option::is_none")]
83    pub tag_name: Option<String>,
84    /// target_commitish
85    #[serde(rename = "target_commitish", skip_serializing_if = "Option::is_none")]
86    pub target: Option<String>,
87    /// name
88    #[serde(rename = "name", skip_serializing_if = "Option::is_none")]
89    pub title: Option<String>,
90    /// body
91    #[serde(rename = "body", skip_serializing_if = "Option::is_none")]
92    pub note: Option<String>,
93    /// draft
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub is_draft: Option<bool>,
96    /// prerelease
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub is_prerelease: Option<bool>,
99}
100
101// ── ListReleaseAttachmentsOptions (attachment.go) ───────────────────
102
103/// ListReleaseAttachmentsOptions options for listing release's attachments
104#[derive(Debug, Clone, Default)]
105/// Options for List Release Attachments Option.
106pub struct ListReleaseAttachmentsOptions {
107    pub list_options: ListOptions,
108}
109
110impl QueryEncode for ListReleaseAttachmentsOptions {
111    fn query_encode(&self) -> String {
112        self.list_options.query_encode()
113    }
114}
115
116// ── EditAttachmentOption (attachment.go) ─────────────────────────────
117
118/// EditAttachmentOptions options for editing attachments
119#[derive(Debug, Clone, Serialize, Deserialize)]
120/// Options for Edit Attachment Option.
121pub struct EditAttachmentOption {
122    /// name
123    pub name: String,
124}
125
126impl EditAttachmentOption {
127    /// Validate the EditAttachmentOption struct
128    pub fn validate(&self) -> crate::Result<()> {
129        if self.name.trim().is_empty() {
130            return Err(crate::Error::Validation("name is required".to_string()));
131        }
132        Ok(())
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139
140    #[test]
141    fn test_create_release_option_validate_success() {
142        let opt = CreateReleaseOption {
143            tag_name: "v1.0.0".to_string(),
144            target: None,
145            title: None,
146            note: None,
147            is_draft: false,
148            is_prerelease: false,
149        };
150        assert!(opt.validate().is_ok());
151    }
152
153    #[test]
154    fn test_create_release_option_validate_empty_tag_name() {
155        let opt = CreateReleaseOption {
156            tag_name: String::new(),
157            target: None,
158            title: None,
159            note: None,
160            is_draft: false,
161            is_prerelease: false,
162        };
163        assert!(opt.validate().is_err());
164    }
165
166    #[test]
167    fn test_create_release_option_validate_empty_title() {
168        let opt = CreateReleaseOption {
169            tag_name: "v1.0.0".to_string(),
170            target: None,
171            title: Some("   ".to_string()),
172            note: None,
173            is_draft: false,
174            is_prerelease: false,
175        };
176        assert!(opt.validate().is_err());
177    }
178
179    #[test]
180    fn test_edit_attachment_option_validate_success() {
181        let opt = EditAttachmentOption {
182            name: "file.zip".to_string(),
183        };
184        assert!(opt.validate().is_ok());
185    }
186
187    #[test]
188    fn test_edit_attachment_option_validate_empty_name() {
189        let opt = EditAttachmentOption {
190            name: String::new(),
191        };
192        assert!(opt.validate().is_err());
193    }
194}