aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/command/script_alias_command.rs
blob: ad26cd7e01ca53d6880b769163a28a4874806602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! ref: composer/src/Composer/Command/ScriptAliasCommand.php

use anyhow::Result;
use shirabe_external_packages::composer::pcre::preg::Preg;
use shirabe_external_packages::symfony::console::input::input_interface::InputInterface;
use shirabe_external_packages::symfony::console::output::output_interface::OutputInterface;
use shirabe_php_shim::{is_string, InvalidArgumentException, LogicException, PhpMixed};
use crate::command::base_command::BaseCommand;
use crate::console::input::input_argument::InputArgument;
use crate::console::input::input_option::InputOption;
use crate::util::platform::Platform;

pub struct ScriptAliasCommand {
    inner: BaseCommand,
    script: String,
    description: String,
    aliases: Vec<String>,
}

impl ScriptAliasCommand {
    pub fn new(script: String, description: Option<String>, aliases: Vec<String>) -> Result<Self> {
        let description = description.unwrap_or_else(|| format!("Runs the {} script as defined in composer.json", script));

        for alias in &aliases {
            if !is_string(&PhpMixed::String(alias.clone())) {
                return Err(InvalidArgumentException {
                    message: r#""scripts-aliases" element array values should contain only strings"#.to_string(),
                    code: 0,
                }.into());
            }
        }

        let mut inner = BaseCommand::new();
        inner.ignore_validation_errors();

        Ok(Self { inner, script, description, aliases })
    }

    pub fn configure(&mut self) {
        self.inner
            .set_name(&self.script)
            .set_description(&self.description)
            .set_aliases(self.aliases.clone())
            .set_definition(vec![
                InputOption::new("dev", None, Some(InputOption::VALUE_NONE), "Sets the dev mode.", None, vec![]),
                InputOption::new("no-dev", None, Some(InputOption::VALUE_NONE), "Disables the dev mode.", None, vec![]),
                InputArgument::new("args", Some(InputArgument::IS_ARRAY | InputArgument::OPTIONAL), "", None, vec![]),
            ])
            .set_help(
                "The <info>run-script</info> command runs scripts defined in composer.json:\n\n\
                <info>php composer.phar run-script post-update-cmd</info>\n\n\
                Read more at https://getcomposer.org/doc/03-cli.md#run-script-run"
            );
    }

    pub fn execute(&mut self, input: &dyn InputInterface, _output: &dyn OutputInterface) -> Result<i64> {
        let composer = self.inner.require_composer()?;

        let args = input.get_arguments();

        // TODO remove for Symfony 6+ as it is then in the interface
        if !input.has_to_string() {
            return Err(LogicException {
                message: format!("Expected an Input instance that is stringable, got {}", input.get_class_name()),
                code: 0,
            }.into());
        }

        let dev_mode = input.get_option("dev").as_bool().unwrap_or(false)
            || !input.get_option("no-dev").as_bool().unwrap_or(false);

        Platform::put_env("COMPOSER_DEV_MODE", if dev_mode { "1" } else { "0" });

        let script_alias_input = Preg::replace_limit(r"^\S+ ?", "", &input.to_string(), 1);
        let mut flags = indexmap::IndexMap::new();
        flags.insert("script-alias-input".to_string(), PhpMixed::String(script_alias_input));

        let args_value = args.get("args").cloned().unwrap_or(PhpMixed::Null);

        Ok(composer.get_event_dispatcher().dispatch_script(&self.script, dev_mode, args_value, flags)?)
    }
}