diff --git a/src/bin/clean.rs b/src/bin/clean.rs index 8aea04d35a7..607f8f1236a 100644 --- a/src/bin/clean.rs +++ b/src/bin/clean.rs @@ -12,6 +12,7 @@ struct Options { flag_verbose: bool, flag_quiet: bool, flag_color: Option, + flag_release: bool, } pub const USAGE: &'static str = " @@ -25,6 +26,7 @@ Options: -p SPEC, --package SPEC ... Package to clean artifacts for --manifest-path PATH Path to the manifest to the package to clean --target TRIPLE Target triple to clean output for (default all) + --release Whether or not to clean release artifacts -v, --verbose Use verbose output -q, --quiet No output printed to stdout --color WHEN Coloring: auto, always, never @@ -45,6 +47,7 @@ pub fn execute(options: Options, config: &Config) -> CliResult> { config: config, spec: &options.flag_package, target: options.flag_target.as_ref().map(|s| &s[..]), + release: options.flag_release, }; ops::clean(&root, &opts).map(|_| None).map_err(|err| { CliError::from_boxed(err, 101) diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 7cf9fde0f2a..cf588ae2837 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -3,8 +3,9 @@ use std::fs; use std::io::prelude::*; use std::path::Path; -use core::{Package, PackageSet, Profiles, Profile}; +use core::{Package, PackageSet, Profiles}; use core::source::{Source, SourceMap}; +use core::registry::PackageRegistry; use util::{CargoResult, human, ChainError, Config}; use ops::{self, Layout, Context, BuildConfig, Kind, Unit}; @@ -12,6 +13,7 @@ pub struct CleanOptions<'a> { pub spec: &'a [String], pub target: Option<&'a str>, pub config: &'a Config, + pub release: bool, } /// Cleans the project from build artifacts. @@ -37,11 +39,19 @@ pub fn clean(manifest_path: &Path, opts: &CleanOptions) -> CargoResult<()> { // filenames and such let srcs = SourceMap::new(); let pkgs = PackageSet::new(&[]); - let profiles = Profiles::default(); + + let dest = if opts.release {"release"} else {"debug"}; + let host_layout = Layout::new(opts.config, &root, None, dest); + let target_layout = opts.target.map(|target| { + Layout::new(opts.config, &root, Some(target), dest) + }); + let cx = try!(Context::new(&resolve, &srcs, &pkgs, opts.config, - Layout::at(target_dir), - None, BuildConfig::default(), - &profiles)); + host_layout, target_layout, + BuildConfig::default(), + root.manifest().profiles())); + + let mut registry = PackageRegistry::new(opts.config); // resolve package specs and remove the corresponding packages for spec in opts.spec { @@ -49,27 +59,31 @@ pub fn clean(manifest_path: &Path, opts: &CleanOptions) -> CargoResult<()> { // Translate the PackageId to a Package let pkg = { - let mut source = pkgid.source_id().load(opts.config); - try!(source.update()); - (try!(source.get(&[pkgid.clone()]))).into_iter().next().unwrap() + try!(registry.add_sources(&[pkgid.source_id().clone()])); + (try!(registry.get(&[pkgid.clone()]))).into_iter().next().unwrap() }; // And finally, clean everything out! - for target in pkg.targets().iter() { - // TODO: `cargo clean --release` - let layout = Layout::new(opts.config, &root, opts.target, "debug"); - try!(rm_rf(&layout.fingerprint(&pkg))); - let profiles = [Profile::default_dev(), Profile::default_test()]; - for profile in profiles.iter() { - let unit = Unit { - pkg: &pkg, - target: target, - profile: profile, - kind: Kind::Target, - }; - for filename in try!(cx.target_filenames(&unit)).iter() { - try!(rm_rf(&layout.dest().join(&filename))); - try!(rm_rf(&layout.deps().join(&filename))); + for target in pkg.targets() { + for kind in [Kind::Host, Kind::Target].iter() { + let layout = cx.layout(&pkg, *kind); + try!(rm_rf(&layout.proxy().fingerprint(&pkg))); + try!(rm_rf(&layout.build(&pkg))); + let Profiles { + ref release, ref dev, ref test, ref bench, ref doc, + ref custom_build, + } = *root.manifest().profiles(); + for profile in [release, dev, test, bench, doc, custom_build].iter() { + let unit = Unit { + pkg: &pkg, + target: target, + profile: profile, + kind: *kind, + }; + let root = cx.out_dir(&unit); + for filename in try!(cx.target_filenames(&unit)).iter() { + try!(rm_rf(&root.join(&filename))); + } } } } diff --git a/tests/test_cargo_clean.rs b/tests/test_cargo_clean.rs index ff3313d9979..b816492e1d4 100644 --- a/tests/test_cargo_clean.rs +++ b/tests/test_cargo_clean.rs @@ -1,6 +1,8 @@ use std::env; -use support::{project, execs, main_file, basic_bin_manifest}; +use support::{git, project, execs, main_file, basic_bin_manifest}; +use support::{COMPILING, RUNNING}; +use support::registry::Package; use hamcrest::{assert_that, existing_dir, existing_file, is_not}; fn setup() { @@ -93,3 +95,135 @@ test!(clean_multiple_packages { assert_that(d1_path, is_not(existing_file())); assert_that(d2_path, is_not(existing_file())); }); + +test!(clean_release { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + a = { path = "a" } + "#) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", r#" + [package] + name = "a" + version = "0.0.1" + authors = [] + "#) + .file("a/src/lib.rs", ""); + p.build(); + + assert_that(p.cargo_process("build").arg("--release"), + execs().with_status(0)); + + assert_that(p.cargo("clean").arg("-p").arg("foo"), + execs().with_status(0)); + assert_that(p.cargo("build").arg("--release"), + execs().with_status(0).with_stdout("")); + + assert_that(p.cargo("clean").arg("-p").arg("foo").arg("--release"), + execs().with_status(0)); + assert_that(p.cargo("build").arg("--release"), + execs().with_status(0).with_stdout(&format!("\ +{compiling} foo v0.0.1 ([..]) +", compiling = COMPILING))); +}); + +test!(build_script { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + build = "build.rs" + "#) + .file("src/main.rs", "fn main() {}") + .file("build.rs", r#" + use std::path::PathBuf; + use std::env; + + fn main() { + let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + if env::var("FIRST").is_ok() { + std::fs::File::create(out.join("out")).unwrap(); + } else { + assert!(!std::fs::metadata(out.join("out")).is_ok()); + } + } + "#) + .file("a/src/lib.rs", ""); + p.build(); + + assert_that(p.cargo_process("build").env("FIRST", "1"), + execs().with_status(0)); + assert_that(p.cargo("clean").arg("-p").arg("foo"), + execs().with_status(0)); + assert_that(p.cargo("build").arg("-v"), + execs().with_status(0).with_stdout(&format!("\ +{compiling} foo v0.0.1 ([..]) +{running} `rustc build.rs [..]` +{running} `[..]build-script-build[..]` +{running} `rustc src[..]main.rs [..]` +", compiling = COMPILING, running = RUNNING))); +}); + +test!(clean_git { + let git = git::new("dep", |project| { + project.file("Cargo.toml", r#" + [project] + name = "dep" + version = "0.5.0" + authors = [] + "#) + .file("src/lib.rs", "") + }).unwrap(); + + let p = project("foo") + .file("Cargo.toml", &format!(r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + dep = {{ git = '{}' }} + "#, git.url())) + .file("src/main.rs", "fn main() {}"); + p.build(); + + assert_that(p.cargo_process("build"), + execs().with_status(0)); + assert_that(p.cargo("clean").arg("-p").arg("dep"), + execs().with_status(0).with_stdout("")); + assert_that(p.cargo("build"), + execs().with_status(0)); +}); + +test!(registry { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + bar = "0.1" + "#) + .file("src/main.rs", "fn main() {}"); + p.build(); + + Package::new("bar", "0.1.0").publish(); + + assert_that(p.cargo_process("build"), + execs().with_status(0)); + assert_that(p.cargo("clean").arg("-p").arg("bar"), + execs().with_status(0).with_stdout("")); + assert_that(p.cargo("build"), + execs().with_status(0)); +});