When uplifting directories, symlink them instead of hard-link them.

Fixes #4671.
This commit is contained in:
kennytm 2017-10-29 03:47:29 +08:00
parent cee38cd30d
commit 2c6a0fe104
No known key found for this signature in database
GPG Key ID: FEF6C8051D0E013C
3 changed files with 31 additions and 12 deletions

View File

@ -533,15 +533,28 @@ fn link_targets<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
format!("failed to remove: {}", dst.display())
})?;
}
fs::hard_link(src, dst)
.or_else(|err| {
debug!("hard link failed {}. falling back to fs::copy", err);
fs::copy(src, dst).map(|_| ())
})
.chain_err(|| {
let link_result = if src.is_dir() {
#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(target_os = "redox")]
use std::os::redox::fs::symlink;
#[cfg(windows)]
use std::os::windows::fs::symlink_dir as symlink;
symlink(src, dst)
} else {
fs::hard_link(src, dst)
};
link_result
.or_else(|err| {
debug!("link failed {}. falling back to fs::copy", err);
fs::copy(src, dst).map(|_| ())
})
.chain_err(|| {
format!("failed to link or copy `{}` to `{}`",
src.display(), dst.display())
})?;
})?;
}
if json_messages {

View File

@ -3899,6 +3899,13 @@ fn uplift_dsym_of_bin_on_mac() {
);
assert_that(&p.bin("foo.dSYM"), existing_dir());
assert_that(&p.bin("b.dSYM"), existing_dir());
assert!(
p.bin("b.dSYM")
.symlink_metadata()
.expect("read metadata from b.dSYM")
.file_type()
.is_symlink()
);
assert_that(&p.bin("c.dSYM"), is_not(existing_dir()));
assert_that(&p.bin("d.dSYM"), is_not(existing_dir()));
}

View File

@ -81,15 +81,14 @@ impl CargoPathExt for Path {
}
for file in t!(fs::read_dir(self)) {
let file = t!(file).path();
if file.is_dir() {
file.rm_rf();
let file = t!(file);
if file.file_type().map(|m| m.is_dir()).unwrap_or(false) {
file.path().rm_rf();
} else {
// 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.
do_op(&file, "remove file", |p| fs::remove_file(p));
do_op(&file.path(), "remove file", |p| fs::remove_file(p));
}
}
do_op(self, "remove dir", |p| fs::remove_dir(p));