Skip to content

Commit

Permalink
Fix excluding target dirs from backups on OSX
Browse files Browse the repository at this point in the history
This fixes an accidental regression from #6880 identified in #7189 by
moving where the configuration of backup preferences happens since it
was accidentally never happening due to the folder always having been
created.
  • Loading branch information
alexcrichton committed Jul 30, 2019
1 parent 1f74bdf commit 643b660
Showing 1 changed file with 37 additions and 34 deletions.
71 changes: 37 additions & 34 deletions src/cargo/core/compiler/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ impl Layout {
///
/// This function will block if the directory is already locked.
pub fn at(config: &Config, root: Filesystem) -> CargoResult<Layout> {
// If the root directory doesn't already exist go ahead and create it
// here. Use this opportunity to exclude it from backups as well if the
// system supports it since this is a freshly created folder.
if !root.as_path_unlocked().exists() {
root.create_dir()?;
exclude_from_backups(root.as_path_unlocked());
}

// For now we don't do any more finer-grained locking on the artifact
// directory, so just lock the entire thing for the duration of this
// compile.
Expand All @@ -127,42 +135,8 @@ impl Layout {
})
}

#[cfg(not(target_os = "macos"))]
fn exclude_from_backups(&self, _: &Path) {}

#[cfg(target_os = "macos")]
/// Marks files or directories as excluded from Time Machine on macOS
///
/// This is recommended to prevent derived/temporary files from bloating backups.
fn exclude_from_backups(&self, path: &Path) {
use core_foundation::base::TCFType;
use core_foundation::{number, string, url};
use std::ptr;

// For compatibility with 10.7 a string is used instead of global kCFURLIsExcludedFromBackupKey
let is_excluded_key: Result<string::CFString, _> = "NSURLIsExcludedFromBackupKey".parse();
let path = url::CFURL::from_path(path, false);
if let (Some(path), Ok(is_excluded_key)) = (path, is_excluded_key) {
unsafe {
url::CFURLSetResourcePropertyForKey(
path.as_concrete_TypeRef(),
is_excluded_key.as_concrete_TypeRef(),
number::kCFBooleanTrue as *const _,
ptr::null_mut(),
);
}
}
// Errors are ignored, since it's an optional feature and failure
// doesn't prevent Cargo from working
}

/// Makes sure all directories stored in the Layout exist on the filesystem.
pub fn prepare(&mut self) -> io::Result<()> {
if fs::metadata(&self.root).is_err() {
fs::create_dir_all(&self.root)?;
self.exclude_from_backups(&self.root);
}

mkdir(&self.deps)?;
mkdir(&self.native)?;
mkdir(&self.incremental)?;
Expand Down Expand Up @@ -209,3 +183,32 @@ impl Layout {
&self.build
}
}

#[cfg(not(target_os = "macos"))]
fn exclude_from_backups(_: &Path) {}

#[cfg(target_os = "macos")]
/// Marks files or directories as excluded from Time Machine on macOS
///
/// This is recommended to prevent derived/temporary files from bloating backups.
fn exclude_from_backups(path: &Path) {
use core_foundation::base::TCFType;
use core_foundation::{number, string, url};
use std::ptr;

// For compatibility with 10.7 a string is used instead of global kCFURLIsExcludedFromBackupKey
let is_excluded_key: Result<string::CFString, _> = "NSURLIsExcludedFromBackupKey".parse();
let path = url::CFURL::from_path(path, false);
if let (Some(path), Ok(is_excluded_key)) = (path, is_excluded_key) {
unsafe {
url::CFURLSetResourcePropertyForKey(
path.as_concrete_TypeRef(),
is_excluded_key.as_concrete_TypeRef(),
number::kCFBooleanTrue as *const _,
ptr::null_mut(),
);
}
}
// Errors are ignored, since it's an optional feature and failure
// doesn't prevent Cargo from working
}

0 comments on commit 643b660

Please sign in to comment.