pub fn work_products(&self) -> Ref<FxHashMap<Arc<WorkProductId>, WorkProduct>> {
self.data.work_products.borrow()
}
+
+ /// Access the map of work-products created during the cached run. Only
+ /// used during saving of the dep-graph.
+ pub fn previous_work_products(&self) -> Ref<FxHashMap<Arc<WorkProductId>, WorkProduct>> {
+ self.data.previous_work_products.borrow()
+ }
}
/// A "work product" is an intermediate result that we save into the
pub use persist::save_work_products;
pub use persist::in_incr_comp_dir;
pub use persist::finalize_session_directory;
+pub use persist::delete_workproduct_files;
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_serialize::Decodable as RustcDecodable;
use rustc_serialize::opaque::Decoder;
-use std::fs;
use std::path::{Path};
use IncrementalHashesMap;
use super::hash::*;
use super::fs::*;
use super::file_format;
+use super::work_product;
pub type DirtyNodes = FxHashSet<DepNode<DefPathIndex>>;
fn delete_dirty_work_product(tcx: TyCtxt,
swp: SerializedWorkProduct) {
debug!("delete_dirty_work_product({:?})", swp);
- for &(_, ref file_name) in &swp.work_product.saved_files {
- let path = in_incr_comp_dir_sess(tcx.sess, file_name);
- match fs::remove_file(&path) {
- Ok(()) => { }
- Err(err) => {
- tcx.sess.warn(
- &format!("file-system error deleting outdated file `{}`: {}",
- path.display(), err));
- }
- }
- }
+ work_product::delete_workproduct_files(tcx.sess, &swp.work_product);
}
fn load_prev_metadata_hashes(tcx: TyCtxt,
pub use self::save::save_dep_graph;
pub use self::save::save_work_products;
pub use self::work_product::save_trans_partition;
+pub use self::work_product::delete_workproduct_files;
use super::fs::*;
use super::dirty_clean;
use super::file_format;
+use super::work_product;
use calculate_svh::IchHasher;
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let _ignore = sess.dep_graph.in_ignore();
let path = work_products_path(sess);
save_in(sess, path, |e| encode_work_products(sess, e));
+
+ // We also need to clean out old work-products, as not all of them are
+ // deleted during invalidation. Some object files don't change their
+ // content, they are just not needed anymore.
+ let new_work_products = sess.dep_graph.work_products();
+ let previous_work_products = sess.dep_graph.previous_work_products();
+
+ for (id, wp) in previous_work_products.iter() {
+ if !new_work_products.contains_key(id) {
+ work_product::delete_workproduct_files(sess, wp);
+ debug_assert!(wp.saved_files.iter().all(|&(_, ref file_name)| {
+ !in_incr_comp_dir_sess(sess, file_name).exists()
+ }));
+ }
+ }
+
+ // Check that we did not delete one of the current work-products:
+ debug_assert!({
+ new_work_products.iter()
+ .flat_map(|(_, wp)| wp.saved_files
+ .iter()
+ .map(|&(_, ref name)| name))
+ .map(|name| in_incr_comp_dir_sess(sess, name))
+ .all(|path| path.exists())
+ });
}
fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
use rustc::util::fs::link_or_copy;
use std::path::PathBuf;
use std::sync::Arc;
+use std::fs as std_fs;
pub fn save_trans_partition(sess: &Session,
cgu_name: &str,
sess.dep_graph.insert_work_product(&work_product_id, work_product);
}
+
+pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
+ for &(_, ref file_name) in &work_product.saved_files {
+ let path = in_incr_comp_dir_sess(sess, file_name);
+ match std_fs::remove_file(&path) {
+ Ok(()) => { }
+ Err(err) => {
+ sess.warn(
+ &format!("file-system error deleting outdated file `{}`: {}",
+ path.display(), err));
+ }
+ }
+ }
+}