Completed
Pull Request — master (#166)
by
unknown
112:06 queued 110:39
created

Caller   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 97.62%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 2
dl 0
loc 137
ccs 41
cts 42
cp 0.9762
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
B execute() 0 43 7
A getOutput() 0 4 1
A getOutputLines() 0 15 4
A getRawOutput() 0 4 1
1
<?php
2
3
/**
4
 * GitElephant - An abstraction layer for git written in PHP
5
 * Copyright (C) 2013  Matteo Giachino
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see [http://www.gnu.org/licenses/].
19
 */
20
21
namespace GitElephant\Command\Caller;
22
23
use GitElephant\Exception\InvalidRepositoryPathException;
24
use Symfony\Component\Process\Process;
25
26
/**
27
 * Caller
28
 *
29
 * @author Matteo Giachino <[email protected]>
30
 * @author Tim Bernhard <[email protected]>
31
 */
32
class Caller extends AbstractCaller
33
{
34
    /**
35
     * the repository path
36
     *
37
     * @var string
38
     */
39
    private $repositoryPath;
40
41
    /**
42
     * raw output
43
     *
44
     * @var string
45
     */
46
    private $rawOutput;
47
48
    /**
49
     * Class constructor
50
     *
51
     * @param string|null   $gitPath the physical path to the git binary
52
     * @param string        $repositoryPath the physical base path for the repository
53
     */
54 107
    public function __construct($gitPath, $repositoryPath)
55
    {
56 107
        if (is_null($gitPath)) {
57
            // unix only!
58 107
            $gitPath = exec('which git');
59
        }
60 107
        $this->setBinaryPath($gitPath);
61 107
        if (!is_dir($repositoryPath)) {
62 1
            throw new InvalidRepositoryPathException($repositoryPath);
63
        }
64 107
        $this->repositoryPath = $repositoryPath;
65 107
    }
66
67
    /**
68
     * Executes a command
69
     *
70
     * @param string $cmd               the command to execute
71
     * @param bool   $git               if the command is git or a generic command
72
     * @param string $cwd               the directory where the command must be executed
73
     * @param array  $acceptedExitCodes exit codes accepted to consider the command execution successful
74
     *
75
     * @throws \RuntimeException
76
     * @throws \Symfony\Component\Process\Exception\InvalidArgumentException
77
     * @throws \Symfony\Component\Process\Exception\ProcessTimedOutException
78
     * @throws \Symfony\Component\Process\Exception\RuntimeException
79
     * @throws \Symfony\Component\Process\Exception\LogicException
80
     * @return Caller
81
     */
82 102
    public function execute(
83
        string $cmd,
84
        bool $git = true,
85
        string $cwd = null,
86
        array $acceptedExitCodes = [0]
87
    ): CallerInterface {
88 102
        if ($git) {
89 102
            $cmd = $this->getBinaryPath() . ' ' . $cmd;
90
        }
91
92 102
        if (stripos(PHP_OS, 'WIN') !== 0) {
93
            // We rely on the C locale in all output we parse.
94 102
            $cmd = 'LC_ALL=C ' . $cmd;
95
        }
96
97 102
        if (is_null($cwd) || !is_dir($cwd)) {
98 102
            $cwd = $this->repositoryPath;
99
        }
100
101 102
        if (method_exists(Process::class, 'fromShellCommandline')) {
102 102
            $process = Process::fromShellCommandline($cmd, $cwd);
103
        } else {
104
            // compatibility fix required for symfony/process versions prior to v4.2.
105
            $process = new Process($cmd, $cwd);
106
        }
107
108 102
        $process->setTimeout(15000);
109 102
        $process->run();
110 102
        if (!in_array($process->getExitCode(), $acceptedExitCodes)) {
111 1
            $text = 'Exit code: ' . $process->getExitCode();
112 1
            $text .= ' while executing: "' . $cmd;
113 1
            $text .= '" with reason: ' . $process->getErrorOutput();
114 1
            $text .= "\n" . $process->getOutput();
115 1
            throw new \RuntimeException($text);
116
        }
117
        
118 101
        $this->rawOutput = $process->getOutput();
119
        // rtrim values
120 101
        $values = array_map('rtrim', explode(PHP_EOL, $process->getOutput()));
121 101
        $this->outputLines = $values;
122
123 101
        return $this;
124
    }
125
126
    /**
127
     * returns the output of the last executed command
128
     *
129
     * @return string
130
     */
131 7
    public function getOutput(): string
132
    {
133 7
        return implode("\n", $this->outputLines);
134
    }
135
136
    /**
137
     * returns the output of the last executed command as an array of lines
138
     *
139
     * @param bool $stripBlankLines remove the blank lines
140
     *
141
     * @return array
142
     */
143 91
    public function getOutputLines(bool $stripBlankLines = false): array
144
    {
145 91
        if ($stripBlankLines) {
146 81
            $output = [];
147 81
            foreach ($this->outputLines as $line) {
148 81
                if ('' !== $line) {
149 81
                    $output[] = $line;
150
                }
151
            }
152
153 81
            return $output;
154
        }
155
156 45
        return $this->outputLines;
157
    }
158
159
    /**
160
     * Get RawOutput
161
     *
162
     * @return string
163
     */
164 1
    public function getRawOutput(): string
165
    {
166 1
        return $this->rawOutput;
167
    }
168
}
169