@@ -324,3 +324,112 @@ fn check_prefix(index: &gix_index::State, prefix: &str, expected: &[&str]) {
324324 "{prefix:?}"
325325 ) ;
326326}
327+
328+ #[ test]
329+ fn path_is_directory ( ) {
330+ let file = Fixture :: Loose ( "ignore-case-realistic" ) . open ( ) ;
331+
332+ // Test that directories containing entries are detected
333+ assert ! (
334+ file. path_is_directory( "tests" . into( ) ) ,
335+ "tests is a directory containing entries"
336+ ) ;
337+ assert ! (
338+ file. path_is_directory( "tests/snapshots" . into( ) ) ,
339+ "tests/snapshots is a directory containing entries"
340+ ) ;
341+ assert ! (
342+ file. path_is_directory( "tests/snapshots/porcelain" . into( ) ) ,
343+ "tests/snapshots/porcelain is a directory"
344+ ) ;
345+ assert ! (
346+ file. path_is_directory( "tests/tools" . into( ) ) ,
347+ "tests/tools is a directory"
348+ ) ;
349+
350+ // Test that non-existent directories return false
351+ assert ! (
352+ !file. path_is_directory( "nonexistent" . into( ) ) ,
353+ "nonexistent is not a directory"
354+ ) ;
355+ assert ! ( !file. path_is_directory( "z" . into( ) ) , "z is not a directory" ) ;
356+ assert ! (
357+ !file. path_is_directory( "test" . into( ) ) ,
358+ "test is not a directory (tests is)"
359+ ) ;
360+
361+ // Test that files are not directories
362+ assert ! (
363+ !file. path_is_directory( "tests/utilities.sh" . into( ) ) ,
364+ "tests/utilities.sh is a file, not a directory"
365+ ) ;
366+
367+ // Test that partial directory names don't match
368+ assert ! ( !file. path_is_directory( "" . into( ) ) , "empty path is not a directory" ) ;
369+ }
370+
371+ #[ test]
372+ fn path_is_directory_icase ( ) {
373+ let file = Fixture :: Loose ( "ignore-case-realistic" ) . open ( ) ;
374+ let icase = file. prepare_icase_backing ( ) ;
375+
376+ // Test case-sensitive matching
377+ assert ! (
378+ file. path_is_directory_icase( "tests" . into( ) , false , & icase) ,
379+ "tests is a directory (case-sensitive)"
380+ ) ;
381+ assert ! (
382+ file. path_is_directory_icase( "tests/tools" . into( ) , false , & icase) ,
383+ "tests/tools is a directory (case-sensitive)"
384+ ) ;
385+
386+ // Test case-insensitive matching
387+ assert ! (
388+ file. path_is_directory_icase( "TESTS" . into( ) , true , & icase) ,
389+ "TESTS is a directory (case-insensitive, matches 'tests')"
390+ ) ;
391+ assert ! (
392+ file. path_is_directory_icase( "tests/TOOLS" . into( ) , true , & icase) ,
393+ "tests/TOOLS is a directory (case-insensitive, matches 'tests/tools')"
394+ ) ;
395+ assert ! (
396+ file. path_is_directory_icase( "TESTS/SNAPSHOTS" . into( ) , true , & icase) ,
397+ "TESTS/SNAPSHOTS is a directory (case-insensitive)"
398+ ) ;
399+
400+ // Test that non-existent paths return false even with icase
401+ assert ! (
402+ !file. path_is_directory_icase( "nonexistent" . into( ) , true , & icase) ,
403+ "nonexistent is not a directory even with icase"
404+ ) ;
405+ assert ! (
406+ !file. path_is_directory_icase( "Z" . into( ) , true , & icase) ,
407+ "Z is not a directory even with icase"
408+ ) ;
409+ }
410+
411+ #[ test]
412+ fn path_is_directory_icase_with_clashes ( ) {
413+ let file = icase_fixture ( ) ;
414+ let icase = file. prepare_icase_backing ( ) ;
415+
416+ // Test directory detection with case clashes
417+ assert ! (
418+ file. path_is_directory_icase( "D" . into( ) , false , & icase) ,
419+ "D is a directory (case-sensitive)"
420+ ) ;
421+ assert ! (
422+ file. path_is_directory_icase( "d" . into( ) , true , & icase) ,
423+ "d matches D directory (case-insensitive)"
424+ ) ;
425+
426+ // Test that files aren't detected as directories
427+ assert ! (
428+ !file. path_is_directory_icase( "X" . into( ) , false , & icase) ,
429+ "X is a file, not a directory"
430+ ) ;
431+ assert ! (
432+ !file. path_is_directory_icase( "x" . into( ) , false , & icase) ,
433+ "x is a symlink, not a directory"
434+ ) ;
435+ }
0 commit comments