pkgcraft/shell/commands/
doinitd.rs

1use camino::Utf8PathBuf;
2use itertools::Either;
3use scallop::ExecStatus;
4
5use crate::eapi::Feature::ConsistentFileOpts;
6use crate::shell::get_build_mut;
7
8use super::{TryParseArgs, make_builtin};
9
10#[derive(clap::Parser, Debug)]
11#[command(
12    name = "doinitd",
13    long_about = "Install init scripts into /etc/init.d/."
14)]
15struct Command {
16    #[arg(required = true, value_name = "PATH")]
17    paths: Vec<Utf8PathBuf>,
18}
19
20pub(crate) fn run(args: &[&str]) -> scallop::Result<ExecStatus> {
21    let cmd = Command::try_parse_args(args)?;
22    let build = get_build_mut();
23    let dest = "/etc/init.d";
24    let opts = if build.eapi().has(ConsistentFileOpts) {
25        Either::Left(["-m0755"].into_iter())
26    } else {
27        Either::Right(build.exeopts.iter().map(|s| s.as_str()))
28    };
29    build
30        .install()
31        .dest(dest)?
32        .file_options(opts)
33        .files(&cmd.paths)?;
34    Ok(ExecStatus::Success)
35}
36
37make_builtin!("doinitd", doinitd_builtin);
38
39#[cfg(test)]
40mod tests {
41    use std::fs;
42
43    use crate::eapi::EAPIS_OFFICIAL;
44    use crate::shell::BuildData;
45    use crate::shell::test::FileTree;
46    use crate::test::assert_err_re;
47
48    use super::super::{
49        assert_invalid_cmd, cmd_scope_tests,
50        functions::{doinitd, exeopts},
51    };
52    use super::*;
53
54    cmd_scope_tests!("doinitd path/to/init/file");
55
56    #[test]
57    fn invalid_args() {
58        assert_invalid_cmd(doinitd, &[0]);
59
60        let _file_tree = FileTree::new();
61
62        // nonexistent
63        let r = doinitd(&["nonexistent"]);
64        assert_err_re!(r, "^invalid file: nonexistent: No such file or directory .*$");
65    }
66
67    #[test]
68    fn creation() {
69        let file_tree = FileTree::new();
70        let default_mode = 0o100755;
71        let custom_mode = 0o100777;
72
73        fs::File::create("pkgcraft").unwrap();
74        doinitd(&["pkgcraft"]).unwrap();
75        file_tree.assert(format!(
76            r#"
77            [[files]]
78            path = "/etc/init.d/pkgcraft"
79            mode = {default_mode}
80        "#
81        ));
82
83        // verify exeopts are respected depending on EAPI
84        for eapi in &*EAPIS_OFFICIAL {
85            BuildData::empty(eapi);
86            exeopts(&["-m0777"]).unwrap();
87            doinitd(&["pkgcraft"]).unwrap();
88            let mode = if eapi.has(ConsistentFileOpts) {
89                default_mode
90            } else {
91                custom_mode
92            };
93            file_tree.assert(format!(
94                r#"
95                [[files]]
96                path = "/etc/init.d/pkgcraft"
97                mode = {mode}
98            "#
99            ));
100        }
101    }
102}