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
use clap::Subcommand;
#[derive(Subcommand)]
pub enum AttachmentAction {
/// List all attachments on a bug.
///
/// Prints attachment ID, summary, file name, MIME type, size,
/// creator, and creation date for every attachment on the given
/// bug. Use `--json` for a structured listing suitable for
/// scripting.
///
/// Examples:
///
/// bzr attachment list 12345
/// bzr attachment list 12345 --json | jq '.attachments[].id'
///
/// See bzr-attachment-download(1) to fetch one and
/// bzr-attachment-upload(1) to add a new attachment.
#[command(verbatim_doc_comment)]
List {
/// Bug ID
bug_id: u64,
},
/// Download an attachment to a local file.
///
/// Fetches the attachment by ID and writes the decoded bytes to
/// disk. With `--out`/`-o`, the file is written to the given
/// path; otherwise the attachment's stored file name is used in
/// the current directory. Base64 decoding is handled transparently;
/// the on-disk file is the original binary.
///
/// Examples:
///
/// bzr attachment download 9876
/// bzr attachment download 9876 --out patch.diff
/// bzr attachment download 9876 -o /tmp/sample.bin
///
/// See bzr-attachment-list(1) to discover IDs for a bug.
#[command(verbatim_doc_comment)]
Download {
/// Attachment ID
id: u64,
/// Output file path (defaults to original filename)
#[arg(short = 'o', long = "out", id = "out_file")]
out: Option<String>,
},
/// Upload a file as an attachment on a bug.
///
/// Reads the local file at `<file>` and uploads it as an
/// attachment on `<bug_id>`. MIME type is auto-detected from the
/// file extension and may be overridden with `--content-type`.
/// `--summary` sets the attachment's display label;
/// it defaults to the file name if omitted.
///
/// `--flag` accepts Bugzilla flag syntax (`name?`, `name+`,
/// `name-`, `name?(user@example.com)`) and is repeatable.
/// Requires credentials with attach-file permission on the
/// target product.
///
/// Examples:
///
/// bzr attachment upload 12345 patch.diff
/// bzr attachment upload 12345 trace.log --summary "Stack trace" \
/// --content-type text/plain
/// bzr attachment upload 12345 fix.patch \
/// --flag 'review?(maintainer@example.com)'
///
/// See bzr-attachment-update(1) to modify metadata after upload.
#[command(verbatim_doc_comment)]
Upload {
/// Bug ID
bug_id: u64,
/// File to upload
file: String,
/// Attachment summary/description
#[arg(long)]
summary: Option<String>,
/// MIME type (auto-detected if not provided)
#[arg(long)]
content_type: Option<String>,
/// Set, request, or clear a flag using Bugzilla flag syntax.
///
/// Repeatable. Accepted forms:
/// `name+` (granted), `name-` (denied), `name?` (request),
/// `name?(user@example.com)` (request a specific user), or
/// `name?,!` to clear an existing flag.
#[arg(long)]
flag: Vec<String>,
},
/// Update an existing attachment's metadata or flags.
///
/// Modifies metadata only -- the attachment's file content
/// itself cannot be replaced via the REST API. Pass any of the
/// flags to change that property: `--summary`, `--file-name`,
/// `--content-type`, `--obsolete`, `--is-patch`, `--is-private`,
/// or `--flag`. Boolean flags accept `true` or `false` and are
/// only applied when explicitly supplied.
///
/// `--flag` uses Bugzilla flag syntax (see bzr-attachment-upload(1));
/// pass `name?,!` to clear an existing flag.
///
/// Examples:
///
/// bzr attachment update 9876 --obsolete true
/// bzr attachment update 9876 --summary "Updated patch v2"
/// bzr attachment update 9876 --flag 'review+'
///
/// See bzr-attachment-upload(1) to attach a new file in place
/// of an obsoleted one.
#[command(verbatim_doc_comment)]
Update {
/// Attachment ID
id: u64,
/// New summary
#[arg(long)]
summary: Option<String>,
/// New file name
#[arg(long)]
file_name: Option<String>,
/// New content type
#[arg(long)]
content_type: Option<String>,
/// Mark as obsolete (`true`) or un-obsolete (`false`).
///
/// Only applied when explicitly supplied; an unset value
/// leaves the flag unchanged. Mark a patch obsolete when
/// uploading a replacement to keep the bug's attachment
/// list tidy.
#[arg(long)]
obsolete: Option<bool>,
/// Mark as a patch (`true`) or non-patch (`false`).
///
/// Only applied when explicitly supplied. The patch flag
/// affects diff rendering in the Bugzilla web UI but is
/// otherwise informational.
#[arg(long)]
is_patch: Option<bool>,
/// Mark as private (`true`) or public (`false`).
///
/// Only applied when explicitly supplied. Private
/// attachments are visible only to users in the bug's
/// `insider` group (server-configured); use carefully.
#[arg(long)]
is_private: Option<bool>,
/// Set, request, or clear a flag using Bugzilla flag syntax.
///
/// Repeatable. Accepted forms:
/// `name+` (granted), `name-` (denied), `name?` (request),
/// `name?(user@example.com)` (request a specific user), or
/// `name?,!` to clear an existing flag.
#[arg(long)]
flag: Vec<String>,
},
}