Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bin/cargo/commands/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub fn cli() -> App {
.arg_target_dir()
.arg_release("Whether or not to clean release artifacts")
.arg_doc("Whether or not to clean just the documentation directory")
.arg(opt("no-deps", "Don't clean dependency artifacts"))
.after_help(
"\
If the `--package` argument is given, then SPEC is a package ID specification
Expand All @@ -30,6 +31,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
target: args.target(),
release: args.is_present("release"),
doc: args.is_present("doc"),
no_deps: args.is_present("no-deps"),
};
ops::clean(&ws, &opts)?;
Ok(())
Expand Down
30 changes: 21 additions & 9 deletions src/cargo/ops/cargo_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub struct CleanOptions<'a> {
pub release: bool,
/// Whether to just clean the doc directory
pub doc: bool,
/// Don't clean dependency artifacts
pub no_deps: bool,
}

/// Cleans the package's build artifacts.
Expand All @@ -39,14 +41,24 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
target_dir = target_dir.join("release");
}

// If we have a spec, then we need to delete some packages, otherwise, just
// remove the whole target directory and be done with it!
//
// Note that we don't bother grabbing a lock here as we're just going to
// blow it all away anyway.
if opts.spec.is_empty() {
return rm_rf(&target_dir.into_path_unlocked(), config);
}
let package_names = match (opts.spec.is_empty(), opts.no_deps) {
(true, false) => {
// If we have a spec, then we need to delete some packages, but in this
// case we remove the whole target directory and be done with it!
//
// Note that we don't bother grabbing a lock here as we're just going to
// blow it all away anyway.
return rm_rf(&target_dir.into_path_unlocked(), config);
}
(true, true) => {
// Only clean workspace members when `no_deps` is specified.
ws.members().map(|pkg| pkg.name().to_string()).collect()
}
(false, _) => {
// Otherwise, `no_deps` doesn't apply when package names are explicitly defined.
opts.spec.clone()
}
};

let (packages, resolve) = ops::resolve_ws(ws)?;

Expand All @@ -66,7 +78,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
)?;
let mut units = Vec::new();

for spec in opts.spec.iter() {
for spec in package_names.iter() {
// Translate the spec to a Package
let pkgid = resolve.query(spec)?;
let pkg = packages.get_one(pkgid)?;
Expand Down
48 changes: 48 additions & 0 deletions tests/testsuite/clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,51 @@ fn clean_remove_rlib_rmeta() {
assert!(!p.target_debug_dir().join("libfoo.rlib").exists());
assert!(!rmeta.exists());
}

#[cargo_test]
fn clean_no_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []

[dependencies.d1]
path = "d1"
[dependencies.d2]
path = "d2"

[[bin]]
name = "foo"
"#,
)
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
.file("d1/Cargo.toml", &basic_bin_manifest("d1"))
.file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
.file("d2/Cargo.toml", &basic_bin_manifest("d2"))
.file("d2/src/main.rs", "fn main() { println!(\"d2\"); }")
.build();

p.cargo("build -p d1 -p d2 -p foo").run();

let d1_path = &p
.build_dir()
.join("debug")
.join(format!("d1{}", env::consts::EXE_SUFFIX));
let d2_path = &p
.build_dir()
.join("debug")
.join(format!("d2{}", env::consts::EXE_SUFFIX));

assert!(p.bin("foo").is_file());
assert!(d1_path.is_file(), "{:?}", d1_path);
assert!(d2_path.is_file());

p.cargo("clean --no-deps").cwd("src").with_stdout("").run();
assert!(!p.bin("foo").is_file());
assert!(d1_path.is_file());
assert!(d2_path.is_file());
}