diff options
author | Anirban Halder <anirbanhalder752@gmail.com> | 2024-05-12 00:37:44 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-11 21:07:44 +0200 |
commit | 1a5639b7d27f384381d3ff2dbd55174eb369bf9f (patch) | |
tree | 3adb796ad97c36f42ec9fd36843f9be9239656b7 | |
parent | dddf9f26d6d3a4812a1ae0fa88b763b43796bab7 (diff) |
Fix ls: panicking on dangling symlink with --color=auto -l (#6346)
* Fixed unwrap being called on dereferenced dangling symlink
* Added test
* Switched to regex matching in test
* Remove unnecessary mkdir call
* Modified documentation of the test and added assertion of the colors
* Fixed a typo
-rw-r--r-- | src/uu/ls/src/ls.rs | 7 | ||||
-rw-r--r-- | tests/by-util/test_ls.rs | 40 |
2 files changed, 42 insertions, 5 deletions
diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index e245a9e18..49768e053 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -3353,10 +3353,9 @@ fn color_name( // use the optional target_symlink // Use fn get_metadata_with_deref_opt instead of get_metadata() here because ls // should not exit with an err, if we are unable to obtain the target_metadata - let md = get_metadata_with_deref_opt(target.p_buf.as_path(), path.must_dereference) - .unwrap_or_else(|_| target.get_metadata(out).unwrap().clone()); - - apply_style_based_on_metadata(path, Some(&md), ls_colors, style_manager, &name) + let md_res = get_metadata_with_deref_opt(target.p_buf.as_path(), path.must_dereference); + let md = md_res.or(path.p_buf.symlink_metadata()); + apply_style_based_on_metadata(path, md.ok().as_ref(), ls_colors, style_manager, &name) } else { let md_option = path.get_metadata(out); let symlink_metadata = path.p_buf.symlink_metadata().ok(); diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index d828d1a64..8ecabf86d 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -2,7 +2,7 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// 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 +// 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 #[cfg(any(unix, feature = "feat_selinux"))] use crate::common::util::expected_result; @@ -1376,6 +1376,44 @@ fn test_ls_long_symlink_color() { } } +/// This test is for "ls -l --color=auto|--color=always" +/// We use "--color=always" as the colors are the same regardless of the color option being "auto" or "always" +/// tests whether the specific color of the target and the dangling_symlink are equal and checks +/// whether checks whether ls outputs the correct path for the symlink and the file it points to and applies the color code to it. +#[test] +fn test_ls_long_dangling_symlink_color() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + at.mkdir("dir1"); + at.symlink_dir("foo", "dir1/dangling_symlink"); + let result = ts + .ucmd() + .arg("-l") + .arg("--color=always") + .arg("dir1/dangling_symlink") + .succeeds(); + + let stdout = result.stdout_str(); + // stdout contains output like in the below sequence. We match for the color i.e. 01;36 + // \x1b[0m\x1b[01;36mdir1/dangling_symlink\x1b[0m -> \x1b[01;36mfoo\x1b[0m + let color_regex = Regex::new(r"(\d\d;)\d\dm").unwrap(); + // colors_vec[0] contains the symlink color and style and colors_vec[1] contains the color and style of the file the + // symlink points to. + let colors_vec: Vec<_> = color_regex + .find_iter(stdout) + .map(|color| color.as_str()) + .collect(); + + assert_eq!(colors_vec[0], colors_vec[1]); + // constructs the string of file path with the color code + let symlink_color_name = colors_vec[0].to_owned() + "dir1/dangling_symlink\x1b"; + let target_color_name = colors_vec[1].to_owned() + at.plus_as_string("foo\x1b").as_str(); + + assert!(stdout.contains(&symlink_color_name)); + assert!(stdout.contains(&target_color_name)); +} + #[test] fn test_ls_long_total_size() { let scene = TestScenario::new(util_name!()); |