@@ -40,6 +40,21 @@ pub fn expand_tilde(path: &Path) -> PathBuf {
4040/// needs to improve on.
4141/// Copied from cargo: <https://github.com/rust-lang/cargo/blob/070e459c2d8b79c5b2ac5218064e7603329c92ae/crates/cargo-util/src/paths.rs#L81>
4242pub fn get_normalized_path(path: &Path) -> PathBuf {
43+ // normalization strategy is to canonicalize first ancestor path that exists (i.e., canonicalize as much as possible),
44+ // then run handrolled normalization on the non-existent remainder
45+ let (base, path) = path
46+ .ancestors()
47+ .find_map(|base| {
48+ let canonicalized_base = dunce::canonicalize(base).ok()?;
49+ let remainder = path.strip_prefix(base).ok()?.into();
50+ Some((canonicalized_base, remainder))
51+ })
52+ .unwrap_or_else(|| (PathBuf::new(), PathBuf::from(path)));
53+
54+ if path.as_os_str().is_empty() {
55+ return base;
56+ }
57+
4358 let mut components = path.components().peekable();
4459 let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
4560 components.next();
@@ -63,7 +78,7 @@ pub fn get_normalized_path(path: &Path) -> PathBuf {
6378 }
6479 }
6580 }
66− ret
81+ base.join(ret)
6782}
6883
6984/// Returns the canonical, absolute form of a path with all intermediate components normalized.
@@ -82,13 +97,19 @@ pub fn get_canonicalized_path(path: &Path) -> std::io::Result<PathBuf> {
8297}
8398
8499pub fn get_relative_path(path: &Path) -> PathBuf {
100+ let path = PathBuf::from(path);
85101 let path = if path.is_absolute() {
86− let cwdir = std::env::current_dir().expect("couldn't determine current directory");
87− path.strip_prefix(cwdir).unwrap_or(path)
102+ let cwdir = std::env::current_dir()
103+ .map(|path| get_normalized_path(&path))
104+ .expect("couldn't determine current directory");
105+ get_normalized_path(&path)
106+ .strip_prefix(cwdir)
107+ .map(PathBuf::from)
108+ .unwrap_or(path)
88109 } else {
89110 path
90111 };
91− fold_home_dir(path)
112+ fold_home_dir(&path)
92113}
93114
94115/// Returns a truncated filepath where the basepart of the path is reduced to the first