Skip to content

Commit 2782ff7

Browse files
committed
Add --clean-per-run flag
1 parent d376f14 commit 2782ff7

File tree

3 files changed

+76
-65
lines changed

3 files changed

+76
-65
lines changed

src/cli.rs

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ const HELP: &[(&str, &str, &str, &[&str])] = &[
5454
"Skip passing --features flag to `cargo` if that feature does not exist in the package",
5555
&[],
5656
),
57+
("", "--clean-per-run", "Remove artifacts for that package before running the command", &[
58+
"If used this flag with --workspace, --each-feature, or --feature-powerset, artifacts will be removed before each run."
59+
]),
5760
("-v", "--verbose", "Use verbose output", &["This flag will be propagated to cargo."]),
5861
("", "--color <WHEN>", "Coloring: auto, always, never", &[
5962
"This flag will be propagated to cargo.",
@@ -184,6 +187,8 @@ pub(crate) struct Args {
184187
pub(crate) optional_deps: bool,
185188
/// --skip-no-default-features
186189
pub(crate) skip_no_default_features: bool,
190+
/// --clean-per-run
191+
pub(crate) clean_per_run: bool,
187192

188193
// flags that will be propagated to cargo
189194
/// --features <FEATURES>...
@@ -264,6 +269,7 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
264269
let mut ignore_non_exist_features = false;
265270
let mut optional_deps = false;
266271
let mut skip_no_default_features = false;
272+
let mut clean_per_run = false;
267273

268274
let res = (|| -> Result<()> {
269275
while let Some(arg) = args.next() {
@@ -284,31 +290,31 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
284290
continue;
285291
}
286292

287-
macro_rules! parse_arg1 {
288-
($ident:ident, $propagate:expr, $pat:expr, $help:expr) => {
293+
macro_rules! parse_opt {
294+
($opt:ident, $propagate:expr, $pat:expr, $help:expr) => {
289295
if arg == $pat {
290-
if $ident.is_some() {
296+
if $opt.is_some() {
291297
return Err(multi_arg($help, subcommand.as_ref()));
292298
}
293299
let next =
294300
args.next().ok_or_else(|| req_arg($help, subcommand.as_ref()))?;
295301
if $propagate {
296-
$ident = Some(next.clone());
302+
$opt = Some(next.clone());
297303
leading.push(arg);
298304
leading.push(next);
299305
} else {
300-
$ident = Some(next);
306+
$opt = Some(next);
301307
}
302308
continue;
303309
} else if arg.starts_with(concat!($pat, "=")) {
304-
if $ident.is_some() {
310+
if $opt.is_some() {
305311
return Err(multi_arg($help, subcommand.as_ref()));
306312
}
307313
let next = arg
308314
.splitn(2, '=')
309315
.nth(1)
310316
.ok_or_else(|| req_arg($help, subcommand.as_ref()))?;
311-
$ident = Some(next.to_string());
317+
$opt = Some(next.to_string());
312318
if $propagate {
313319
leading.push(arg);
314320
}
@@ -317,18 +323,18 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
317323
};
318324
}
319325

320-
macro_rules! parse_arg2 {
321-
($ident:ident, $allow_split:expr, $pat:expr, $help:expr) => {
326+
macro_rules! parse_multi_opt {
327+
($v:ident, $allow_split:expr, $pat:expr, $help:expr) => {
322328
if arg == $pat {
323329
let arg = args.next().ok_or_else(|| req_arg($help, subcommand.as_ref()))?;
324330
if $allow_split {
325331
if arg.contains(',') {
326-
$ident.extend(arg.split(',').map(ToString::to_string));
332+
$v.extend(arg.split(',').map(ToString::to_string));
327333
} else {
328-
$ident.extend(arg.split(' ').map(ToString::to_string));
334+
$v.extend(arg.split(' ').map(ToString::to_string));
329335
}
330336
} else {
331-
$ident.push(arg);
337+
$v.push(arg);
332338
}
333339
continue;
334340
} else if arg.starts_with(concat!($pat, "=")) {
@@ -343,68 +349,49 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
343349
arg = &arg[1..arg.len() - 1];
344350
}
345351
if arg.contains(',') {
346-
$ident.extend(arg.split(',').map(ToString::to_string));
352+
$v.extend(arg.split(',').map(ToString::to_string));
347353
} else {
348-
$ident.extend(arg.split(' ').map(ToString::to_string));
354+
$v.extend(arg.split(' ').map(ToString::to_string));
349355
}
350356
} else {
351-
$ident.push(arg.to_string());
357+
$v.push(arg.to_string());
352358
}
353359
continue;
354360
}
355361
};
356362
}
357363

358-
parse_arg1!(manifest_path, false, "--manifest-path", "--manifest-path <PATH>");
359-
parse_arg1!(color, true, "--color", "--color <WHEN>");
364+
macro_rules! parse_flag {
365+
($flag:ident) => {
366+
if mem::replace(&mut $flag, true) {
367+
return Err(multi_arg(&arg, subcommand.as_ref()));
368+
}
369+
};
370+
}
371+
372+
parse_opt!(manifest_path, false, "--manifest-path", "--manifest-path <PATH>");
373+
parse_opt!(color, true, "--color", "--color <WHEN>");
360374

361-
parse_arg2!(package, false, "--package", "--package <SPEC>");
362-
parse_arg2!(package, false, "-p", "--package <SPEC>");
363-
parse_arg2!(exclude, false, "--exclude", "--exclude <SPEC>");
364-
parse_arg2!(features, true, "--features", "--features <FEATURES>");
365-
parse_arg2!(skip, true, "--skip", "--skip <FEATURES>");
375+
parse_multi_opt!(package, false, "--package", "--package <SPEC>");
376+
parse_multi_opt!(package, false, "-p", "--package <SPEC>");
377+
parse_multi_opt!(exclude, false, "--exclude", "--exclude <SPEC>");
378+
parse_multi_opt!(features, true, "--features", "--features <FEATURES>");
379+
parse_multi_opt!(skip, true, "--skip", "--skip <FEATURES>");
366380

367381
match arg.as_str() {
368382
"--workspace" | "--all" => {
369383
if let Some(arg) = workspace.replace(arg) {
370384
return Err(multi_arg(&arg, subcommand.as_ref()));
371385
}
372386
}
373-
"--no-dev-deps" => {
374-
if mem::replace(&mut no_dev_deps, true) {
375-
return Err(multi_arg(&arg, subcommand.as_ref()));
376-
}
377-
}
378-
"--remove-dev-deps" => {
379-
if mem::replace(&mut remove_dev_deps, true) {
380-
return Err(multi_arg(&arg, subcommand.as_ref()));
381-
}
382-
}
383-
"--each-feature" => {
384-
if mem::replace(&mut each_feature, true) {
385-
return Err(multi_arg(&arg, subcommand.as_ref()));
386-
}
387-
}
388-
"--feature-powerset" => {
389-
if mem::replace(&mut feature_powerset, true) {
390-
return Err(multi_arg(&arg, subcommand.as_ref()));
391-
}
392-
}
393-
"--ignore-private" => {
394-
if mem::replace(&mut ignore_private, true) {
395-
return Err(multi_arg(&arg, subcommand.as_ref()));
396-
}
397-
}
398-
"--optional-deps" => {
399-
if mem::replace(&mut optional_deps, true) {
400-
return Err(multi_arg(&arg, subcommand.as_ref()));
401-
}
402-
}
403-
"--skip-no-default-features" => {
404-
if mem::replace(&mut skip_no_default_features, true) {
405-
return Err(multi_arg(&arg, subcommand.as_ref()));
406-
}
407-
}
387+
"--no-dev-deps" => parse_flag!(no_dev_deps),
388+
"--remove-dev-deps" => parse_flag!(remove_dev_deps),
389+
"--each-feature" => parse_flag!(each_feature),
390+
"--feature-powerset" => parse_flag!(feature_powerset),
391+
"--ignore-private" => parse_flag!(ignore_private),
392+
"--optional-deps" => parse_flag!(optional_deps),
393+
"--skip-no-default-features" => parse_flag!(skip_no_default_features),
394+
"--clean-per-run" => parse_flag!(clean_per_run),
408395
"--ignore-unknown-features" => {
409396
if ignore_unknown_features || ignore_non_exist_features {
410397
return Err(multi_arg(&arg, subcommand.as_ref()));
@@ -426,6 +413,7 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
426413

427414
let color = color.map(|c| c.parse()).transpose()?;
428415
*coloring = color;
416+
let verbose = leading.iter().any(|a| a == "--verbose" || a == "-v" || a == "-vv");
429417

430418
res?;
431419

@@ -489,7 +477,7 @@ pub(crate) fn args(coloring: &mut Option<Coloring>) -> Result<Option<Args>> {
489477

490478
if subcommand.is_none() {
491479
if leading.iter().any(|a| a == "--list") {
492-
let mut line = ProcessBuilder::new(crate::cargo_binary());
480+
let mut line = ProcessBuilder::new(crate::cargo_binary(), verbose);
493481
line.arg("--list");
494482
line.exec()?;
495483
return Ok(None);
@@ -508,7 +496,6 @@ For more information try --help
508496
}
509497
}
510498

511-
let verbose = leading.iter().any(|a| a == "--verbose" || a == "-v" || a == "-vv");
512499
if ignore_non_exist_features {
513500
warn!(
514501
color,
@@ -542,6 +529,7 @@ For more information try --help
542529
ignore_unknown_features: ignore_unknown_features || ignore_non_exist_features,
543530
optional_deps,
544531
skip_no_default_features,
532+
clean_per_run,
545533

546534
features,
547535
color,

src/package.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{fmt::Write, ops::Deref};
1+
use std::{ffi::OsStr, fmt::Write, ops::Deref};
22

33
use crate::{metadata, Args, Info, Manifest, ProcessBuilder, Result};
44

@@ -189,6 +189,10 @@ fn exec_cargo(
189189
) -> Result<()> {
190190
info.count += 1;
191191

192+
if args.clean_per_run {
193+
cargo_clean(line.get_program(), args, package)?;
194+
}
195+
192196
// running `<command>` on <package> (<count>/<total>)
193197
let mut msg = String::new();
194198
write!(msg, "running {} on {}", line, &package.name).unwrap();
@@ -200,6 +204,20 @@ fn exec_cargo(
200204
line.exec()
201205
}
202206

207+
fn cargo_clean(cargo: &OsStr, args: &Args, package: &Package<'_>) -> Result<()> {
208+
let mut line = ProcessBuilder::new(cargo, args.verbose);
209+
line.arg("clean");
210+
line.arg("--package");
211+
line.arg(&package.name);
212+
213+
if args.verbose {
214+
// running `cargo clean --package <package>`
215+
info!(args.color, "running {}", line);
216+
}
217+
218+
line.exec()
219+
}
220+
203221
fn powerset<T: Clone>(iter: impl IntoIterator<Item = T>) -> Vec<Vec<T>> {
204222
iter.into_iter().fold(vec![vec![]], |mut acc, elem| {
205223
let ext = acc.clone().into_iter().map(|mut curr| {

src/process.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,21 @@ pub(crate) struct ProcessBuilder {
3333

3434
impl ProcessBuilder {
3535
/// Creates a new `ProcessBuilder`.
36-
pub(crate) fn new(program: OsString) -> Self {
36+
pub(crate) fn new(program: impl Into<Rc<OsStr>>, verbose: bool) -> Self {
3737
Self {
38-
program: Rc::from(program),
38+
program: program.into(),
3939
leading_args: Rc::from(&[][..]),
4040
trailing_args: Rc::from(&[][..]),
4141
args: Vec::new(),
4242
features: String::new(),
43-
verbose: false,
43+
verbose,
4444
}
4545
}
4646

4747
/// Creates a new `ProcessBuilder` from `Args`.
48-
pub(crate) fn from_args(program: OsString, args: &Args) -> Self {
48+
pub(crate) fn from_args(program: impl Into<Rc<OsStr>>, args: &Args) -> Self {
4949
Self {
50-
program: Rc::from(program),
50+
program: program.into(),
5151
leading_args: args.leading_args.clone(),
5252
trailing_args: args.trailing_args.clone(),
5353
args: Vec::new(),
@@ -107,6 +107,11 @@ impl ProcessBuilder {
107107
// self
108108
// }
109109

110+
/// Gets the executable name.
111+
pub(crate) fn get_program(&self) -> &OsStr {
112+
&self.program
113+
}
114+
110115
/// Runs the process, waiting for completion, and mapping non-success exit codes to an error.
111116
pub(crate) fn exec(&self) -> Result<()> {
112117
let mut command = self.build_command();

0 commit comments

Comments
 (0)