From a8077cc04836389b750732839de540c06d0cce38 Mon Sep 17 00:00:00 2001
From: Seiichi Uchida <seiichi.uchida@dena.com>
Date: Wed, 6 Feb 2019 21:31:15 +0900
Subject: [PATCH 1/5] Use absolute_path instead of fs::canonicalize

---
 Cargo.lock                |  1 +
 Cargo.toml                |  3 +++
 src/bin/main.rs           | 10 ++++-----
 src/cargo-fmt/main.rs     | 12 ++++++-----
 src/config/config_type.rs |  2 +-
 src/config/file_lines.rs  | 13 ++++++------
 src/lib.rs                |  4 ++++
 src/utils.rs              | 44 ++++++++++++++++++++++++++++++++++++++-
 8 files changed, 71 insertions(+), 18 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index bc52c406226..6ca1190293f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -644,6 +644,7 @@ dependencies = [
  "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index b1e83e93b09..18d277cf431 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -57,6 +57,9 @@ unicode-width = "0.1.5"
 unicode_categories = "0.1.1"
 dirs = "1.0.4"
 
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["errhandlingapi", "fileapi"] }
+
 # A noop dependency that changes in the Rust repository, it's a bit of a hack.
 # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
 # for more information.
diff --git a/src/bin/main.rs b/src/bin/main.rs
index 53e95e8b5b6..2b612e158fd 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -25,8 +25,8 @@ use failure::err_msg;
 use getopts::{Matches, Options};
 
 use crate::rustfmt::{
-    load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName,
-    Input, Session, Verbosity,
+    absolute_path, load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines,
+    FileName, Input, Session, Verbosity,
 };
 
 fn main() {
@@ -414,9 +414,9 @@ fn determine_operation(matches: &Matches) -> Result<Operation, ErrorKind> {
         .iter()
         .map(|s| {
             let p = PathBuf::from(s);
-            // we will do comparison later, so here tries to canonicalize first
-            // to get the expected behavior.
-            p.canonicalize().unwrap_or(p)
+            // we will do comparison later, so here tries to get the absolute
+            // path first to get the expected behavior.
+            absolute_path(&p).unwrap_or(p)
         })
         .collect();
 
diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs
index 83a93240ff2..776450d0720 100644
--- a/src/cargo-fmt/main.rs
+++ b/src/cargo-fmt/main.rs
@@ -15,11 +15,11 @@
 
 extern crate cargo_metadata;
 extern crate getopts;
+extern crate rustfmt_nightly as rustfmt;
 extern crate serde_json as json;
 
 use std::collections::{HashMap, HashSet};
 use std::env;
-use std::fs;
 use std::hash::{Hash, Hasher};
 use std::io::{self, Write};
 use std::iter::FromIterator;
@@ -29,6 +29,8 @@ use std::str;
 
 use getopts::{Matches, Options};
 
+use crate::rustfmt::absolute_path;
+
 fn main() {
     let exit_status = execute();
     std::io::stdout().flush().unwrap();
@@ -170,10 +172,10 @@ pub struct Target {
 impl Target {
     pub fn from_target(target: &cargo_metadata::Target) -> Self {
         let path = PathBuf::from(&target.src_path);
-        let canonicalized = fs::canonicalize(&path).unwrap_or(path);
+        let path = absolute_path(&path).unwrap_or(path);
 
         Target {
-            path: canonicalized,
+            path,
             kind: target.kind[0].clone(),
             edition: target.edition.clone(),
         }
@@ -236,9 +238,9 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error
 
 fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
     let metadata = get_cargo_metadata(None)?;
-    let current_dir = env::current_dir()?.canonicalize()?;
+    let current_dir = absolute_path(env::current_dir()?)?;
     let current_dir_manifest = current_dir.join("Cargo.toml");
-    let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?;
+    let workspace_root_path = absolute_path(PathBuf::from(&metadata.workspace_root))?;
     let in_workspace_root = workspace_root_path == current_dir;
 
     for package in metadata.packages {
diff --git a/src/config/config_type.rs b/src/config/config_type.rs
index 09c41f8bb1d..ddc9df70854 100644
--- a/src/config/config_type.rs
+++ b/src/config/config_type.rs
@@ -334,7 +334,7 @@ macro_rules! create_config {
                         dir.to_path_buf()
                     };
 
-                    current = fs::canonicalize(current)?;
+                    current = crate::utils::absolute_path(current)?;
 
                     loop {
                         match get_toml_path(&current) {
diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs
index 07df0e32d9c..8b3debfc69d 100644
--- a/src/config/file_lines.rs
+++ b/src/config/file_lines.rs
@@ -18,9 +18,10 @@ use std::{cmp, fmt, iter, str};
 use serde::de::{Deserialize, Deserializer};
 use serde::ser::{self, Serialize, Serializer};
 use serde_json as json;
-
 use syntax::source_map::{self, SourceFile};
 
+use crate::utils::absolute_path;
+
 /// A range of lines in a file, inclusive of both ends.
 pub struct LineRange {
     pub file: Rc<SourceFile>,
@@ -233,7 +234,7 @@ impl FileLines {
             Some(ref map) => map,
         };
 
-        match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) {
+        match absolute_path_string(file_name).and_then(|file| map.get(&file)) {
             Some(ranges) => ranges.iter().any(f),
             None => false,
         }
@@ -272,9 +273,9 @@ impl<'a> iter::Iterator for Files<'a> {
     }
 }
 
-fn canonicalize_path_string(file: &FileName) -> Option<FileName> {
+fn absolute_path_string(file: &FileName) -> Option<FileName> {
     match *file {
-        FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real),
+        FileName::Real(ref path) => absolute_path(path).ok().map(FileName::Real),
         _ => Some(file.clone()),
     }
 }
@@ -304,8 +305,8 @@ pub struct JsonSpan {
 impl JsonSpan {
     fn into_tuple(self) -> Result<(FileName, Range), String> {
         let (lo, hi) = self.range;
-        let canonical = canonicalize_path_string(&self.file)
-            .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?;
+        let canonical = absolute_path_string(&self.file)
+            .ok_or_else(|| format!("Can't get absolute path {}", &self.file))?;
         Ok((canonical, Range::new(lo, hi)))
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 6fc3dc85945..a7f89b2b801 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -34,6 +34,9 @@ extern crate unicode_categories;
 extern crate unicode_segmentation;
 extern crate unicode_width;
 
+#[cfg(windows)]
+extern crate winapi;
+
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt;
@@ -55,6 +58,7 @@ pub use crate::config::{
     load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle,
     Range, Verbosity,
 };
+pub use crate::utils::absolute_path;
 
 #[macro_use]
 mod utils;
diff --git a/src/utils.rs b/src/utils.rs
index 06f1ca2d8d8..ab05d0ac6de 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 use std::borrow::Cow;
+use std::io;
+use std::path;
 
 use bytecount;
-
 use rustc_target::spec::abi;
 use syntax::ast::{
     self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind,
@@ -604,6 +605,47 @@ pub(crate) fn unicode_str_width(s: &str) -> usize {
     s.width()
 }
 
+#[cfg(windows)]
+pub fn absolute_path<P: AsRef<path::Path>>(p: P) -> io::Result<path::PathBuf> {
+    use std::ffi::OsString;
+    use std::iter::once;
+    use std::os::windows::ffi::{OsStrExt, OsStringExt};
+    use std::ptr::null_mut;
+    use winapi::um::errhandlingapi::GetLastError;
+    use winapi::um::fileapi::GetFullPathNameW;
+
+    // FIXME: This `MAX_PATH` may be valid only from Windows 10, version 1607.
+    // https://docs.microsoft.com/ja-jp/windows/desktop/FileIO/naming-a-file#paths
+    const MAX_PATH: usize = 32767;
+    let wide: Vec<u16> = p
+        .as_ref()
+        .as_os_str()
+        .encode_wide()
+        .chain(once(0))
+        .collect();
+    let mut buffer: Vec<u16> = vec![0; MAX_PATH];
+    unsafe {
+        let result = GetFullPathNameW(
+            wide.as_ptr(),
+            MAX_PATH as u32,
+            buffer.as_mut_ptr(),
+            null_mut(),
+        );
+        if result == 0 {
+            Err(std::io::Error::from_raw_os_error(GetLastError() as i32))
+        } else {
+            Ok(path::PathBuf::from(OsString::from_wide(
+                &buffer[..result as usize],
+            )))
+        }
+    }
+}
+
+#[cfg(not(windows))]
+pub fn absolute_path<P: AsRef<path::Path>>(p: P) -> io::Result<path::PathBuf> {
+    std::fs::canonicalize(p)
+}
+
 #[cfg(test)]
 mod test {
     use super::*;

From 57119d38011b05bb36e7e5154f9871c4413beacb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Tue, 14 May 2019 10:42:43 +0200
Subject: [PATCH 2/5] fix import order

---
 src/bin/main.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bin/main.rs b/src/bin/main.rs
index 449132a8877..33bae11467f 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -16,7 +16,7 @@ use getopts::{Matches, Options};
 
 use crate::rustfmt::{
     absolute_path, load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines,
-    FormatReportFormatterBuilder, FileName, Input, Session, Verbosity,
+    FileName, FormatReportFormatterBuilder, Input, Session, Verbosity,
 };
 
 fn main() {

From 13893465710bfef653661d0ffdb30c9a6607df94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Mon, 27 May 2019 12:48:56 +0200
Subject: [PATCH 3/5] fix compilation on windows

---
 Cargo.lock | 2 +-
 src/lib.rs | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index edad278e6e1..e0156f3ed71 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -827,7 +827,7 @@ dependencies = [
  "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/src/lib.rs b/src/lib.rs
index baff6925c19..ffc5a92ffc5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,9 +9,6 @@ extern crate lazy_static;
 #[macro_use]
 extern crate log;
 
-#[cfg(windows)]
-extern crate winapi;
-
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt;

From 394597d135e106ba37e289db1373163e2ef387dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Tue, 28 May 2019 00:36:33 +0200
Subject: [PATCH 4/5] add test for relative path to modules

---
 tests/source/mods-relative-paths/lib.rs   | 2 ++
 tests/source/mods-relative-paths/mod_b.rs | 7 +++++++
 tests/target/mods-relative-paths/lib.rs   | 2 ++
 tests/target/mods-relative-paths/mod_b.rs | 3 +++
 4 files changed, 14 insertions(+)
 create mode 100644 tests/source/mods-relative-paths/lib.rs
 create mode 100644 tests/source/mods-relative-paths/mod_b.rs
 create mode 100644 tests/target/mods-relative-paths/lib.rs
 create mode 100644 tests/target/mods-relative-paths/mod_b.rs

diff --git a/tests/source/mods-relative-paths/lib.rs b/tests/source/mods-relative-paths/lib.rs
new file mode 100644
index 00000000000..c8648249177
--- /dev/null
+++ b/tests/source/mods-relative-paths/lib.rs
@@ -0,0 +1,2 @@
+#[path = "../mods-relative-paths/mod_b.rs"]
+mod b;
diff --git a/tests/source/mods-relative-paths/mod_b.rs b/tests/source/mods-relative-paths/mod_b.rs
new file mode 100644
index 00000000000..85f9f3f0a4f
--- /dev/null
+++ b/tests/source/mods-relative-paths/mod_b.rs
@@ -0,0 +1,7 @@
+fn
+
+
+
+foo() {
+               println!("toto")
+}
diff --git a/tests/target/mods-relative-paths/lib.rs b/tests/target/mods-relative-paths/lib.rs
new file mode 100644
index 00000000000..c8648249177
--- /dev/null
+++ b/tests/target/mods-relative-paths/lib.rs
@@ -0,0 +1,2 @@
+#[path = "../mods-relative-paths/mod_b.rs"]
+mod b;
diff --git a/tests/target/mods-relative-paths/mod_b.rs b/tests/target/mods-relative-paths/mod_b.rs
new file mode 100644
index 00000000000..3b0991e5071
--- /dev/null
+++ b/tests/target/mods-relative-paths/mod_b.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    println!("toto")
+}

From 130fa514ff1a52f8cbb0ffbb486961fb69a01006 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Campinas?= <stephane.campinas@gmail.com>
Date: Fri, 20 Sep 2019 11:16:28 +0200
Subject: [PATCH 5/5] update winapi from 0.3.7 to 0.3.8

---
 Cargo.lock | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock
index ceff9f86032..729ad141e02 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -894,7 +894,7 @@ dependencies = [
  "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]