shadow_crypt_shell/decryption/
cli.rs1use std::path::PathBuf;
2
3use crate::errors::{WorkflowError, WorkflowResult};
4use clap::Parser;
5
6#[derive(Debug, Clone, Default, Parser)]
8#[command(
9 name = "unshadow",
10 about = "Decrypt shadow files",
11 version,
12 after_help = "Exit codes: 0 success; 1 operation failed; 2 invalid usage or input; \
13 3 authentication failure (wrong password or corrupted file)."
14)]
15pub struct DecryptionCliArgs {
16 #[arg(value_name = "FILE")]
18 pub input_files: Vec<String>,
19
20 #[arg(long = "output-dir", short = 'o', value_name = "DIR")]
22 pub output_dir: Option<PathBuf>,
23
24 #[arg(long = "password-file", value_name = "FILE")]
26 pub password_file: Option<PathBuf>,
27
28 #[arg(long = "force", short = 'f')]
30 pub force: bool,
31
32 #[arg(long = "quiet", short = 'q')]
34 pub quiet: bool,
35}
36
37pub fn get_cli_args(args: Vec<String>) -> WorkflowResult<DecryptionCliArgs> {
39 let cli_args = DecryptionCliArgs::try_parse_from(args).map_err(|e| {
40 if e.kind() == clap::error::ErrorKind::DisplayHelp
42 || e.kind() == clap::error::ErrorKind::DisplayVersion
43 {
44 eprintln!("{}", e);
46 std::process::exit(0);
47 }
48 WorkflowError::UserInput(e.to_string())
49 })?;
50
51 if cli_args.input_files.is_empty() {
52 return Err(WorkflowError::UserInput(
53 "No input files provided".to_string(),
54 ));
55 }
56
57 Ok(cli_args)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_parse_cli_args_with_files() {
66 let args = vec![
67 "unshadow".to_string(),
68 "file1.txt".to_string(),
69 "file2.txt".to_string(),
70 ];
71 let cli_args = get_cli_args(args).unwrap();
72 assert_eq!(
73 cli_args.input_files,
74 vec!["file1.txt".to_string(), "file2.txt".to_string()]
75 );
76 }
77
78 #[test]
79 fn test_parse_cli_args_with_single_file() {
80 let args = vec!["unshadow".to_string(), "file1.txt".to_string()];
81 let cli_args = get_cli_args(args).unwrap();
82 assert_eq!(cli_args.input_files, vec!["file1.txt".to_string()]);
83 }
84
85 #[test]
86 fn test_parse_cli_args_no_files() {
87 let args = vec!["unshadow".to_string()];
88 let result = get_cli_args(args);
89 assert!(result.is_err());
90 if let Err(WorkflowError::UserInput(msg)) = result {
91 assert_eq!(msg, "No input files provided");
92 } else {
93 panic!("Expected UserInput error");
94 }
95 }
96
97 #[test]
98 fn test_parse_cli_args_help() {
99 }
101}