33// For the full copyright and license information, please view the LICENSE
44// file that was distributed with this source code.
55// spell-checker:ignore (words) READMECAREFULLY birthtime doesntexist oneline somebackup lrwx somefile somegroup somehiddenbackup somehiddenfile tabsize aaaaaaaa bbbb cccc dddddddd ncccc neee naaaaa nbcdef nfffff dired subdired tmpfs mdir COLORTERM mexe bcdef mfoo timefile
6- // spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry
6+ // spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry awith acolons
77#![ allow(
88 clippy:: similar_names,
99 clippy:: too_many_lines,
@@ -5701,19 +5701,15 @@ fn test_ls_hyperlink() {
57015701
57025702 let result = scene. ucmd ( ) . arg ( "--hyperlink" ) . succeeds ( ) ;
57035703 assert ! ( result. stdout_str( ) . contains( "\x1b ]8;;file://" ) ) ;
5704- assert ! (
5705- result
5706- . stdout_str( )
5707- . contains( & format!( "{path}{separator}{file}\x07 {file}\x1b ]8;;\x07 " ) )
5708- ) ;
5704+ assert ! ( result. stdout_str( ) . contains( & format!(
5705+ "{path}{separator}{file}\x1b \\ {file}\x1b ]8;;\x1b \\ "
5706+ ) ) ) ;
57095707
57105708 let result = scene. ucmd ( ) . arg ( "--hyperlink=always" ) . succeeds ( ) ;
57115709 assert ! ( result. stdout_str( ) . contains( "\x1b ]8;;file://" ) ) ;
5712- assert ! (
5713- result
5714- . stdout_str( )
5715- . contains( & format!( "{path}{separator}{file}\x07 {file}\x1b ]8;;\x07 " ) )
5716- ) ;
5710+ assert ! ( result. stdout_str( ) . contains( & format!(
5711+ "{path}{separator}{file}\x1b \\ {file}\x1b ]8;;\x1b \\ "
5712+ ) ) ) ;
57175713
57185714 for argument in [
57195715 "--hyperlink=never" ,
@@ -5748,23 +5744,23 @@ fn test_ls_hyperlink_encode_link() {
57485744 assert ! (
57495745 result
57505746 . stdout_str( )
5751- . contains( "back%5cslash\x07 back \\ slash\x1b ]8;;\x07 " )
5747+ . contains( "back%5cslash\x1b \\ back \\ slash\x1b ]8;;\x1b \\ " )
57525748 ) ;
57535749 assert ! (
57545750 result
57555751 . stdout_str( )
5756- . contains( "ques%3ftion\x07 ques ?tion\x1b ]8;;\x07 " )
5752+ . contains( "ques%3ftion\x1b \\ ques ?tion\x1b ]8;;\x1b \\ " )
57575753 ) ;
57585754 }
57595755 assert ! (
57605756 result
57615757 . stdout_str( )
5762- . contains( "encoded%253Fquestion\x07 encoded %3Fquestion\x1b ]8;;\x07 " )
5758+ . contains( "encoded%253Fquestion\x1b \\ encoded %3Fquestion\x1b ]8;;\x1b \\ " )
57635759 ) ;
57645760 assert ! (
57655761 result
57665762 . stdout_str( )
5767- . contains( "sp%20ace\x07 sp ace\x1b ]8;;\x07 " )
5763+ . contains( "sp%20ace\x1b \\ sp ace\x1b ]8;;\x1b \\ " )
57685764 ) ;
57695765}
57705766// spell-checker: enable
@@ -5796,7 +5792,9 @@ fn test_ls_hyperlink_dirs() {
57965792 . lines( )
57975793 . next( )
57985794 . unwrap( )
5799- . contains( & format!( "{path}{separator}{dir_a}\x07 {dir_a}\x1b ]8;;\x07 :" ) )
5795+ . contains( & format!(
5796+ "{path}{separator}{dir_a}\x1b \\ {dir_a}\x1b ]8;;\x1b \\ :"
5797+ ) )
58005798 ) ;
58015799 assert_eq ! ( result. stdout_str( ) . lines( ) . nth( 1 ) . unwrap( ) , "" ) ;
58025800 assert ! (
@@ -5805,7 +5803,9 @@ fn test_ls_hyperlink_dirs() {
58055803 . lines( )
58065804 . nth( 2 )
58075805 . unwrap( )
5808- . contains( & format!( "{path}{separator}{dir_b}\x07 {dir_b}\x1b ]8;;\x07 :" ) )
5806+ . contains( & format!(
5807+ "{path}{separator}{dir_b}\x1b \\ {dir_b}\x1b ]8;;\x1b \\ :"
5808+ ) )
58095809 ) ;
58105810}
58115811
@@ -5837,21 +5837,95 @@ fn test_ls_hyperlink_recursive_dirs() {
58375837 let mut lines = result. stdout_str ( ) . lines ( ) ;
58385838 assert_hyperlink ! (
58395839 lines. next( ) ,
5840- & format!( "{path}{separator}{dir_a}\x07 {dir_a}\x1b ]8;;\x07 :" )
5840+ & format!( "{path}{separator}{dir_a}\x1b \\ {dir_a}\x1b ]8;;\x1b \\ :" )
58415841 ) ;
58425842 assert_hyperlink ! (
58435843 lines. next( ) ,
5844- & format!( "{path}{separator}{dir_a}{separator}{dir_b}\x07 {dir_b}\x1b ]8;;\x07 " )
5844+ & format!( "{path}{separator}{dir_a}{separator}{dir_b}\x1b \\ {dir_b}\x1b ]8;;\x1b \\ " )
58455845 ) ;
58465846 assert ! ( matches!( lines. next( ) , Some ( l) if l. is_empty( ) ) ) ;
58475847 assert_hyperlink ! (
58485848 lines. next( ) ,
58495849 & format!(
5850- "{path}{separator}{dir_a}{separator}{dir_b}\x07 {dir_a}{separator}{dir_b}\x1b ]8;;\x07 :"
5850+ "{path}{separator}{dir_a}{separator}{dir_b}\x1b \\ {dir_a}{separator}{dir_b}\x1b ]8;;\x1b \\ :"
58515851 )
58525852 ) ;
58535853}
58545854
5855+ #[ test]
5856+ fn test_ls_hyperlink_symlink_target_handling ( ) {
5857+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
5858+ let at = & scene. fixtures ;
5859+
5860+ at. mkdir ( "target_dir" ) ;
5861+ at. touch ( "target_file.txt" ) ;
5862+ at. symlink_file ( "target_file.txt" , "link_to_file" ) ;
5863+ at. symlink_dir ( "target_dir" , "link_to_dir" ) ;
5864+ at. symlink_file ( "nonexistent" , "link_to_missing" ) ;
5865+
5866+ let result = scene
5867+ . ucmd ( )
5868+ . args ( & [ "-l" , "--hyperlink" , "--color" ] )
5869+ . succeeds ( ) ;
5870+ let output = result. stdout_str ( ) ;
5871+
5872+ assert ! ( output. contains( "\x1b ]8;;file://" ) ) ;
5873+ assert ! ( !output. contains( '\x07' ) ) ;
5874+ assert ! ( output. contains( "\x1b \\ " ) ) ;
5875+
5876+ let file_link_line = output
5877+ . lines ( )
5878+ . find ( |line| line. contains ( "link_to_file" ) )
5879+ . unwrap ( ) ;
5880+ assert ! ( file_link_line. contains( " -> " ) ) ;
5881+ let target_part = file_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5882+ assert ! ( !target_part. contains( "\x1b [" ) ) ;
5883+ assert ! ( !target_part. ends_with( "\x1b [K" ) ) ;
5884+
5885+ let dir_link_line = output
5886+ . lines ( )
5887+ . find ( |line| line. contains ( "link_to_dir" ) )
5888+ . unwrap ( ) ;
5889+ assert ! ( dir_link_line. contains( " -> " ) ) ;
5890+ let target_part = dir_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5891+ assert ! ( target_part. contains( "\x1b [" ) ) ;
5892+
5893+ let missing_link_line = output
5894+ . lines ( )
5895+ . find ( |line| line. contains ( "link_to_missing" ) )
5896+ . unwrap ( ) ;
5897+ assert ! ( missing_link_line. contains( " -> " ) ) ;
5898+ let missing_target_part = missing_link_line. split ( " -> " ) . nth ( 1 ) . unwrap ( ) ;
5899+ assert ! ( missing_target_part. contains( "\x1b [" ) ) ;
5900+ }
5901+
5902+ #[ test]
5903+ fn test_ls_hyperlink_utf8_encoding ( ) {
5904+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
5905+ let at = & scene. fixtures ;
5906+
5907+ at. touch ( "café.txt" ) ;
5908+ #[ cfg( not( target_os = "windows" ) ) ]
5909+ at. touch ( "file:with:colons.txt" ) ;
5910+ #[ cfg( target_os = "windows" ) ]
5911+ at. touch ( "file-with-colons.txt" ) ;
5912+ at. touch ( "file with spaces.txt" ) ;
5913+
5914+ let result = scene. ucmd ( ) . args ( & [ "--hyperlink" ] ) . succeeds ( ) ;
5915+ let output = result. stdout_str ( ) ;
5916+
5917+ assert ! ( output. contains( "caf%c3%a9.txt" ) ) ;
5918+ #[ cfg( not( target_os = "windows" ) ) ]
5919+ assert ! ( output. contains( "file%3awith%3acolons.txt" ) ) ;
5920+ #[ cfg( target_os = "windows" ) ]
5921+ assert ! ( output. contains( "file-with-colons.txt" ) ) ;
5922+ assert ! ( output. contains( "file%20with%20spaces.txt" ) ) ;
5923+
5924+ let hyperlink_count = output. matches ( "\x1b ]8;;file://" ) . count ( ) ;
5925+ let terminator_count = output. matches ( "\x1b \\ " ) . count ( ) ;
5926+ assert_eq ! ( terminator_count, hyperlink_count * 2 ) ;
5927+ }
5928+
58555929#[ test]
58565930fn test_ls_color_do_not_reset ( ) {
58575931 let scene: TestScenario = TestScenario :: new ( util_name ! ( ) ) ;
0 commit comments