@@ -359,7 +359,8 @@ fn format_path(cwd: impl AsRef<Path>, path: impl AsRef<Path>) -> String {
359359 . map ( |p| p. to_string_lossy ( ) . to_string ( ) )
360360 // If we have three consecutive ".." then it should probably just stay as an absolute path.
361361 . map ( |p| {
362- if p. starts_with ( "../../.." ) {
362+ let three_up = format ! ( "..{}..{}.." , std:: path:: MAIN_SEPARATOR , std:: path:: MAIN_SEPARATOR ) ;
363+ if p. starts_with ( & three_up) {
363364 path. as_ref ( ) . to_string_lossy ( ) . to_string ( )
364365 } else {
365366 p
@@ -376,6 +377,10 @@ fn supports_truecolor(ctx: &Context) -> bool {
376377
377378#[ cfg( test) ]
378379mod tests {
380+ use std:: path:: MAIN_SEPARATOR ;
381+
382+ use chat_cli:: platform:: ACTIVE_USER_HOME ;
383+
379384 use super :: * ;
380385 use crate :: platform:: EnvProvider ;
381386
@@ -384,15 +389,12 @@ mod tests {
384389 let ctx = Context :: builder ( ) . with_test_home ( ) . await . unwrap ( ) . build_fake ( ) ;
385390
386391 let actual = sanitize_path_tool_arg ( & ctx, "~" ) ;
387- assert_eq ! (
388- actual,
389- ctx. fs( ) . chroot_path( ctx. env( ) . home( ) . unwrap( ) ) ,
390- "tilde should expand"
391- ) ;
392+ let expected_home = ctx. env ( ) . home ( ) . unwrap_or_default ( ) ;
393+ assert_eq ! ( actual, ctx. fs( ) . chroot_path( & expected_home) , "tilde should expand" ) ;
392394 let actual = sanitize_path_tool_arg ( & ctx, "~/hello" ) ;
393395 assert_eq ! (
394396 actual,
395- ctx. fs( ) . chroot_path( ctx . env ( ) . home ( ) . unwrap ( ) . join( "hello" ) ) ,
397+ ctx. fs( ) . chroot_path( expected_home . join( "hello" ) ) ,
396398 "tilde should expand"
397399 ) ;
398400 let actual = sanitize_path_tool_arg ( & ctx, "/~" ) ;
@@ -412,15 +414,39 @@ mod tests {
412414 let path = sanitize_path_tool_arg ( & ctx, path) ;
413415 fs. create_dir_all ( & cwd) . await . unwrap ( ) ;
414416 fs. create_dir_all ( & path) . await . unwrap ( ) ;
415- // Using `contains` since the chroot test directory will prefix the formatted path with a tmpdir
416- // path.
417- assert ! ( format_path( cwd, path) . contains( expected) ) ;
417+
418+ let formatted = format_path ( & cwd, & path) ;
419+
420+ if Path :: new ( expected) . is_absolute ( ) {
421+ // If the expected path is relative, we need to ensure it is relative to the cwd.
422+ let expected = fs. chroot_path_str ( expected) ;
423+
424+ assert ! ( formatted == expected, "Expected '{}' to be '{}'" , formatted, expected) ;
425+
426+ return ;
427+ }
428+
429+ assert ! (
430+ formatted. contains( expected) ,
431+ "Expected '{}' to be '{}'" ,
432+ formatted,
433+ expected
434+ ) ;
418435 }
419- assert_paths ( "/Users/testuser/src" , "/Users/testuser/Downloads" , "../Downloads" ) . await ;
436+
437+ // Test relative path from src to Downloads (sibling directories)
438+ assert_paths (
439+ format ! ( "{ACTIVE_USER_HOME}{MAIN_SEPARATOR}src" ) . as_str ( ) ,
440+ format ! ( "{ACTIVE_USER_HOME}{MAIN_SEPARATOR}Downloads" ) . as_str ( ) ,
441+ format ! ( "..{MAIN_SEPARATOR}Downloads" ) . as_str ( ) ,
442+ )
443+ . await ;
444+
445+ // Test absolute path that should stay absolute (going up too many levels)
420446 assert_paths (
421- "/Users/testuser/ projects/MyProject/src" ,
422- "/Volumes/projects/MyProject/src" ,
423- "/Volumes/projects/MyProject/src" ,
447+ format ! ( "{ACTIVE_USER_HOME}{MAIN_SEPARATOR} projects{MAIN_SEPARATOR}some{MAIN_SEPARATOR}project" ) . as_str ( ) ,
448+ format ! ( "{ACTIVE_USER_HOME}{MAIN_SEPARATOR}other" ) . as_str ( ) ,
449+ format ! ( "{ACTIVE_USER_HOME}{MAIN_SEPARATOR}other" ) . as_str ( ) ,
424450 )
425451 . await ;
426452 }
0 commit comments