• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tamada / totebag / 9073633753

14 May 2024 04:12AM UTC coverage: 75.855% (-3.8%) from 79.637%
9073633753

push

github

web-flow
Merge pull request #19 from tamada/release/v0.3.0

Release/v0.3.0

208 of 343 new or added lines in 12 files covered. (60.64%)

9 existing lines in 3 files now uncovered.

754 of 994 relevant lines covered (75.86%)

4.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/cli.rs
1
use std::path::PathBuf;
2
use clap::{Parser, ValueEnum};
3

4
pub type Result<T> = std::result::Result<T, ToteError>;
5

6
#[derive(Parser, Debug)]
7
#[clap(
8
    version, author, about,
9
    arg_required_else_help = true,
10
)]
11
pub struct CliOpts {
12
    #[clap(short = 'm', long = "mode", default_value_t = RunMode::Auto, value_name = "MODE", required = false, ignore_case = true, value_enum, help = "Mode of operation.")]
1✔
13
    pub mode: RunMode,
×
14
    #[clap(short = 'o', short_alias = 'd', long = "output", alias = "dest", value_name = "DEST", required = false, help = "Output file in archive mode, or output directory in extraction mode")]
15
    pub output: Option<PathBuf>,
16
    #[clap(long = "to-archive-name-dir", help = "extract files to DEST/ARCHIVE_NAME directory (extract mode).", default_value_t = false)]
1✔
17
    pub to_archive_name_dir: bool,
×
18
    #[clap(short = 'n', long = "no-recursive", help = "No recursive directory (archive mode).", default_value_t = false)]
1✔
19
    pub no_recursive: bool,
×
20
    #[clap(short = 'v', long = "verbose", help = "Display verbose output.", default_value_t = false)]
1✔
21
    pub verbose: bool,
×
22
    #[clap(long, help = "Overwrite existing files.")]
23
    pub overwrite: bool,
×
24
    #[clap(value_name = "ARGUMENTS", help = "List of files or directories to be processed.")]
25
    pub args: Vec<PathBuf>,
5✔
26
}
27

28
impl CliOpts {
29
    pub fn run_mode(&mut self) -> Result<RunMode> {
7✔
30
        if self.args.len() == 0 {
7✔
NEW
31
            return Err(ToteError::NoArgumentsGiven)
×
32
        }
7✔
33
        if self.mode == RunMode::Auto {
7✔
34
            if is_all_args_archives(&self.args) {
3✔
35
                self.mode = RunMode::Extract;
1✔
36
                Ok(RunMode::Extract)
1✔
37
            } else {
38
                self.mode = RunMode::Archive;
2✔
39
                Ok(RunMode::Archive)
2✔
40
            }
41
        } else {
42
            Ok(self.mode)
4✔
43
        }
44
    }
7✔
45
}
46

47
fn is_all_args_archives(args: &[PathBuf]) -> bool {
4✔
48
    args.iter().all(|arg| {
13✔
49
        let name = arg.to_str().unwrap().to_lowercase();
13✔
50
        let exts = vec![".zip", ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".rar", ".jar", ".war", ".ear", "7z", ];
13✔
51
        for ext in exts.iter() {
65✔
52
            if name.ends_with(ext) {
65✔
53
                return true
11✔
54
            }
54✔
55
        }
56
        return false
2✔
57
    })
13✔
58
}
4✔
59

60
#[derive(Debug, Clone, ValueEnum, PartialEq, Copy)]
61
pub enum RunMode {
62
    Auto,
63
    Archive,
64
    Extract,
65
    List,
66
}
67

68
#[derive(Debug)]
69
pub enum ToteError {
70
    NoArgumentsGiven,
71
    FileNotFound(PathBuf),
72
    FileExists(PathBuf),
73
    IOError(std::io::Error),
74
    ArchiverError(String),
75
    UnsupportedFormat(String),
76
    UnknownFormat(String),
77
    UnknownError(String),
78
    SomeError(Box<dyn std::error::Error>)
79
}
80

81
#[cfg(test)]
82
mod tests {
83
    use std::path::PathBuf;
84
    use clap::Parser;
85

86
    use super::*;
87

88
    #[test]
89
    fn test_find_mode() {
1✔
90
        let mut cli1 = CliOpts::parse_from(&["totebag_test", "src", "LICENSE", "README.md", "Cargo.toml"]);
1✔
91
        let r1 = cli1.run_mode();
1✔
92
        assert!(r1.is_ok());
1✔
93
        assert_eq!(r1.unwrap(), RunMode::Archive);
1✔
94

95
        let mut cli2 = CliOpts::parse_from(&["totebag_test", "src", "LICENSE", "README.md", "hoge.zip"]);
1✔
96
        let r2 = cli2.run_mode();
1✔
97
        assert!(r2.is_ok());
1✔
98
        assert_eq!(cli2.run_mode().unwrap(), RunMode::Archive);
1✔
99

100
        let mut cli3 = CliOpts::parse_from(&["totebag_test", "src.zip", "LICENSE.tar", "README.tar.bz2", "hoge.rar"]);
1✔
101
        let r3 = cli3.run_mode();
1✔
102
        assert!(r3.is_ok());
1✔
103
        assert_eq!(cli3.run_mode().unwrap(), RunMode::Extract);
1✔
104

105
        let mut cli4 = CliOpts::parse_from(&["totebag_test", "src.zip", "LICENSE.tar", "README.tar.bz2", "hoge.rar", "--mode", "list"]);
1✔
106
        let r4 = cli3.run_mode();
1✔
107
        assert!(r4.is_ok());
1✔
108
        assert_eq!(cli4.run_mode().unwrap(), RunMode::List);
1✔
109
    }
1✔
110

111
    #[test]
112
    fn test_is_all_args_archives() {
1✔
113
        assert!(is_all_args_archives(&[PathBuf::from("test.zip"), PathBuf::from("test.tar"), PathBuf::from("test.tar.gz"), PathBuf::from("test.tgz"), PathBuf::from("test.tar.bz2"), PathBuf::from("test.tbz2"), PathBuf::from("test.rar")]));
1✔
114
    }
1✔
115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc