about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/util.rs12
-rw-r--r--src/librustc_metadata/locator.rs28
-rw-r--r--src/stage0.txt2
3 files changed, 39 insertions, 3 deletions
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 520514f5fc9..fc63655d79b 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -20,6 +20,8 @@ use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::time::Instant;
 
+use filetime::{self, FileTime};
+
 /// Returns the `name` as the filename of a static library for `target`.
 pub fn staticlib(name: &str, target: &str) -> String {
     if target.contains("windows") {
@@ -38,12 +40,18 @@ pub fn copy(src: &Path, dst: &Path) {
 
     // Attempt to "easy copy" by creating a hard link (symlinks don't work on
     // windows), but if that fails just fall back to a slow `copy` operation.
-    let res = fs::hard_link(src, dst);
-    let res = res.or_else(|_| fs::copy(src, dst).map(|_| ()));
+    // let res = fs::hard_link(src, dst);
+    let res = fs::copy(src, dst);
     if let Err(e) = res {
         panic!("failed to copy `{}` to `{}`: {}", src.display(),
                dst.display(), e)
     }
+    let metadata = t!(src.metadata());
+    t!(fs::set_permissions(dst, metadata.permissions()));
+    let atime = FileTime::from_last_access_time(&metadata);
+    let mtime = FileTime::from_last_modification_time(&metadata);
+    t!(filetime::set_file_times(dst, atime, mtime));
+
 }
 
 /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index de465ea92f6..a6771083fc3 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -639,6 +639,34 @@ impl<'a> Context<'a> {
                                                          lib.display()));
                 continue;
             }
+
+            // Ok so at this point we've determined that `(lib, kind)` above is
+            // a candidate crate to load, and that `slot` is either none (this
+            // is the first crate of its kind) or if some the previous path has
+            // the exact same hash (e.g. it's the exact same crate).
+            //
+            // In principle these two candidate crates are exactly the same so
+            // we can choose either of them to link. As a stupidly gross hack,
+            // however, we favor crate in the sysroot.
+            //
+            // You can find more info in rust-lang/rust#39518 and various linked
+            // issues, but the general gist is that during testing libstd the
+            // compilers has two candidates to choose from: one in the sysroot
+            // and one in the deps folder. These two crates are the exact same
+            // crate but if the compiler chooses the one in the deps folder
+            // it'll cause spurious errors on Windows.
+            //
+            // As a result, we favor the sysroot crate here. Note that the
+            // candidates are all canonicalized, so we canonicalize the sysroot
+            // as well.
+            if let Some((ref prev, _)) = ret {
+                let sysroot = self.sess.sysroot();
+                let sysroot = sysroot.canonicalize()
+                                     .unwrap_or(sysroot.to_path_buf());
+                if prev.starts_with(&sysroot) {
+                    continue
+                }
+            }
             *slot = Some((hash, metadata));
             ret = Some((lib, kind));
         }
diff --git a/src/stage0.txt b/src/stage0.txt
index cda9a5a9643..772029ab0c2 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -13,4 +13,4 @@
 # released on `$date`
 
 rustc: beta-2017-02-01
-cargo: bfee18f73287687c543bda8c35e4e33808792715
+cargo: 407edef22e894266eb562618cba5ca9757051946