]>
Commit | Line | Data |
---|---|---|
a7813a04 XL |
1 | //! Implementation of `make clean` in rustbuild. |
2 | //! | |
3 | //! Responsible for cleaning out a build directory of all old and stale | |
4 | //! artifacts to prepare for a fresh build. Currently doesn't remove the | |
5 | //! `build/cache` directory (download cache) or the `build/$target/llvm` | |
9fa01778 | 6 | //! directory unless the `--all` flag is present. |
a7813a04 | 7 | |
7453a54e | 8 | use std::fs; |
c30ab7b3 | 9 | use std::io::{self, ErrorKind}; |
7453a54e SL |
10 | use std::path::Path; |
11 | ||
0731742a | 12 | use crate::Build; |
7453a54e | 13 | |
ea8adc8c | 14 | pub fn clean(build: &Build, all: bool) { |
cc61c64b | 15 | rm_rf("tmp".as_ref()); |
ea8adc8c XL |
16 | |
17 | if all { | |
18 | rm_rf(&build.out); | |
19 | } else { | |
20 | rm_rf(&build.out.join("tmp")); | |
21 | rm_rf(&build.out.join("dist")); | |
22 | ||
23 | for host in &build.hosts { | |
24 | let entries = match build.out.join(host).read_dir() { | |
25 | Ok(iter) => iter, | |
26 | Err(_) => continue, | |
27 | }; | |
28 | ||
29 | for entry in entries { | |
30 | let entry = t!(entry); | |
31 | if entry.file_name().to_str() == Some("llvm") { | |
32 | continue | |
33 | } | |
34 | let path = t!(entry.path().canonicalize()); | |
35 | rm_rf(&path); | |
c30ab7b3 | 36 | } |
c30ab7b3 SL |
37 | } |
38 | } | |
39 | } | |
7453a54e | 40 | |
cc61c64b XL |
41 | fn rm_rf(path: &Path) { |
42 | match path.symlink_metadata() { | |
43 | Err(e) => { | |
44 | if e.kind() == ErrorKind::NotFound { | |
45 | return; | |
46 | } | |
47 | panic!("failed to get metadata for file {}: {}", path.display(), e); | |
48 | }, | |
49 | Ok(metadata) => { | |
50 | if metadata.file_type().is_file() || metadata.file_type().is_symlink() { | |
51 | do_op(path, "remove file", |p| fs::remove_file(p)); | |
52 | return; | |
53 | } | |
c30ab7b3 | 54 | |
cc61c64b XL |
55 | for file in t!(fs::read_dir(path)) { |
56 | rm_rf(&t!(file).path()); | |
57 | } | |
58 | do_op(path, "remove dir", |p| fs::remove_dir(p)); | |
59 | }, | |
60 | }; | |
7453a54e SL |
61 | } |
62 | ||
c30ab7b3 SL |
63 | fn do_op<F>(path: &Path, desc: &str, mut f: F) |
64 | where F: FnMut(&Path) -> io::Result<()> | |
65 | { | |
66 | match f(path) { | |
67 | Ok(()) => {} | |
cc61c64b XL |
68 | // On windows we can't remove a readonly file, and git will often clone files as readonly. |
69 | // As a result, we have some special logic to remove readonly files on windows. | |
70 | // This is also the reason that we can't use things like fs::remove_dir_all(). | |
c30ab7b3 SL |
71 | Err(ref e) if cfg!(windows) && |
72 | e.kind() == ErrorKind::PermissionDenied => { | |
cc61c64b | 73 | let mut p = t!(path.symlink_metadata()).permissions(); |
c30ab7b3 SL |
74 | p.set_readonly(false); |
75 | t!(fs::set_permissions(path, p)); | |
76 | f(path).unwrap_or_else(|e| { | |
77 | panic!("failed to {} {}: {}", desc, path.display(), e); | |
78 | }) | |
79 | } | |
80 | Err(e) => { | |
81 | panic!("failed to {} {}: {}", desc, path.display(), e); | |
82 | } | |
7453a54e SL |
83 | } |
84 | } |