diff --git a/Cargo.lock b/Cargo.lock index 3948216b4ece7..ffe06a9b3a169 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4570,6 +4570,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" +[[package]] +name = "path-clean" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" + [[package]] name = "path-slash" version = "0.2.1" @@ -6933,7 +6939,7 @@ dependencies = [ "normpath", "once_cell", "parking_lot", - "path-clean", + "path-clean 0.1.0", "pathdiff", "serde", "serde_json", @@ -7163,7 +7169,7 @@ dependencies = [ "bitflags 2.2.1", "indexmap", "is-macro", - "path-clean", + "path-clean 0.1.0", "pathdiff", "regex", "serde", @@ -9151,6 +9157,8 @@ version = "0.1.0" dependencies = [ "anyhow", "bstr", + "dunce", + "path-clean 1.0.1", "path-slash", "serde", "thiserror", @@ -10177,7 +10185,7 @@ dependencies = [ "lexical-sort", "memmap2", "once_cell", - "path-clean", + "path-clean 0.1.0", "rand 0.8.5", "serde", "serde_cbor", diff --git a/crates/turbopath/Cargo.toml b/crates/turbopath/Cargo.toml index a6eae711b8469..5d4951549bd48 100644 --- a/crates/turbopath/Cargo.toml +++ b/crates/turbopath/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [dependencies] bstr = "1.4.0" +dunce = { workspace = true } +path-clean = "1.0.1" path-slash = "0.2.1" # TODO: Make this a crate feature serde = { workspace = true } diff --git a/crates/turbopath/src/absolute_system_path_buf.rs b/crates/turbopath/src/absolute_system_path_buf.rs index e302f3d691fb0..e09e7ec3b1c00 100644 --- a/crates/turbopath/src/absolute_system_path_buf.rs +++ b/crates/turbopath/src/absolute_system_path_buf.rs @@ -6,6 +6,7 @@ use std::{ path::{Components, Path, PathBuf}, }; +use path_clean::PathClean; use serde::Serialize; use crate::{ @@ -237,10 +238,14 @@ impl AbsoluteSystemPathBuf { } pub fn to_realpath(&self) -> Result { - let realpath = fs::canonicalize(&self.0)?; + let realpath = dunce::canonicalize(&self.0)?; Ok(Self(realpath)) } + pub fn clean(&self) -> Self { + Self(self.0.clean()) + } + pub fn symlink_to_file(&self, target: impl AsRef) -> Result<(), PathError> { self.as_absolute_path().symlink_to_file(target) } @@ -291,6 +296,13 @@ mod tests { PathValidationError::NotAbsolute(_) )) ); + + assert_eq!( + AbsoluteSystemPathBuf::new("/some/dir/../other") + .unwrap() + .clean(), + AbsoluteSystemPathBuf::new("/some/other").unwrap(), + ); } #[cfg(windows)] @@ -314,6 +326,13 @@ mod tests { Err(PathError::PathValidationError( PathValidationError::NotAbsolute(_) )) - ) + ); + + assert_eq!( + AbsoluteSystemPathBuf::new("C:\\some\\dir\\..\\other") + .unwrap() + .clean(), + AbsoluteSystemPathBuf::new("C:\\some\\other").unwrap(), + ); } } diff --git a/crates/turborepo-scm/src/package_deps.rs b/crates/turborepo-scm/src/package_deps.rs index 27002cfef8eee..d0f5a8ba168d9 100644 --- a/crates/turborepo-scm/src/package_deps.rs +++ b/crates/turborepo-scm/src/package_deps.rs @@ -30,7 +30,7 @@ pub(crate) fn find_git_root( .current_dir(turbo_root) .output()?; let root = String::from_utf8(rev_parse.stdout)?; - Ok(turbo_root.join_literal(root.trim_end()).to_realpath()?) + Ok(turbo_root.join_literal(root.trim_end()).clean()) } #[cfg(test)] @@ -72,6 +72,20 @@ mod tests { } } + #[test] + fn test_symlinked_git_root() { + let (_, tmp_root) = tmp_dir(); + let git_root = tmp_root.join_literal("actual_repo"); + git_root.create_dir_all().unwrap(); + setup_repository(&git_root); + git_root.join_literal("inside").create_dir_all().unwrap(); + let link = tmp_root.join_literal("link"); + link.symlink_to_dir("actual_repo").unwrap(); + let turbo_root = link.join_literal("inside"); + let result = find_git_root(&turbo_root).unwrap(); + assert_eq!(result, link); + } + #[test] fn test_get_package_deps() -> Result<(), Error> { // Directory structure: