mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
realpath: implement -E
This commit is contained in:
parent
32eef0687d
commit
cbccc9a456
4 changed files with 82 additions and 3 deletions
|
|
@ -7,6 +7,7 @@ realpath-help-strip = Only strip '.' and '..' components, but don't resolve symb
|
|||
realpath-help-zero = Separate output filenames with \0 rather than newline
|
||||
realpath-help-logical = resolve '..' components before symlinks
|
||||
realpath-help-physical = resolve symlinks as encountered (default)
|
||||
realpath-help-canonicalize = all but the last component must exist (default)
|
||||
realpath-help-canonicalize-existing = canonicalize by following every symlink in every component of the given name recursively, all components must exist
|
||||
realpath-help-canonicalize-missing = canonicalize by following every symlink in every component of the given name recursively, without requirements on components existence
|
||||
realpath-help-relative-to = print the resolved path relative to DIR
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ realpath-help-strip = Supprimer uniquement les composants '.' et '..', mais ne p
|
|||
realpath-help-zero = Séparer les noms de fichiers de sortie avec \0 plutôt qu'avec un saut de ligne
|
||||
realpath-help-logical = résoudre les composants '..' avant les liens symboliques
|
||||
realpath-help-physical = résoudre les liens symboliques rencontrés (par défaut)
|
||||
realpath-help-canonicalize = tous les composants sauf le dernier doivent exister (par défaut)
|
||||
realpath-help-canonicalize-existing = canonicaliser en suivant récursivement chaque lien symbolique dans chaque composant du nom donné, tous les composants doivent exister
|
||||
realpath-help-canonicalize-missing = canonicaliser en suivant récursivement chaque lien symbolique dans chaque composant du nom donné, sans exigences sur l'existence des composants
|
||||
realpath-help-relative-to = afficher le chemin résolu relativement à RÉP
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ const OPT_ZERO: &str = "zero";
|
|||
const OPT_PHYSICAL: &str = "physical";
|
||||
const OPT_LOGICAL: &str = "logical";
|
||||
const OPT_CANONICALIZE_MISSING: &str = "canonicalize-missing";
|
||||
const OPT_CANONICALIZE: &str = "canonicalize";
|
||||
const OPT_CANONICALIZE_EXISTING: &str = "canonicalize-existing";
|
||||
const OPT_RELATIVE_TO: &str = "relative-to";
|
||||
const OPT_RELATIVE_BASE: &str = "relative-base";
|
||||
|
|
@ -86,11 +87,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
let line_ending = LineEnding::from_zero_flag(matches.get_flag(OPT_ZERO));
|
||||
let quiet = matches.get_flag(OPT_QUIET);
|
||||
let logical = matches.get_flag(OPT_LOGICAL);
|
||||
let can_mode = if matches.get_flag(OPT_CANONICALIZE_EXISTING) {
|
||||
MissingHandling::Existing
|
||||
} else if matches.get_flag(OPT_CANONICALIZE_MISSING) {
|
||||
let can_mode = if matches.get_flag(OPT_CANONICALIZE_MISSING) {
|
||||
MissingHandling::Missing
|
||||
} else if matches.get_flag(OPT_CANONICALIZE_EXISTING) {
|
||||
// -e: all components must exist
|
||||
// Despite the name, MissingHandling::Existing requires all components to exist
|
||||
MissingHandling::Existing
|
||||
} else {
|
||||
// Default behavior (same as -E): all but last component must exist
|
||||
// MissingHandling::Normal allows the final component to not exist
|
||||
MissingHandling::Normal
|
||||
};
|
||||
let resolve_mode = if strip {
|
||||
|
|
@ -164,10 +169,19 @@ pub fn uu_app() -> Command {
|
|||
.help(translate!("realpath-help-physical"))
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(OPT_CANONICALIZE)
|
||||
.short('E')
|
||||
.long(OPT_CANONICALIZE)
|
||||
.overrides_with_all([OPT_CANONICALIZE_EXISTING, OPT_CANONICALIZE_MISSING])
|
||||
.help(translate!("realpath-help-canonicalize"))
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(OPT_CANONICALIZE_EXISTING)
|
||||
.short('e')
|
||||
.long(OPT_CANONICALIZE_EXISTING)
|
||||
.overrides_with_all([OPT_CANONICALIZE, OPT_CANONICALIZE_MISSING])
|
||||
.help(translate!("realpath-help-canonicalize-existing"))
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
|
|
@ -175,6 +189,7 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(OPT_CANONICALIZE_MISSING)
|
||||
.short('m')
|
||||
.long(OPT_CANONICALIZE_MISSING)
|
||||
.overrides_with_all([OPT_CANONICALIZE, OPT_CANONICALIZE_EXISTING])
|
||||
.help(translate!("realpath-help-canonicalize-missing"))
|
||||
.action(ArgAction::SetTrue),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -505,3 +505,65 @@ fn test_realpath_empty_string() {
|
|||
.fails()
|
||||
.code_is(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_realpath_canonicalize_options() {
|
||||
// Test that default, -E, and --canonicalize all allow nonexistent final component
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir("existing_dir");
|
||||
|
||||
let test_cases = [
|
||||
vec![], // default behavior
|
||||
vec!["-E"], // explicit -E flag
|
||||
vec!["--canonicalize"], // --canonicalize long form
|
||||
];
|
||||
|
||||
#[cfg(windows)]
|
||||
let expected_path = "existing_dir\\nonexistent";
|
||||
#[cfg(not(windows))]
|
||||
let expected_path = "existing_dir/nonexistent";
|
||||
|
||||
for args in test_cases {
|
||||
let mut ucmd = scene.ucmd();
|
||||
for arg in args {
|
||||
ucmd.arg(arg);
|
||||
}
|
||||
ucmd.arg("existing_dir/nonexistent")
|
||||
.succeeds()
|
||||
.stdout_contains(expected_path);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_realpath_canonicalize_vs_existing() {
|
||||
// Test difference between -E and -e, and option overrides
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir("existing_dir");
|
||||
|
||||
let test_cases = [
|
||||
(vec!["-E"], true), // -E should succeed with nonexistent final component
|
||||
(vec!["-e"], false), // -e should fail with nonexistent final component
|
||||
(vec!["-e", "-E"], true), // -E should override -e
|
||||
];
|
||||
|
||||
#[cfg(windows)]
|
||||
let expected_path = "existing_dir\\nonexistent";
|
||||
#[cfg(not(windows))]
|
||||
let expected_path = "existing_dir/nonexistent";
|
||||
|
||||
for (args, should_succeed) in test_cases {
|
||||
let mut ucmd = scene.ucmd();
|
||||
for arg in args {
|
||||
ucmd.arg(arg);
|
||||
}
|
||||
ucmd.arg("existing_dir/nonexistent");
|
||||
|
||||
if should_succeed {
|
||||
ucmd.succeeds().stdout_contains(expected_path);
|
||||
} else {
|
||||
ucmd.fails();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue