1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
use std::path::PathBuf;
use clap::{Args, Subcommand};
use serde::{Deserialize, Serialize};
use crate::schema::{
AttachmentsDeleteByFilterReq, AttachmentsDeleteByKeysReq, AttachmentsDownloadByFilterReq,
AttachmentsDownloadByKeysReq, AttachmentsQueryReq,
};
#[derive(Serialize, Debug, Deserialize, Args, derive_more::From, Clone)]
pub struct AttachmentsArgs {
#[command(subcommand)]
pub command: AttachmentsCommands,
}
#[derive(Subcommand, Serialize, Debug, Deserialize, derive_more::From, Clone)]
pub enum AttachmentsCommands {
/// Delete an attachment from a group
Delete(DeleteAttachmentArgs),
/// Upload an attachment to a group
Upload(UploadAttachmentArgs),
/// Get the metadata of an attachment
Get(GetAttachmentMetaArgs),
/// Download an attachment of a group
Download(DownloadAttachmentArgs),
/// Query attachments subject to the filter
Query(QueryAttachmentsArgs),
/// Batch download attachments by filter criteria
DownloadMany(DownloadAttachmentsByFilterArgs),
/// Batch download attachments by keys
DownloadList(DownloadAttachmentsByListArgs),
/// Batch delete attachments by filter criteria
DeleteMany(DeleteAttachmentsByFilterArgs),
/// Batch delete attachments by keys
DeleteList(DeleteAttachmentsByListArgs),
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DeleteAttachmentArgs {
/// The group of the attachment belongs to
#[arg(short = 'g', long = "group")]
pub group_name: Option<String>,
/// The key of the attachment
pub key: String,
/// Parse the command with smart mode. Will try parse the first component before first `/` in
/// key (if specified) as group-name (if not specified)
#[arg(short, long)]
pub smart: bool,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct UploadAttachmentArgs {
/// The path of the local file to upload
pub local_file: PathBuf,
/// The group of the attachment uploaded to
#[arg(short = 'g', long = "group")]
pub group_name: Option<String>,
/// The key of the attachment uploaded to. If not specified, the filename will be used.
/// If the key specified is a directory (ends with '/'),
/// the filename (final component of local file) will be appended to it.
pub key: Option<String>,
/// Whether to show progress bar when downloading
#[arg(long)]
pub pb: bool,
/// Parse the command with smart mode. Will try parse the first component before first `/` in
/// key (if specified) as group-name (if not specified)
#[arg(short, long)]
pub smart: bool,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DownloadAttachmentArgs {
/// The group of the attachment belongs to
#[arg(short, long = "group")]
pub group_name: Option<String>,
/// The key of the attachment
pub key: String,
/// Specify the path to download the artifact
#[arg(short, long = "output")]
pub output_path: Option<String>,
/// Only output the URL without downloading the attachment
#[arg(long)]
pub no_download: bool,
/// Whether to show progress bar when downloading
#[arg(long)]
pub pb: bool,
/// Try to use file name (last path component) of key
/// as part of the output path
#[arg(short, long)]
pub smart: bool,
}
#[derive(Serialize, Debug, Deserialize, Clone)]
pub(crate) struct InnerDownloadAttachmentArgs {
/// The group of the attachment belongs to
pub(crate) group_name: String,
/// The key of the attachment
pub(crate) key: String,
/// Specify the path to download the artifact
pub(crate) output_path: PathBuf,
/// Whether to show progress bar when downloading
pub(crate) show_pb: bool,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct QueryAttachmentsArgs {
/// The name of the group the attachments belong to
#[arg(short, long)]
pub group: Option<String>,
/// The part of the key of the attachments
#[arg(short, long = "key")]
pub key: Option<String>,
/// The limit of the tasks to query
#[arg(long)]
pub limit: Option<u64>,
/// The offset of the tasks to query
#[arg(long)]
pub offset: Option<u64>,
/// Only count the number of workers
#[arg(long)]
pub count: bool,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct GetAttachmentMetaArgs {
/// The group of the attachment belongs to
#[arg(short = 'g', long = "group")]
pub group_name: Option<String>,
/// The key of the attachment
pub key: String,
/// Parse the command with smart mode. Will try parse the first component before first `/` in
/// key (if specified) as group-name (if not specified)
#[arg(short, long)]
pub smart: bool,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DownloadAttachmentsByFilterArgs {
/// The name of the group the attachments belong to
#[arg(short, long)]
pub group: Option<String>,
/// The part of the key of the attachments
#[arg(short, long = "key")]
pub key: Option<String>,
/// The limit of the attachments to download
#[arg(long)]
pub limit: Option<u64>,
/// The offset of the attachments to download
#[arg(long)]
pub offset: Option<u64>,
/// Specify the directory to download attachments
#[arg(short, long = "output")]
pub output_dir: Option<PathBuf>,
/// Only output the URLs without downloading
#[arg(long)]
pub no_download: bool,
/// Whether to show progress bar when downloading
#[arg(long)]
pub pb: bool,
/// Number of concurrent downloads (default: 1)
#[arg(long, default_value_t = 1)]
pub concurrent: usize,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DownloadAttachmentsByListArgs {
/// The name of the group the attachments belong to
#[arg(short, long)]
pub group: Option<String>,
/// The keys of the attachments
#[arg(num_args = 1..)]
pub keys: Vec<String>,
/// Specify the directory to download attachments
#[arg(short, long = "output")]
pub output_dir: Option<PathBuf>,
/// Only output the URLs without downloading
#[arg(long)]
pub no_download: bool,
/// Whether to show progress bar when downloading
#[arg(long)]
pub pb: bool,
/// Number of concurrent downloads (default: 1)
#[arg(long, default_value_t = 1)]
pub concurrent: usize,
}
impl From<QueryAttachmentsArgs> for AttachmentsQueryReq {
fn from(args: QueryAttachmentsArgs) -> Self {
Self {
key: args.key,
limit: args.limit,
offset: args.offset,
count: args.count,
}
}
}
impl From<DownloadAttachmentsByFilterArgs> for AttachmentsDownloadByFilterReq {
fn from(args: DownloadAttachmentsByFilterArgs) -> Self {
Self {
key: args.key,
limit: args.limit,
offset: args.offset,
}
}
}
impl From<DownloadAttachmentsByListArgs> for AttachmentsDownloadByKeysReq {
fn from(args: DownloadAttachmentsByListArgs) -> Self {
Self { keys: args.keys }
}
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DeleteAttachmentsByFilterArgs {
/// The name of the group the attachments belong to
#[arg(short, long)]
pub group: Option<String>,
/// The part of the key of the attachments
#[arg(short, long = "key")]
pub key: Option<String>,
/// The limit of the attachments to delete
#[arg(long)]
pub limit: Option<u64>,
/// The offset of the attachments to delete
#[arg(long)]
pub offset: Option<u64>,
}
#[derive(Serialize, Debug, Deserialize, Args, Clone)]
pub struct DeleteAttachmentsByListArgs {
/// The name of the group the attachments belong to
#[arg(short, long)]
pub group: Option<String>,
/// The keys of the attachments
#[arg(num_args = 1..)]
pub keys: Vec<String>,
}
impl From<DeleteAttachmentsByFilterArgs> for AttachmentsDeleteByFilterReq {
fn from(args: DeleteAttachmentsByFilterArgs) -> Self {
Self {
key: args.key,
limit: args.limit,
offset: args.offset,
}
}
}
impl From<DeleteAttachmentsByListArgs> for AttachmentsDeleteByKeysReq {
fn from(args: DeleteAttachmentsByListArgs) -> Self {
Self { keys: args.keys }
}
}