rust/src/bootstrap/clean.rs

95 lines
3.1 KiB
Rust
Raw Normal View History

// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Implementation of `make clean` in rustbuild.
//!
//! Responsible for cleaning out a build directory of all old and stale
//! artifacts to prepare for a fresh build. Currently doesn't remove the
//! `build/cache` directory (download cache) or the `build/$target/llvm`
//! directory unless the --all flag is present.
use std::fs;
2016-11-04 19:44:53 -05:00
use std::io::{self, ErrorKind};
use std::path::Path;
use Build;
pub fn clean(build: &Build, all: bool) {
rm_rf("tmp".as_ref());
if all {
rm_rf(&build.out);
} else {
rm_rf(&build.out.join("tmp"));
rm_rf(&build.out.join("dist"));
for host in &build.hosts {
let entries = match build.out.join(host).read_dir() {
Ok(iter) => iter,
Err(_) => continue,
};
for entry in entries {
let entry = t!(entry);
if entry.file_name().to_str() == Some("llvm") {
continue
}
let path = t!(entry.path().canonicalize());
rm_rf(&path);
rustbuild: Rewrite user-facing interface This commit is a rewrite of the user-facing interface to the rustbuild build system. The intention here is to make it much easier to compile/test the project without having to remember weird rule names and such. An overall view of the new interface is: # build everything ./x.py build # document everyting ./x.py doc # test everything ./x.py test # test libstd ./x.py test src/libstd # build libcore stage0 ./x.py build src/libcore --stage 0 # run stage1 run-pass tests ./x.py test src/test/run-pass --stage 1 The `src/bootstrap/bootstrap.py` script is now aliased as a top-level `x.py` script. This `x` was chosen to be both short and easily tab-completable (no collisions in that namespace!). The build system now accepts a "subcommand" of what to do next, the main ones being build/doc/test. Each subcommand then receives an optional list of arguments. These arguments are paths in the source repo of what to work with. That is, if you want to test a directory, you just pass that directory as an argument. The purpose of this rewrite is to do away with all of the arcane renames like "rpass" is the "run-pass" suite, "cfail" is the "compile-fail" suite, etc. By simply working with directories and files it's much more intuitive of how to run a test (just pass it as an argument). The rustbuild step/dependency management was also rewritten along the way to make this easy to work with and define, but that's largely just a refactoring of what was there before. The *intention* is that this support is extended for arbitrary files (e.g. `src/test/run-pass/my-test-case.rs`), but that isn't quite implemented just yet. Instead directories work for now but we can follow up with stricter path filtering logic to plumb through all the arguments.
2016-10-21 15:18:09 -05:00
}
}
}
}
fn rm_rf(path: &Path) {
match path.symlink_metadata() {
Err(e) => {
if e.kind() == ErrorKind::NotFound {
return;
}
panic!("failed to get metadata for file {}: {}", path.display(), e);
},
Ok(metadata) => {
if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
do_op(path, "remove file", |p| fs::remove_file(p));
return;
}
2016-11-04 19:44:53 -05:00
for file in t!(fs::read_dir(path)) {
rm_rf(&t!(file).path());
}
do_op(path, "remove dir", |p| fs::remove_dir(p));
},
};
2016-11-04 19:44:53 -05:00
}
fn do_op<F>(path: &Path, desc: &str, mut f: F)
where F: FnMut(&Path) -> io::Result<()>
{
match f(path) {
Ok(()) => {}
// On windows we can't remove a readonly file, and git will often clone files as readonly.
// As a result, we have some special logic to remove readonly files on windows.
// This is also the reason that we can't use things like fs::remove_dir_all().
2016-11-04 19:44:53 -05:00
Err(ref e) if cfg!(windows) &&
e.kind() == ErrorKind::PermissionDenied => {
let mut p = t!(path.symlink_metadata()).permissions();
2016-11-04 19:44:53 -05:00
p.set_readonly(false);
t!(fs::set_permissions(path, p));
f(path).unwrap_or_else(|e| {
panic!("failed to {} {}: {}", desc, path.display(), e);
})
}
Err(e) => {
panic!("failed to {} {}: {}", desc, path.display(), e);
}
}
}