mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
ls: ls -lF symlink target indicators (#11554)
--------- Co-authored-by: Guillem L. Jara <4lon3ly0@tutanota.com> Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
co-authored by
Guillem L. Jara
Sylvestre Ledru
parent
179b977b93
commit
b22013ab79
+149
-3
@@ -1280,7 +1280,14 @@ fn test_ls_long_symlink_color() {
|
||||
];
|
||||
|
||||
// We are only interested in lines or the ls output that are symlinks. These start with "lrwx".
|
||||
let result = scene.ucmd().arg("-laR").arg("--color").arg(".").succeeds();
|
||||
// Use --file-type to ensure symlink targets are stat'd and colored
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-laR")
|
||||
.arg("--color")
|
||||
.arg("--file-type")
|
||||
.arg(".")
|
||||
.succeeds();
|
||||
let mut result_lines = result
|
||||
.stdout_str()
|
||||
.lines()
|
||||
@@ -1521,6 +1528,41 @@ fn test_ls_dangling_symlink_or_and_missing_colors() {
|
||||
assert_eq!(captures.name("target").unwrap().as_str(), "34");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_ls_symlink_to_dir_with_mi_colors() {
|
||||
// When LS_COLORS contains mi=, ln=, di=, ls -lp should stat the symlink target,
|
||||
// color the link with ln color, the target with di color, and append '/' to the target.
|
||||
use std::os::unix::fs::symlink;
|
||||
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
at.mkdir("target_dir");
|
||||
symlink("target_dir", at.plus("link")).unwrap();
|
||||
|
||||
let stdout = ts
|
||||
.ucmd()
|
||||
.env("LS_COLORS", "mi=41:ln=1;36:di=1;34")
|
||||
.arg("-lp")
|
||||
.arg("--color=always")
|
||||
.arg("link")
|
||||
.succeeds()
|
||||
.stdout_str()
|
||||
.to_string();
|
||||
|
||||
// Regex to capture link color and target color
|
||||
let color_regex = Regex::new(
|
||||
r"\x1b\[0m\x1b\[(?P<link>[0-9;]*)[m]link\x1b\[0m -> \x1b\[(?P<target>[0-9;]*)[m]target_dir\x1b\[0m/",
|
||||
)
|
||||
.unwrap();
|
||||
let captures = color_regex
|
||||
.captures(&stdout)
|
||||
.expect("failed to capture symlink colors");
|
||||
|
||||
assert_eq!(captures.name("link").unwrap().as_str(), "1;36");
|
||||
assert_eq!(captures.name("target").unwrap().as_str(), "1;34");
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Mirrors GNU `tests/ls/ls-misc.pl::sl-dangle4`.
|
||||
fn test_ls_dangling_symlink_ln_or_priority() {
|
||||
@@ -3400,6 +3442,110 @@ fn test_ls_indicator_style() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn test_ls_indicator_style_symlink_target_long() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.mkdir("dir");
|
||||
assert!(at.dir_exists("dir"));
|
||||
|
||||
at.symlink_dir("dir", "dir_link");
|
||||
assert!(at.is_symlink("dir_link"));
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--classify")
|
||||
.arg("-l")
|
||||
.arg("dir_link")
|
||||
.succeeds()
|
||||
.stdout_contains("dir_link -> ")
|
||||
.stdout_does_not_contain("dir_link@ -> ")
|
||||
.stdout_contains("/dir/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_ls_indicator_style_filetype_symlink_target_long() {
|
||||
// GNU `ls -l --file-type` does append `/` to a symlink target that resolves to a
|
||||
// directory unlike `ls -lp`
|
||||
use std::os::unix::fs::symlink;
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.mkdir("dir");
|
||||
assert!(at.dir_exists("dir"));
|
||||
|
||||
// Use a relative-path symlink so the displayed target matches GNU output.
|
||||
symlink("dir", at.plus("dir_link")).unwrap();
|
||||
assert!(at.is_symlink("dir_link"));
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--file-type")
|
||||
.arg("-l")
|
||||
.arg("dir_link")
|
||||
.succeeds()
|
||||
.stdout_contains("dir_link -> dir/")
|
||||
.stdout_does_not_contain("dir_link/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_ls_indicator_style_filetype_symlink_to_executable_target_long() {
|
||||
use std::fs;
|
||||
use std::os::unix::fs::{PermissionsExt, symlink};
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.touch("exec_target");
|
||||
let mut perms = fs::metadata(at.plus("exec_target")).unwrap().permissions();
|
||||
perms.set_mode(0o755);
|
||||
fs::set_permissions(at.plus("exec_target"), perms).unwrap();
|
||||
|
||||
symlink("exec_target", at.plus("link")).unwrap();
|
||||
assert!(at.is_symlink("link"));
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--file-type")
|
||||
.arg("-l")
|
||||
.arg("link")
|
||||
.succeeds()
|
||||
.stdout_contains("link -> exec_target")
|
||||
.stdout_does_not_contain("exec_target*");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_ls_indicator_style_slash_symlink_target_long() {
|
||||
// GNU `ls -lp` does NOT append `/` to a symlink target that resolves to a
|
||||
// directory — the slash indicator style only applies to real directories.
|
||||
use std::os::unix::fs::symlink;
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.mkdir("dir");
|
||||
assert!(at.dir_exists("dir"));
|
||||
|
||||
// Use a relative-path symlink so the displayed target matches GNU output.
|
||||
symlink("dir", at.plus("dir_link")).unwrap();
|
||||
assert!(at.is_symlink("dir_link"));
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-lp")
|
||||
.arg("dir_link")
|
||||
.succeeds()
|
||||
.stdout_contains("dir_link -> dir\n")
|
||||
.stdout_does_not_contain("dir_link/")
|
||||
.stdout_does_not_contain("-> dir/");
|
||||
}
|
||||
|
||||
// Essentially the same test as above, but only test symlinks and directories,
|
||||
// not pipes or sockets.
|
||||
#[test]
|
||||
@@ -5024,7 +5170,7 @@ fn test_symlink_target_extension_color() {
|
||||
at.touch("archive.tar.gz");
|
||||
at.relative_symlink_file("archive.tar.gz", "link");
|
||||
let out = ucmd
|
||||
.env("LS_COLORS", "*.tar.gz=31")
|
||||
.env("LS_COLORS", "*.tar.gz=31:or=33")
|
||||
.args(&["-l", "--color=always", "link"])
|
||||
.succeeds()
|
||||
.stdout_move_str();
|
||||
@@ -6045,7 +6191,7 @@ fn test_ls_hyperlink_symlink_target_handling() {
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&["-l", "--hyperlink", "--color"])
|
||||
.args(&["-l", "--hyperlink", "--color", "--file-type"])
|
||||
.succeeds();
|
||||
let output = result.stdout_str();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user