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

tamada / totebag / 12855166384

19 Jan 2025 04:12PM UTC coverage: 80.663% (-0.7%) from 81.322%
12855166384

push

github

web-flow
Merge pull request #35 from tamada/release/v0.7.0

Release/v0.7.0

438 of 628 new or added lines in 18 files covered. (69.75%)

15 existing lines in 7 files now uncovered.

1339 of 1660 relevant lines covered (80.66%)

14.11 hits per line

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

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

4
use totebag::{IgnoreType, Result, RunMode, ToteError};
5
use totebag::format::is_all_args_archives;
6

7
#[derive(Parser, Debug)]
8
#[clap(
9
    version, author, about,
10
    arg_required_else_help = true,
11
)]
12
pub struct CliOpts {
13
    #[clap(flatten)]
14
    pub extractors: ExtractorOpts,
15

16
    #[clap(flatten)]
17
    pub archivers: ArchiverOpts,
18

19
    #[clap(long = "level", help = "Specify the log level", default_value_t = LogLevel::Warn, ignore_case = true, value_enum)]
1✔
NEW
20
    pub level: LogLevel,
×
21

22
    #[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✔
23
    pub mode: RunMode,
×
24

25
    #[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")]
26
    pub output: Option<PathBuf>,
27

28
    #[clap(long, help = "Overwrite existing files.")]
NEW
29
    pub overwrite: bool,
×
30

31
    #[clap(value_name = "ARGUMENTS", help = r###"List of files or directories to be processed.
32
If archive mode, the archive file name can specify at the first argument.
33
If the frist argument was not the archive name, the default archive name `totebag.zip` is applied.
34
"###)]
35
    pub args: Vec<String>,
5✔
36
}
37

38
#[derive(Parser, Debug)]
39
pub struct ListOpts {
40
    #[clap(short, long, help = "List with long format.")]
NEW
41
    pub long: bool,
×
42
}
43

44
#[derive(Parser, Debug)]
45
pub struct ArchiverOpts {
46
    #[clap(
47
        short = 'C', long = "dir", value_name = "DIR", required = false,
48
        default_value = ".", help = "Specify the base directory for archiving or extracting."
49
    )]
50
    pub base_dir: PathBuf,
×
51

52
    #[clap(short = 'i', long = "ignore-types", value_name = "IGNORE_TYPES", value_delimiter = ',', help = "Specify the ignore type.")]
NEW
53
    pub ignores: Vec<IgnoreType>,
×
54

55
    #[clap(short = 'n', long = "no-recursive", help = "No recursive directory (archive mode).", default_value_t = false)]
1✔
56
    pub no_recursive: bool,
×
57

58
}
59

60
#[derive(Parser, Debug)]
61
pub struct ExtractorOpts {
62
    #[clap(long = "to-archive-name-dir", help = "extract files to DEST/ARCHIVE_NAME directory (extract mode).", default_value_t = false)]
1✔
NEW
63
    pub to_archive_name_dir: bool,
×
64
}
65

66
#[derive(Parser, Debug, ValueEnum, Clone, PartialEq, Copy)]
67
pub enum LogLevel {
68
    Error,
69
    Warn,
70
    Info,
71
    Debug,
72
    Trace,
73
}
74

75
impl CliOpts {
76
    pub fn run_mode(&mut self) -> Result<RunMode> {
7✔
77
        if self.args.len() == 0 {
7✔
NEW
78
            return Err(ToteError::NoArgumentsGiven)
×
79
        }
7✔
80
        if self.mode == RunMode::Auto {
7✔
81
            if is_all_args_archives(&self.args.iter().map(PathBuf::from).collect::<Vec<PathBuf>>()) {
3✔
82
                self.mode = RunMode::Extract;
1✔
83
                Ok(RunMode::Extract)
1✔
84
            } else {
85
                self.mode = RunMode::Archive;
2✔
86
                Ok(RunMode::Archive)
2✔
87
            }
88
        } else {
89
            Ok(self.mode)
4✔
90
        }
91
    }
7✔
92
}
93

94
#[cfg(test)]
95
mod tests {
96
    use clap::Parser;
97

98
    use super::*;
99

100
    #[test]
101
    fn test_find_mode() {
1✔
102
        let mut cli1 = CliOpts::parse_from(&["totebag_test", "src", "LICENSE", "README.md", "Cargo.toml"]);
1✔
103
        let r1 = cli1.run_mode();
1✔
104
        assert!(r1.is_ok());
1✔
105
        assert_eq!(r1.unwrap(), RunMode::Archive);
1✔
106

107
        let mut cli2 = CliOpts::parse_from(&["totebag_test", "src", "LICENSE", "README.md", "hoge.zip"]);
1✔
108
        let r2 = cli2.run_mode();
1✔
109
        assert!(r2.is_ok());
1✔
110
        assert_eq!(cli2.run_mode().unwrap(), RunMode::Archive);
1✔
111

112
        let mut cli3 = CliOpts::parse_from(&["totebag_test", "src.zip", "LICENSE.tar", "README.tar.bz2", "hoge.rar"]);
1✔
113
        let r3 = cli3.run_mode();
1✔
114
        assert!(r3.is_ok());
1✔
115
        assert_eq!(cli3.run_mode().unwrap(), RunMode::Extract);
1✔
116

117
        let mut cli4 = CliOpts::parse_from(&["totebag_test", "src.zip", "LICENSE.tar", "README.tar.bz2", "hoge.rar", "--mode", "list"]);
1✔
118
        let r4 = cli3.run_mode();
1✔
119
        assert!(r4.is_ok());
1✔
120
        assert_eq!(cli4.run_mode().unwrap(), RunMode::List);
1✔
121
    }
1✔
122
}
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