Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
99.16% covered (success)
99.16%
118 / 119
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Install
99.16% covered (success)
99.16%
118 / 119
83.33% covered (warning)
83.33%
5 / 6
25
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
1 / 1
2
 execute
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
8
 configureTarget
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
4.02
 getRequestedResources
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 installResources
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2020-2024 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Command;
10
11use InvalidArgumentException;
12use OCA\Libresign\AppInfo\Application;
13use OCA\Libresign\Exception\LibresignException;
14use OCA\Libresign\Service\Install\InstallService;
15use OCA\Libresign\Service\Install\InstallTarget;
16use OCP\IAppConfig;
17use OCP\IConfig;
18use Psr\Log\LoggerInterface;
19use Symfony\Component\Console\Input\InputInterface;
20use Symfony\Component\Console\Input\InputOption;
21use Symfony\Component\Console\Output\OutputInterface;
22
23class Install extends Base {
24    public function __construct(
25        InstallService $installService,
26        LoggerInterface $logger,
27        private IAppConfig $appConfig,
28        private IConfig $config,
29    ) {
30        parent::__construct($installService, $logger);
31    }
32
33    #[\Override]
34    protected function configure(): void {
35        $this
36            ->setName('libresign:install')
37            ->setDescription('Install files')
38            ->addOption(
39                name: 'all',
40                shortcut: null,
41                mode: InputOption::VALUE_NONE,
42                description: 'All binaries'
43            )
44            ->addOption(
45                name: 'jsignpdf',
46                shortcut: null,
47                mode: InputOption::VALUE_NONE,
48                description: 'JSignPdf'
49            )
50            ->addOption(
51                name: 'pdftk',
52                shortcut: null,
53                mode: InputOption::VALUE_NONE,
54                description: 'PDFtk'
55            )
56            ->addOption(
57                name: 'cfssl',
58                shortcut: null,
59                mode: InputOption::VALUE_NONE,
60                description: 'CFSSL'
61            )
62            ->addOption(
63                name: 'java',
64                shortcut: null,
65                mode: InputOption::VALUE_NONE,
66                description: 'Java'
67            )
68            ->addOption(
69                name: 'architecture',
70                shortcut: null,
71                mode: InputOption::VALUE_REQUIRED,
72                description: 'x86_64/amd64 or aarch64/arm64'
73            )
74            ->addOption(
75                name: 'distro',
76                shortcut: null,
77                mode: InputOption::VALUE_REQUIRED,
78                description: 'linux or alpine-linux'
79            )
80            ->addOption(
81                name: 'all-distros',
82                shortcut: null,
83                mode: InputOption::VALUE_NONE,
84                description: 'Will download java to all available distros'
85            );
86        if ($this->config->getSystemValue('debug', false) === true) {
87            $this->addOption(
88                name: 'use-local-cert',
89                shortcut: null,
90                mode: InputOption::VALUE_NONE,
91                description: 'Use local cert'
92            );
93        }
94    }
95
96    #[\Override]
97    protected function execute(InputInterface $input, OutputInterface $output): int {
98        $this->installService->setOutput($output);
99
100        try {
101            $this->configureTarget($input);
102
103            if ($input->hasOption('use-local-cert') && $input->getOption('use-local-cert')) {
104                $this->installService->useDevelopmentTrust();
105            }
106
107            $resources = $this->getRequestedResources($input);
108            if ($resources === []) {
109                $output->writeln('<error>Please inform what you want to install</error>');
110                $output->writeln('<error>--all to all</error>');
111                $output->writeln('<error>--help to check the available options</error>');
112                return 1;
113            }
114
115            $this->installResources($resources, $input);
116
117            if (in_array('cfssl', $resources, true)) {
118                $currentEngine = $this->appConfig->getValueString(
119                    Application::APP_ID,
120                    'certificate_engine',
121                    'openssl',
122                );
123                if ($currentEngine !== 'cfssl') {
124                    $output->writeln('<comment>To use CFSSL, set the engine to cfssl with:</comment> config:app:set libresign certificate_engine --value=cfssl');
125                }
126            }
127        } catch (LibresignException $e) {
128            $this->installService->saveErrorMessage($e->getMessage());
129            $this->logger->error('LibreSign dependency installation failed', [
130                'exception' => $e,
131            ]);
132            throw $e;
133        } catch (\Exception $e) {
134            $this->logger->error('Unexpected error while installing LibreSign dependencies', [
135                'exception' => $e,
136            ]);
137            throw $e;
138        }
139
140        $output->writeln('Finished with success.');
141
142        return 0;
143    }
144
145    private function configureTarget(InputInterface $input): void {
146        $architecture = (string)$input->getOption('architecture');
147        if ($architecture !== '') {
148            $this->installService->setArchitecture(
149                InstallTarget::normalizeArchitecture($architecture),
150            );
151        }
152
153        $distro = (string)$input->getOption('distro');
154        if ($distro !== '') {
155            if ($input->getOption('all-distros')) {
156                throw new InvalidArgumentException('--distro and --all-distros cannot be used together.');
157            }
158            $this->installService->setDistro($distro);
159        }
160    }
161
162    /**
163     * @return list<string>
164     */
165    private function getRequestedResources(InputInterface $input): array {
166        if ($input->getOption('all')) {
167            return array_values($this->installService->getAvailableResources());
168        }
169
170        $resources = [];
171        foreach ($this->installService->getAvailableResources() as $resource) {
172            if ($input->getOption($resource)) {
173                $resources[] = $resource;
174            }
175        }
176        return $resources;
177    }
178
179    /**
180     * @param list<string> $resources
181     */
182    private function installResources(array $resources, InputInterface $input): void {
183        foreach ($resources as $resource) {
184            if ($resource === 'java' && $input->getOption('all-distros')) {
185                $currentDistro = $this->installService->getLinuxDistributionToDownloadJava();
186                if ($currentDistro === 'linux') {
187                    $distros = ['alpine-linux', 'linux'];
188                } else {
189                    $distros = ['linux', 'alpine-linux'];
190                }
191                foreach ($distros as $distro) {
192                    $this->installService->setDistro($distro);
193                    $this->installService->install($resource);
194                }
195                continue;
196            }
197
198            $this->installService->install($resource);
199        }
200    }
201}