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

tamada / sibling / 21945130899

12 Feb 2026 11:40AM UTC coverage: 71.867% (+7.5%) from 64.338%
21945130899

Pull #44

github

tamada
refactor: add unit tests for error display in sibling operations
Pull Request #44: refactor: reorganize code structure and update dependencies for improved functionality

262 of 349 new or added lines in 7 files covered. (75.07%)

3 existing lines in 2 files now uncovered.

562 of 782 relevant lines covered (71.87%)

3.95 hits per line

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

59.26
/cli/src/cli.rs
1
use std::path::PathBuf;
2

3
use clap::{Parser, ValueEnum};
4

5
use crate::{LogLevel, minisib};
6

7
#[derive(Debug, Parser)]
8
#[clap(version, author, about, arg_required_else_help = true)]
9
pub struct CliOpts {
10
    #[clap(flatten)]
11
    pub(crate) p_opts: PrintingOpts,
12

13
    #[clap(flatten)]
14
    pub(crate) nexter_opts: NexterOpts,
15

16
    #[clap(flatten)]
17
    pub(crate) init_script: InitOpts,
18

19
    #[clap(flatten)]
20
    pub(crate) log_opts: LogOpts,
21

22
    #[arg(
23
        short = 'w',
24
        long = "working-dir",
25
        help = "set the current working directory.",
26
        hide = true,
27
        value_name = "DIR",
28
        long_help = "This option is applied before any other processing. Therefore, other options that specify paths should use the relative path from this option value. If this option is not specified, the current directory is used."
29
    )]
30
    pub(crate) cwd: Option<PathBuf>,
31

32
    #[arg(index = 1, help = "the target directory", value_name = "DIR")]
33
    pub dirs: Vec<PathBuf>,
34

35
    #[cfg(debug_assertions)]
36
    #[clap(flatten)]
37
    pub(crate) compopts: CompletionOpts,
38

39
    #[clap(subcommand)]
40
    pub(crate) minisib: Option<minisib::MiniSibCommand>,
41
}
42

43
impl CliOpts {
44
    pub fn init(&mut self) {
1✔
45
        self.log_opts.init();
1✔
46
        if let Some(cwd) = &self.cwd
1✔
47
            && let Err(e) = std::env::set_current_dir(cwd)
1✔
48
        {
NEW
49
            log::error!("Failed to set current directory to {cwd:?}: {e}, use \".\"");
×
50
        }
1✔
51
        if self.dirs.is_empty() {
1✔
52
            match std::env::current_dir() {
1✔
53
                Ok(cwd) => self.dirs.push(cwd),
1✔
NEW
54
                Err(e) => {
×
NEW
55
                    log::error!("Failed to get current directory: {e}");
×
NEW
56
                    eprintln!("Error: failed to determine current working directory: {e}");
×
NEW
57
                    std::process::exit(1);
×
58
                }
59
            }
NEW
60
        }
×
61
    }
1✔
62
}
63

64
#[derive(Parser, Debug)]
65
pub(crate) struct LogOpts {
66
    #[arg(
67
        long,
68
        help = "set the log level",
69
        value_enum,
70
        default_value_t = LogLevel::Warn,
71
        value_name = "LEVEL",
72
        ignore_case = true
73
    )]
74
    pub log: LogLevel,
75
}
76

77
impl LogOpts {
78
    pub fn init(&self) {
1✔
79
        use LogLevel::{Debug, Error, Info, Trace, Warn};
80
        if std::env::var_os("RUST_LOG").is_none() {
1✔
81
            unsafe {
82
                match self.log {
1✔
NEW
83
                    Error => std::env::set_var("RUST_LOG", "error"),
×
84
                    Warn => std::env::set_var("RUST_LOG", "warn"),
1✔
NEW
85
                    Info => std::env::set_var("RUST_LOG", "info"),
×
NEW
86
                    Debug => std::env::set_var("RUST_LOG", "debug"),
×
NEW
87
                    Trace => std::env::set_var("RUST_LOG", "trace"),
×
88
                };
89
            }
NEW
90
        }
×
91
        env_logger::init();
1✔
92
        log::info!("Log level set to {:?}", self.log);
1✔
93
    }
1✔
94
}
95

96
#[derive(Parser, Debug)]
97
pub(crate) struct InitOpts {
98
    #[arg(
99
        long,
100
        help = "generate the initialize script for the shell",
101
        value_name = "SHELL",
102
        hide = true,
103
        default_missing_value = "bash"
104
    )]
105
    pub init: Option<String>,
106
}
107

108
#[derive(Parser, Debug)]
109
pub(crate) struct NexterOpts {
110
    #[arg(
111
        short,
112
        long,
113
        help = "specify the number of times to execute sibling",
114
        value_name = "COUNT",
115
        default_value_t = 1
116
    )]
117
    pub step: i32,
118

119
    #[arg(short = 't', long = "type", help = "specify the nexter type", value_enum, default_value_t = sibling::NexterType::Next, value_name = "TYPE", ignore_case = true)]
120
    pub nexter: sibling::NexterType,
121

122
    #[arg(
123
        short,
124
        long,
125
        help = "directory list from file, if FILE is \"-\", reads from stdin.",
126
        value_name = "FILE"
127
    )]
128
    pub input: Option<String>,
129

130
    #[arg(
131
        short = 'a',
132
        long,
133
        help = "Set the targets to all directories from the given list. By default, the sibling skips non-existent directories.",
134
        default_value_t = false
135
    )]
136
    pub all: bool,
137
}
138

139
#[cfg(debug_assertions)]
140
#[derive(Parser, Debug)]
141
pub(crate) struct CompletionOpts {
142
    #[arg(
143
        long = "generate-completion-files",
144
        help = "Generate completion files",
145
        hide = true
146
    )]
147
    pub(crate) completion: bool,
148

149
    #[arg(
150
        long = "completion-out-dir",
151
        value_name = "DIR",
152
        default_value = "assets/completions",
153
        help = "Output directory of completion files",
154
        hide = true
155
    )]
156
    pub(crate) dest: PathBuf,
157
}
158

159
#[derive(Debug, Clone, PartialEq, Eq, ValueEnum)]
160
pub enum Format {
161
    Json,
162
    Csv,
163
    List,
164
    Default,
165
}
166

167
#[derive(Debug, Parser)]
168
pub(crate) struct PrintingOpts {
169
    #[arg(
170
        short, long,
171
        help = "print the result in the specified format",
172
        default_value_t = Format::Default,
173
        value_enum,
174
    )]
175
    pub format: Format,
176

177
    #[arg(
178
        short = 'A',
179
        long,
180
        help = "print the directory name in the absolute path",
181
        default_value_t = false
182
    )]
183
    pub absolute: bool,
184

185
    #[arg(
186
        short,
187
        long,
188
        help = "print the progress of traversing directories",
189
        default_value_t = false
190
    )]
191
    pub progress: bool,
192

193
    #[arg(
194
        short = 'P',
195
        long,
196
        help = "print parent directory, when no more sibling directories are found",
197
        default_value_t = false
198
    )]
199
    pub parent: bool,
200
}
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