Completed
Pull Request — master (#181)
by
unknown
01:39
created

ChurnCommand::isValidGitFolder()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 1
1
<?php declare(strict_types = 1);
2
3
namespace Churn\Commands;
4
5
use Churn\Factories\ResultsRendererFactory;
6
use Churn\Logic\ResultsLogic;
7
use Churn\Managers\ProcessManager;
8
use Churn\Factories\ProcessFactory;
9
use Churn\Managers\FileManager;
10
use Symfony\Component\Console\Command\Command;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Churn\Configuration\Config;
16
use Symfony\Component\Process\Process;
17
use Symfony\Component\Yaml\Yaml;
18
use InvalidArgumentException;
19
20
/**
21
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
22
 */
23
class ChurnCommand extends Command
24
{
25
    /**
26
     * The results logic.
27
     * @var ResultsLogic
28
     */
29
    private $resultsLogic;
30
31
    /**
32
     * The process manager.
33
     * @var ProcessManager
34
     */
35
    private $processManager;
36
37
    /**
38
     * The renderer factory.
39
     * @var ResultsRendererFactory
40
     */
41
    private $renderFactory;
42
43
    /**
44
     * ChurnCommand constructor.
45
     * @param ResultsLogic           $resultsLogic   The results logic.
46
     * @param ProcessManager         $processManager The process manager.
47
     * @param ResultsRendererFactory $renderFactory  The Results Renderer Factory.
48
     */
49
    public function __construct(
50
        ResultsLogic $resultsLogic,
51
        ProcessManager $processManager,
52
        ResultsRendererFactory $renderFactory
53
    ) {
54
        parent::__construct();
55
        $this->resultsLogic = $resultsLogic;
56
        $this->processManager = $processManager;
57
        $this->renderFactory = $renderFactory;
58
    }
59
60
    /**
61
     * Configure the command
62
     * @return void
63
     */
64
    protected function configure()
65
    {
66
        $this->setName('run')
67
            ->addArgument('paths', InputArgument::IS_ARRAY, 'Path to source to check.')
68
            ->addOption('configuration', 'c', InputOption::VALUE_OPTIONAL, 'Path to the configuration file', 'churn.yml')  // @codingStandardsIgnoreLine
69
            ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format to use', 'text')
70
            ->setDescription('Check files')
71
            ->setHelp('Checks the churn on the provided path argument(s).');
72
    }
73
74
    /**
75
     * Execute the command
76
     * @param  InputInterface  $input  Input.
77
     * @param  OutputInterface $output Output.
78
     * @return void
79
     */
80
    protected function execute(InputInterface $input, OutputInterface $output)
81
    {
82
        $config = Config::create(Yaml::parse(@file_get_contents($input->getOption('configuration'))) ?? []);
83
84
        $filesCollection = (new FileManager($config->getFileExtensions(), $config->getFilesToIgnore()))
85
            ->getPhpFiles($this->getDirectoriesToScan($input, $config->getDirectoriesToScan()));
86
87
        $completedProcesses = $this->processManager->process(
88
            $filesCollection,
89
            new ProcessFactory($config->getCommitsSince()),
90
            $config->getParallelJobs()
91
        );
92
93
        $resultCollection = $this->resultsLogic->process(
94
            $completedProcesses,
95
            $config->getMinScoreToShow(),
96
            $config->getFilesToShow()
97
        );
98
99
        $renderer = $this->renderFactory->getRenderer($input->getOption('format'));
100
        $renderer->render($output, $resultCollection);
101
    }
102
103
    /**
104
     * Get the directories to scan.
105
     * @param InputInterface $input          Input Interface.
106
     * @param array          $dirsConfigured The directories configured to scan.
107
     * @throws InvalidArgumentException If paths argument invalid.
108
     * @return array When no directories to scan found.
109
     */
110
    private function getDirectoriesToScan(InputInterface $input, array $dirsConfigured): array
111
    {
112
        $dirsProvidedAsArgs = $input->getArgument('paths');
113
        foreach ($dirsProvidedAsArgs as $dir) {
114
            $this->isValidGitFolder($dir);
115
        }
116
117
        if (count($dirsProvidedAsArgs) > 0) {
118
            return $dirsProvidedAsArgs;
119
        }
120
121
        if (count($dirsConfigured) > 0) {
122
            return $dirsConfigured;
123
        }
124
125
        throw new InvalidArgumentException(
126
            'Provide the directories you want to scan as arguments, ' .
127
            'or configure them under "directoriesToScan" in your churn.yml file.'
128
        );
129
    }
130
131
    /**
132
     * Check if a path is a valid git folder.
133
     * @param string $path The path to check.
134
     * @throws InvalidArgumentException If path is not a valid git folder.
135
     * @return void
136
     */
137
    private function isValidGitFolder(string $path)
138
    {
139
        $commands = ['git status', 'git log'];
140
        foreach ($commands as $command) {
141
            $process = new Process($command, $path);
142
            $process->run();
143
            $process->wait();
144
            if ($process->getExitCode() === 128) {
145
                throw new InvalidArgumentException(
146
                    $path . ' is not a valid git folder, ' .
147
                    'or it has no commits yet.'
148
                );
149
            }
150
        }
151
    }
152
}
153