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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
//! The [`Output`] trait that defines all possible outputs of a child process.
use crate::;
use ExitStatus;
/// All possible return types of [`run!`], [`run_output!`] or
/// [`run_result!`] must implement this trait.
/// This return-type polymorphism makes cradle very flexible.
/// For example, if you want to capture what a command writes
/// to `stdout` you can do that using [`StdoutUntrimmed`]:
///
/// ```
/// use cradle::prelude::*;
///
/// let StdoutUntrimmed(output) = run_output!(%"echo foo");
/// assert_eq!(output, "foo\n");
/// ```
///
/// But if instead you want to capture the command's [`ExitStatus`],
/// you can use [`Status`]:
///
/// ```
/// use cradle::prelude::*;
///
/// let Status(exit_status) = run_output!("false");
/// assert_eq!(exit_status.code(), Some(1));
/// ```
///
/// For documentation on what all the possible return types do,
/// see the documentation for the individual impls of [`Output`].
/// Here's a non-exhaustive list of the more commonly used return types to get you started:
///
/// - [`()`]: In case you don't want to capture anything. See also [`run`].
/// - To capture output streams:
/// - [`StdoutTrimmed`]: To capture `stdout`, trimmed of whitespace.
/// - [`StdoutUntrimmed`]: To capture `stdout` untrimmed.
/// - [`Stderr`]: To capture `stderr`.
/// - [`Status`]: To capture the command's [`ExitStatus`].
///
/// Also, [`Output`] is implemented for tuples.
/// You can use this to combine multiple return types that implement [`Output`].
/// The following code for example retrieves the command's [`ExitStatus`]
/// _and_ what it writes to `stdout`:
///
/// ```
/// use cradle::prelude::*;
///
/// let (Status(exit_status), StdoutUntrimmed(stdout)) = run_output!(%"echo foo");
/// assert!(exit_status.success());
/// assert_eq!(stdout, "foo\n");
/// ```
///
/// [`()`]: trait.Output.html#impl-Output-for-()
///
/// ## Custom [`Output`] impls
///
/// It is possible, but not recommended, to write [`Output`] implementations for your
/// own types.
/// The API is inconvenient, under-documented, and easy to misuse,
/// i.e. it is easily possible to provoke [`Internal`](Error::Internal) errors.
///
/// See
/// [Issue 184: Provide a better API for writing custom Output impls](https://github.com/soenkehahn/cradle/issues/184)
/// for more details and discussion.
/// Use this when you don't need any result from the child process.
///
/// ```
/// # let temp_dir = tempfile::TempDir::new().unwrap();
/// # std::env::set_current_dir(&temp_dir).unwrap();
/// use cradle::prelude::*;
///
/// let () = run_output!(%"touch ./foo");
/// ```
///
/// Since [`run_output!`] (and [`run_result`]) use return type polymorphism,
/// you have to make sure the compiler can figure out which return type you want to use.
/// In this example that happens through the `let () =`.
/// So you can't just omit that.
///
/// See also [`run!`] for a more convenient way to use `()` as the return type.
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
tuple_impl!;
/// Returns what the child process writes to `stdout`, interpreted as utf-8,
/// collected into a string, trimmed of leading and trailing whitespace.
/// This also suppresses output of the child's `stdout`
/// to the parent's `stdout`. (Which would be the default when not using [`StdoutTrimmed`]
/// as the return value.)
///
/// It's recommended to pattern-match to get to the inner [`String`].
/// This will make sure that the return type can be inferred.
/// Here's an example:
///
/// ```
/// use std::path::Path;
/// use cradle::prelude::*;
///
/// # #[cfg(unix)]
/// # {
/// let StdoutTrimmed(output) = run_output!(%"which ls");
/// assert!(Path::new(&output).exists());
/// # }
/// ```
;
/// Same as [`StdoutTrimmed`], but does not trim whitespace from the output:
///
/// ```
/// use cradle::prelude::*;
///
/// let StdoutUntrimmed(output) = run_output!(%"echo foo");
/// assert_eq!(output, "foo\n");
/// ```
;
/// [`Stderr`] allows to capture the `stderr` of a child process:
///
/// ```
/// use cradle::prelude::*;
///
/// // (`Status` is used here to suppress panics caused by `ls`
/// // terminating with a non-zero exit code.)
/// let (Stderr(stderr), Status(_)) = run_output!(%"ls does-not-exist");
/// assert!(stderr.contains("No such file or directory"));
/// ```
///
/// This assumes that the output written to `stderr` is encoded
/// as utf-8, and will error otherwise.
///
/// By default, what is written to `stderr` by the child process
/// is relayed to the parent's `stderr`. However, when [`Stderr`]
/// is used, this is switched off.
;
/// Use [`Status`] as the return type for [`run_output!`] to retrieve the
/// [`ExitStatus`] of the child process:
///
/// ```
/// use cradle::prelude::*;
///
/// let Status(exit_status) = run_output!(%"echo foo");
/// assert!(exit_status.success());
/// ```
///
/// Also, when using [`Status`], non-zero exit codes won't
/// result in neither a panic (when used with [`run!`] or
/// [`run_output!`]) nor an [`std::result::Result::Err`]
/// (when used with [`run_result!`]):
///
/// ```
/// use cradle::prelude::*;
///
/// let Status(exit_status) = run_output!("false");
/// assert_eq!(exit_status.code(), Some(1));
/// let result: Result<Status, cradle::Error> = run_result!("false");
/// assert!(result.is_ok());
/// assert_eq!(result.unwrap().0.code(), Some(1));
/// ```
///
/// Also see the
/// [section about error handling](index.html#error-handling) in
/// the module documentation.
;
/// Using [`bool`] as the return type for [`run_output!`] will return `true` if
/// the command returned successfully, and `false` otherwise:
///
/// ```
/// use cradle::prelude::*;
///
/// if !run_output!(%"which cargo") {
/// panic!("Cargo is not installed!");
/// }
/// ```
///
/// Also, when using [`bool`], non-zero exit codes will not result in a panic
/// or [`std::result::Result::Err`]:
///
/// ```
/// use cradle::prelude::*;
///
/// let success: bool = run_output!("false");
/// assert!(!success);
/// let result: Result<bool, cradle::Error> = run_result!("false");
/// assert!(result.is_ok());
/// assert_eq!(result.unwrap(), false);
/// ```
///
/// Also see the
/// [section about error handling](index.html#error-handling) in
/// the module documentation.