Skip to content

Commit 3efdb50

Browse files
ChrisDrydensylvestre
authored andcommitted
ls: fix symlink target coloring for chains and extensions
1 parent a1545ef commit 3efdb50

2 files changed

Lines changed: 39 additions & 4 deletions

File tree

src/uu/ls/src/ls.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,10 +3398,15 @@ fn display_item_name(
33983398
}
33993399
}
34003400

3401-
match fs::metadata(&absolute_target) {
3402-
Ok(_) => {
3403-
let target_data =
3404-
PathData::new(absolute_target, None, None, config, false);
3401+
match fs::canonicalize(&absolute_target) {
3402+
Ok(resolved_target) => {
3403+
let target_data = PathData::new(
3404+
resolved_target,
3405+
None,
3406+
target_path.file_name().map(|s| s.to_os_string()),
3407+
config,
3408+
false,
3409+
);
34053410
name.push(color_name(
34063411
escaped_target,
34073412
&target_data,

tests/by-util/test_ls.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4951,6 +4951,36 @@ fn test_dereference_symlink_file_color() {
49514951
.stdout_is(out_exp);
49524952
}
49534953

4954+
/// Symlink chain target should be colored by final target type, not as symlink (#8934).
4955+
#[test]
4956+
fn test_symlink_chain_target_color() {
4957+
let (at, mut ucmd) = at_and_ucmd!();
4958+
at.touch("file");
4959+
at.relative_symlink_file("file", "link1");
4960+
at.relative_symlink_file("link1", "link2");
4961+
let out = ucmd
4962+
.args(&["-l", "--color=always", "link2"])
4963+
.succeeds()
4964+
.stdout_move_str();
4965+
let target = out.split("->").nth(1).unwrap();
4966+
assert!(!target.contains("36m")); // 36m = cyan (symlink color)
4967+
}
4968+
4969+
/// Symlink target should be colored by extension (e.g., .tar.gz shows as archive color).
4970+
#[test]
4971+
fn test_symlink_target_extension_color() {
4972+
let (at, mut ucmd) = at_and_ucmd!();
4973+
at.touch("archive.tar.gz");
4974+
at.relative_symlink_file("archive.tar.gz", "link");
4975+
let out = ucmd
4976+
.env("LS_COLORS", "*.tar.gz=31")
4977+
.args(&["-l", "--color=always", "link"])
4978+
.succeeds()
4979+
.stdout_move_str();
4980+
let target = out.split("->").nth(1).unwrap();
4981+
assert!(target.contains("31m")); // 31 = red (our configured archive color)
4982+
}
4983+
49544984
#[test]
49554985
fn test_tabsize_option() {
49564986
let scene = TestScenario::new(util_name!());

0 commit comments

Comments
 (0)