Completed
Push — master ( c1a738...2c88a4 )
by
unknown
02:35 queued 01:13
created

Diff   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 251
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 50.79%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 6
dl 0
loc 251
ccs 32
cts 63
cp 0.5079
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 11 1
A __construct() 0 6 1
B createFromCommand() 0 26 6
A parseOutputLines() 0 9 2
A getCaller() 0 4 1
A setRepository() 0 4 1
A getRepository() 0 4 1
A offsetExists() 0 4 1
A offsetGet() 0 4 2
A offsetSet() 0 8 2
A offsetUnset() 0 4 1
A count() 0 4 1
A current() 0 4 1
A next() 0 4 1
A key() 0 4 1
A valid() 0 4 1
A rewind() 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\Objects\Diff;
22
23
use GitElephant\Command\Caller\CallerInterface;
24
use GitElephant\Command\DiffCommand;
25
use GitElephant\Command\DiffTreeCommand;
26
use GitElephant\Repository;
27
use GitElephant\Utilities;
28
29
/**
30
 * Represent a collection of diffs between two trees
31
 *
32
 * @author Matteo Giachino <[email protected]>
33
 */
34
class Diff implements \ArrayAccess, \Countable, \Iterator
35
{
36
    /**
37
     * @var \GitElephant\Repository
38
     */
39
    private $repository;
40
41
    /**
42
     * the cursor position
43
     *
44
     * @var int
45
     */
46
    private $position;
47
48
    /**
49
     * DiffObject instances
50
     *
51
     * @var array<DiffObject>
52
     */
53
    private $diffObjects = [];
54
55
    /**
56
     * static generator to generate a Diff object
57
     *
58
     * @param \GitElephant\Repository                 $repository repository
59
     * @param null|string|\GitElephant\Objects\Commit $commit1    first commit
60
     * @param null|string|\GitElephant\Objects\Commit $commit2    second commit
61
     * @param null|string                             $path       path to consider
62
     *
63
     * @throws \RuntimeException
64
     * @throws \InvalidArgumentException
65
     * @throws \Symfony\Component\Process\Exception\RuntimeException
66
     * @return Diff
67
     */
68 2
    public static function create(
69
        Repository $repository,
70
        $commit1 = null,
71
        $commit2 = null,
72
        string $path = null
73
    ): \GitElephant\Objects\Diff\Diff {
74 2
        $commit = new self($repository);
75 2
        $commit->createFromCommand($commit1, $commit2, $path);
76
77 2
        return $commit;
78
    }
79
80
    /**
81
     * Class constructor
82
     * bare Diff object
83
     *
84
     * @param \GitElephant\Repository $repository  repository instance
85
     * @param array<DiffObject>                  $diffObjects  array of diff objects
86
     */
87 2
    public function __construct(Repository $repository, array $diffObjects = [])
88
    {
89 2
        $this->position = 0;
90 2
        $this->repository = $repository;
91 2
        $this->diffObjects = $diffObjects;
92 2
    }
93
94
    /**
95
     * get the commit properties from command
96
     *
97
     * @param string|null$commit1 commit 1
98
     * @param string|null$commit2 commit 2
99
     * @param string|null$path    path
100
     *
101
     * @throws \RuntimeException
102
     * @throws \Symfony\Component\Process\Exception\InvalidArgumentException
103
     * @throws \Symfony\Component\Process\Exception\LogicException
104
     * @throws \InvalidArgumentException
105
     * @throws \Symfony\Component\Process\Exception\RuntimeException
106
     * @see ShowCommand::commitInfo
107
     */
108 2
    public function createFromCommand($commit1 = null, $commit2 = null, $path = null): void
109
    {
110 2
        if (null === $commit1) {
111
            $commit1 = $this->getRepository()->getCommit();
112
        }
113
114 2
        if (is_string($commit1)) {
115
            $commit1 = $this->getRepository()->getCommit($commit1);
116
        }
117
118 2
        if ($commit2 === null) {
119 2
            if ($commit1->isRoot()) {
120
                $command = DiffTreeCommand::getInstance($this->repository)->rootDiff($commit1);
121
            } else {
122 2
                $command = DiffCommand::getInstance($this->repository)->diff($commit1);
123
            }
124
        } else {
125
            if (is_string($commit2)) {
126
                $commit2 = $this->getRepository()->getCommit($commit2);
127
            }
128
            $command = DiffCommand::getInstance($this->repository)->diff($commit1, $commit2, $path);
129
        }
130
131 2
        $outputLines = $this->getCaller()->execute($command)->getOutputLines();
132 2
        $this->parseOutputLines($outputLines);
133 2
    }
134
135
    /**
136
     * parse the output of a git command showing a commit
137
     *
138
     * @param array $outputLines output lines
139
     *
140
     * @throws \InvalidArgumentException
141
     */
142 2
    private function parseOutputLines(array $outputLines): void
143
    {
144 2
        $this->diffObjects = [];
145 2
        $splitArray = Utilities::pregSplitArray($outputLines, '/^diff --git SRC\/(.*) DST\/(.*)$/');
146
147 2
        foreach ($splitArray as $diffObjectLines) {
148 2
            $this->diffObjects[] = new DiffObject($diffObjectLines);
149
        }
150 2
    }
151
152
    /**
153
     * @return \GitElephant\Command\Caller\CallerInterface
154
     */
155 2
    private function getCaller(): CallerInterface
156
    {
157 2
        return $this->getRepository()->getCaller();
158
    }
159
160
    /**
161
     * Repository setter
162
     *
163
     * @param \GitElephant\Repository $repository the repository variable
164
     */
165
    public function setRepository(Repository $repository): void
166
    {
167
        $this->repository = $repository;
168
    }
169
170
    /**
171
     * Repository getter
172
     *
173
     * @return \GitElephant\Repository
174
     */
175 2
    public function getRepository(): \GitElephant\Repository
176
    {
177 2
        return $this->repository;
178
    }
179
180
    /**
181
     * ArrayAccess interface
182
     *
183
     * @param int $offset offset
184
     *
185
     * @return bool
186
     */
187
    public function offsetExists($offset): bool
188
    {
189
        return isset($this->diffObjects[$offset]);
190
    }
191
192
    /**
193
     * ArrayAccess interface
194
     *
195
     * @param int $offset offset
196
     *
197
     * @return null|mixed
198
     */
199 1
    public function offsetGet($offset)
200
    {
201 1
        return isset($this->diffObjects[$offset]) ? $this->diffObjects[$offset] : null;
202
    }
203
204
    /**
205
     * ArrayAccess interface
206
     *
207
     * @param int|null   $offset offset
208
     * @param mixed $value  value
209
     */
210
    public function offsetSet($offset, $value): void
211
    {
212
        if (is_null($offset)) {
213
            $this->diffObjects[] = $value;
214
        } else {
215
            $this->diffObjects[$offset] = $value;
216
        }
217
    }
218
219
    /**
220
     * ArrayAccess interface
221
     *
222
     * @param int $offset offset
223
     */
224
    public function offsetUnset($offset): void
225
    {
226
        unset($this->diffObjects[$offset]);
227
    }
228
229
    /**
230
     * Countable interface
231
     *
232
     * @return int
233
     */
234 2
    public function count(): int
235
    {
236 2
        return count($this->diffObjects);
237
    }
238
239
    /**
240
     * Iterator interface
241
     *
242
     * @return mixed
243
     */
244
    public function current()
245
    {
246
        return $this->diffObjects[$this->position];
247
    }
248
249
    /**
250
     * Iterator interface
251
     */
252
    public function next(): void
253
    {
254
        ++$this->position;
255
    }
256
257
    /**
258
     * Iterator interface
259
     *
260
     * @return int
261
     */
262
    public function key(): int
263
    {
264
        return $this->position;
265
    }
266
267
    /**
268
     * Iterator interface
269
     *
270
     * @return bool
271
     */
272
    public function valid(): bool
273
    {
274
        return isset($this->diffObjects[$this->position]);
275
    }
276
277
    /**
278
     * Iterator interface
279
     */
280
    public function rewind(): void
281
    {
282
        $this->position = 0;
283
    }
284
}
285