aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/command/suggests_command.rs
blob: 0350dd19012da401f8783f8d594513902978c6cb (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! ref: composer/src/Composer/Command/SuggestsCommand.php

use crate::command::base_command::{BaseCommand, BaseCommandData, HasBaseCommandData};
use crate::composer::Composer;
use crate::console::input::input_argument::InputArgument;
use crate::console::input::input_option::InputOption;
use crate::installer::suggested_packages_reporter::SuggestedPackagesReporter;
use crate::io::io_interface::IOInterface;
use crate::repository::installed_repository::InstalledRepository;
use crate::repository::platform_repository::PlatformRepository;
use crate::repository::root_package_repository::RootPackageRepository;
use anyhow::Result;
use shirabe_external_packages::symfony::component::console::input::input_interface::InputInterface;
use shirabe_external_packages::symfony::component::console::output::output_interface::OutputInterface;
use shirabe_php_shim::{PhpMixed, empty, in_array};

#[derive(Debug)]
pub struct SuggestsCommand {
    base_command_data: BaseCommandData,
}

impl SuggestsCommand {
    pub fn configure(&mut self) {
        // TODO(cli-completion): suggest_installed_package() for `packages` argument
        self
            .set_name("suggests")
            .set_description("Shows package suggestions")
            .set_definition(&[
                InputOption::new("by-package", None, Some(InputOption::VALUE_NONE), "Groups output by suggesting package (default)", None).unwrap().into(),
        InputOption::new("by-suggestion", None, Some(InputOption::VALUE_NONE), "Groups output by suggested package", None).unwrap().into(),
        InputOption::new("all", Some(PhpMixed::String("a".to_string())), Some(InputOption::VALUE_NONE), "Show suggestions from all dependencies, including transitive ones", None).unwrap().into(),
        InputOption::new("list", None, Some(InputOption::VALUE_NONE), "Show only list of suggested package names", None).unwrap().into(),
        InputOption::new("no-dev", None, Some(InputOption::VALUE_NONE), "Exclude suggestions from require-dev packages", None).unwrap().into(),
        InputArgument::new("packages", Some(InputArgument::IS_ARRAY | InputArgument::OPTIONAL), "Packages that you want to list suggestions from.", None).unwrap().into(),
            ])
            .set_help(
                "\nThe <info>%command.name%</info> command shows a sorted list of suggested packages.\n\nRead more at https://getcomposer.org/doc/03-cli.md#suggests",
            );
    }

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

        let mut installed_repos = vec![Box::new(RootPackageRepository::new(
            composer.get_package().clone(),
        ))];

        let locker = composer.get_locker();
        if locker.is_locked() {
            installed_repos.push(Box::new(PlatformRepository::new(
                vec![],
                locker.get_platform_overrides(),
            )));
            installed_repos.push(Box::new(locker.get_locked_repository(
                !input.get_option("no-dev").as_bool().unwrap_or(false),
            )));
        } else {
            installed_repos.push(Box::new(PlatformRepository::new(
                vec![],
                composer.get_config().borrow().get("platform"),
            )));
            installed_repos.push(Box::new(
                composer.get_repository_manager().get_local_repository(),
            ));
        }

        let installed_repo = InstalledRepository::new(installed_repos);
        let mut reporter = SuggestedPackagesReporter::new(self.get_io());

        let filter = input.get_argument("packages");
        let mut packages = installed_repo.get_packages();
        packages.push(composer.get_package());
        for package in &packages {
            if !empty(&filter)
                && !in_array(
                    PhpMixed::String(package.get_name().to_string()),
                    &filter,
                    false,
                )
            {
                continue;
            }
            reporter.add_suggestions_from_package(package);
        }

        let mut mode = SuggestedPackagesReporter::MODE_BY_PACKAGE;

        if input.get_option("by-suggestion").as_bool().unwrap_or(false) {
            mode = SuggestedPackagesReporter::MODE_BY_SUGGESTION;
        }
        if input.get_option("by-package").as_bool().unwrap_or(false) {
            mode |= SuggestedPackagesReporter::MODE_BY_PACKAGE;
        }
        if input.get_option("list").as_bool().unwrap_or(false) {
            mode = SuggestedPackagesReporter::MODE_LIST;
        }

        reporter.output(
            mode,
            &installed_repo,
            if empty(&filter) && !input.get_option("all").as_bool().unwrap_or(false) {
                Some(composer.get_package())
            } else {
                None
            },
        );

        Ok(0)
    }
}

impl HasBaseCommandData for SuggestsCommand {
    fn base_command_data(&self) -> &BaseCommandData {
        &self.base_command_data
    }

    fn base_command_data_mut(&mut self) -> &mut BaseCommandData {
        &mut self.base_command_data
    }
}