When uplifting directories, symlink them instead of hard-link them.
authorkennytm <kennytm@gmail.com>
Sat, 28 Oct 2017 19:47:29 +0000 (03:47 +0800)
committerkennytm <kennytm@gmail.com>
Sat, 28 Oct 2017 20:00:40 +0000 (04:00 +0800)
Fixes #4671.

src/cargo/ops/cargo_rustc/mod.rs
tests/build.rs
tests/cargotest/support/paths.rs

index 97dbc334fb0edf7d5dcb979bd0be6417b3999327..8dce388c055b176fbabe6bf726191bec5ab4d1bb 100644 (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 {
index 0e531486dcb78c2903a117a2f7884ddc501f67b8..bee40601430df6fae1e323ae727c1187ae19146f 100644 (file)
@@ -3877,6 +3877,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()));
 }
index bf3b6d446cc8a4d27ccd0fbeabcaa9cc6eb186db..8a74fc0f61df9b44c5ad9a809f4f139b2753f131 100644 (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));