convert ArgMatches to Options

    1. impl Options {
    2. fn from_matches(matches: &ArgMatches) -> CopyResult<Options> {
    3. let not_implemented_opts = vec![
    4. OPT_COPY_CONTENTS,
    5. OPT_SPARSE,
    6. #[cfg(not(any(windows, unix)))]
    7. OPT_ONE_FILE_SYSTEM,
    8. OPT_CONTEXT,
    9. #[cfg(windows)]
    10. OPT_FORCE,
    11. ];
    12. for not_implemented_opt in not_implemented_opts {
    13. if matches.is_present(not_implemented_opt) {
    14. return Err(Error::NotImplemented(not_implemented_opt.to_string()));
    15. }
    16. }
    17. let recursive = matches.is_present(OPT_RECURSIVE)
    18. || matches.is_present(OPT_RECURSIVE_ALIAS)
    19. || matches.is_present(OPT_ARCHIVE);
    20. let backup = matches.is_present(OPT_BACKUP) || (matches.occurrences_of(OPT_SUFFIX) > 0);
    21. // Parse target directory options
    22. let no_target_dir = matches.is_present(OPT_NO_TARGET_DIRECTORY);
    23. let target_dir = matches
    24. .value_of(OPT_TARGET_DIRECTORY)
    25. .map(ToString::to_string);
    26. // Parse attributes to preserve
    27. let preserve_attributes: Vec<Attribute> = if matches.is_present(OPT_PRESERVE) {
    28. match matches.values_of(OPT_PRESERVE) {
    29. None => DEFAULT_ATTRIBUTES.to_vec(),
    30. Some(attribute_strs) => {
    31. let mut attributes = Vec::new();
    32. for attribute_str in attribute_strs {
    33. if attribute_str == "all" {
    34. attributes = add_all_attributes();
    35. break;
    36. } else {
    37. attributes.push(Attribute::from_str(attribute_str)?);
    38. }
    39. }
    40. attributes
    41. }
    42. }
    43. } else if matches.is_present(OPT_ARCHIVE) {
    44. // --archive is used. Same as --preserve=all
    45. add_all_attributes()
    46. } else if matches.is_present(OPT_NO_DEREFERENCE_PRESERVE_LINKS) {
    47. vec![Attribute::Links]
    48. } else if matches.is_present(OPT_PRESERVE_DEFAULT_ATTRIBUTES) {
    49. DEFAULT_ATTRIBUTES.to_vec()
    50. } else {
    51. vec![]
    52. };
    53. let options = Options {
    54. attributes_only: matches.is_present(OPT_ATTRIBUTES_ONLY),
    55. copy_contents: matches.is_present(OPT_COPY_CONTENTS),
    56. copy_mode: CopyMode::from_matches(matches),
    57. dereference: matches.is_present(OPT_DEREFERENCE),
    58. // No dereference is set with -p, -d and --archive
    59. no_dereference: matches.is_present(OPT_NO_DEREFERENCE)
    60. || matches.is_present(OPT_NO_DEREFERENCE_PRESERVE_LINKS)
    61. || matches.is_present(OPT_ARCHIVE),
    62. one_file_system: matches.is_present(OPT_ONE_FILE_SYSTEM),
    63. overwrite: OverwriteMode::from_matches(matches),
    64. parents: matches.is_present(OPT_PARENTS),
    65. backup_suffix: matches.value_of(OPT_SUFFIX).unwrap().to_string(),
    66. update: matches.is_present(OPT_UPDATE),
    67. verbose: matches.is_present(OPT_VERBOSE),
    68. strip_trailing_slashes: matches.is_present(OPT_STRIP_TRAILING_SLASHES),
    69. reflink: matches.is_present(OPT_REFLINK),
    70. reflink_mode: {
    71. if let Some(reflink) = matches.value_of(OPT_REFLINK) {
    72. match reflink {
    73. "always" => ReflinkMode::Always,
    74. "auto" => ReflinkMode::Auto,
    75. value => {
    76. return Err(Error::InvalidArgument(format!(
    77. "invalid argument '{}' for \'reflink\'",
    78. value
    79. )));
    80. }
    81. }
    82. } else {
    83. ReflinkMode::Never
    84. }
    85. },
    86. backup,
    87. no_target_dir,
    88. preserve_attributes,
    89. recursive,
    90. target_dir,
    91. };
    92. Ok(options)
    93. }
    94. }