1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-01 05:27:45 +00:00

backup_control: Match abbreviated backup options

Add a function that takes a user-supplied backup option and checks if it
matches any of the valid backup options. This is because GNU allows to
abbreviate backup options, as long as they are valid and unambiguous.

In case a backup option is either invalid or ambiguous, an error type is
returned that contains a formatted error string for output to the user.
This commit is contained in:
Andreas Hartmann 2021-06-26 20:13:51 +02:00
parent 3b8f135842
commit fa0b4861b9

View file

@ -7,7 +7,7 @@ pub static BACKUP_CONTROL_VALUES: &[&str] = &[
"simple", "never", "numbered", "t", "existing", "nil", "none", "off",
];
pub static BACKUP_CONTROL_LONG_HELP: &str =
pub static BACKUP_CONTROL_LONG_HELP: &str =
"The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.
The version control method may be selected via the --backup option or through
the VERSION_CONTROL environment variable. Here are the values:
@ -65,6 +65,50 @@ pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>)
}
}
/// Match a backup option string to a `BackupMode`.
///
/// The GNU manual specifies that abbreviations to options are valid as long as
/// they aren't ambiguous. This function matches the given `method` argument
/// against all valid backup options (via `starts_with`), and returns a valid
/// [`BackupMode`] if exactly one backup option matches the `method` given.
///
/// `origin` is required in order to format the generated error message
/// properly, when an error occurs.
///
///
/// # Errors
///
/// If `method` is ambiguous (i.e. may resolve to multiple backup modes) or
/// invalid, an error is returned. The error contains the formatted error string
/// which may then be passed to the [`show_usage_error`] macro.
fn match_method(method: &str, origin: &str) -> Result<BackupMode, String> {
let x = vec!["simple", "never", "numbered", "t",
"existing", "nil", "none", "off"];
let matches: Vec<&&str> = x.iter()
.filter(|val| val.starts_with(method))
.collect();
if matches.len() == 1 {
match *matches[0] {
"simple" | "never" => Ok(BackupMode::SimpleBackup),
"numbered" | "t" => Ok(BackupMode::NumberedBackup),
"existing" | "nil" => Ok(BackupMode::ExistingBackup),
"none" | "off" => Ok(BackupMode::NoBackup),
_ => panic!(), // cannot happen as we must have exactly one match
// from the list above.
}
} else {
let error_type = if matches.len() == 0 { "invalid" } else { "ambiguous" };
Err(format!(
"{0} argument {1} for {2}
Valid arguments are:
- none, off
- simple, never
- existing, nil
- numbered, t", error_type, method, origin))
}
}
pub fn get_backup_path(
backup_mode: BackupMode,
backup_path: &Path,