]> git.proxmox.com Git - cargo.git/blame - src/cargo/ops/cargo_clean.rs
Implement overrides via local cargo configuration
[cargo.git] / src / cargo / ops / cargo_clean.rs
CommitLineData
63915360 1use std::collections::HashMap;
325c5f2d 2use std::io::fs::{mod, PathExtensions};
3f110840 3
325c5f2d
AC
4use core::{MultiShell, PackageSet};
5use core::source::{Source, SourceMap};
3f110840 6use sources::PathSource;
325c5f2d
AC
7use util::{CargoResult, human, ChainError, Config};
8use ops::{mod, Layout, Context};
0025dbde 9
325c5f2d
AC
10pub struct CleanOptions<'a> {
11 pub spec: Option<&'a str>,
12 pub target: Option<&'a str>,
bdb49668 13 pub shell: &'a mut MultiShell,
325c5f2d 14}
dd2459cd 15
325c5f2d
AC
16/// Cleans the project from build artifacts.
17pub fn clean(manifest_path: &Path, opts: &mut CleanOptions) -> CargoResult<()> {
e2191677 18 let mut src = try!(PathSource::for_path(&manifest_path.dir_path()));
3f110840
AC
19 try!(src.update());
20 let root = try!(src.get_root_package());
21 let manifest = root.get_manifest();
dd2459cd 22
325c5f2d
AC
23 // If we have a spec, then we need to delete some package,s otherwise, just
24 // remove the whole target directory and be done with it!
25 let spec = match opts.spec {
26 Some(spec) => spec,
27 None => return rm_rf(manifest.get_target_dir()),
28 };
29
30 // Load the lockfile (if one's available), and resolve spec to a pkgid
31 let lockfile = root.get_root().join("Cargo.lock");
32 let source_id = root.get_package_id().get_source_id();
33 let resolve = match try!(ops::load_lockfile(&lockfile, source_id)) {
34 Some(resolve) => resolve,
35 None => return Err(human("A Cargo.lock must exist before cleaning"))
36 };
37 let pkgid = try!(resolve.query(spec));
38
39 // Translate the PackageId to a Package
40 let mut cfg = try!(Config::new(opts.shell, None, None));
41 let pkg = {
42 let mut source = pkgid.get_source_id().load(&mut cfg);
43 try!(source.update());
44 (try!(source.get([pkgid.clone()]))).into_iter().next().unwrap()
45 };
3f110840 46
325c5f2d
AC
47 // Create a compilation context to have access to information like target
48 // filenames and such
49 let srcs = SourceMap::new();
50 let pkgs = PackageSet::new([]);
51 let cx = try!(Context::new("compile", &resolve, &srcs, &pkgs, &mut cfg,
52 Layout::at(root.get_absolute_target_dir()),
63915360 53 None, &pkg, HashMap::new()));
325c5f2d
AC
54
55 // And finally, clean everything out!
56 for target in pkg.get_targets().iter() {
57 let layout = Layout::new(&root, opts.target,
58 target.get_profile().get_dest());
59 try!(rm_rf(&layout.native(&pkg)));
60 try!(rm_rf(&layout.fingerprint(&pkg)));
61 for filename in try!(cx.target_filenames(target)).iter() {
62 let filename = filename.as_slice();
63 try!(rm_rf(&layout.dest().join(filename)));
64 try!(rm_rf(&layout.deps().join(filename)));
65 }
3f110840
AC
66 }
67
68 Ok(())
0025dbde 69}
325c5f2d
AC
70
71fn rm_rf(path: &Path) -> CargoResult<()> {
72 if path.is_dir() {
73 try!(fs::rmdir_recursive(path).chain_error(|| {
74 human("could not remove build directory")
75 }));
76 } else if path.exists() {
77 try!(fs::unlink(path).chain_error(|| {
78 human("failed to remove build artifact")
79 }));
80 }
81 Ok(())
82}