Branch   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 80%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 5
dl 0
loc 302
ccs 60
cts 75
cp 0.8
rs 10
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 14 1
A createFromOutputLine() 0 8 1
A checkout() 0 8 2
A __construct() 0 7 1
A createFromCommand() 0 16 3
A parseOutputLine() 0 14 2
A getMatches() 0 19 4
A __toString() 0 4 1
A setName() 0 4 1
A getName() 0 4 1
A setSha() 0 4 1
A getSha() 0 4 1
A setCurrent() 0 4 1
A getCurrent() 0 4 1
A setComment() 0 4 1
A getComment() 0 4 1
A setFullRef() 0 4 1
A getFullRef() 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;
22
23
use GitElephant\Command\BranchCommand;
24
use GitElephant\Exception\InvalidBranchNameException;
25
use GitElephant\Repository;
26
27
/**
28
 * An object representing a git branch
29
 *
30
 * @author Matteo Giachino <[email protected]>
31
 */
32
class Branch extends NodeObject implements TreeishInterface
33
{
34
    /**
35
     * current checked out branch
36
     *
37
     * @var bool
38
     */
39
    private $current = false;
40
41
    /**
42
     * branch name
43
     *
44
     * @var string
45
     */
46
    private $name;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
47
48
    /**
49
     * sha
50
     *
51
     * @var string
52
     */
53
    private $sha;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
54
55
    /**
56
     * branch comment
57
     *
58
     * @var string
59
     */
60
    private $comment;
61
62
    /**
63
     * the full branch reference
64
     *
65
     * @var string
66
     */
67
    private $fullRef;
68
69
    /**
70
     * Creates a new branch on the repository and returns it
71
     *
72
     * @param \GitElephant\Repository $repository repository instance
73
     * @param string                  $name       branch name
74
     * @param string                  $startPoint branch to start from
75
     *
76
     * @throws \RuntimeException
77
     * @throws \Symfony\Component\Process\Exception\LogicException
78
     * @throws \Symfony\Component\Process\Exception\InvalidArgumentException
79
     * @throws \Symfony\Component\Process\Exception\RuntimeException
80
     * @return \GitElephant\Objects\Branch
81
     */
82 33
    public static function create(
83
        Repository $repository,
84
        string $name,
85
        string $startPoint = null
86
    ): \GitElephant\Objects\Branch {
87
        /** @var BranchCommand */
88 33
        $branchCommand = BranchCommand::getInstance($repository);
89
90
        $repository
91 33
            ->getCaller()
92 33
            ->execute($branchCommand->create($name, $startPoint));
93
94 33
        return new self($repository, $name);
95
    }
96
97
    /**
98
     * static generator to generate a single commit from output of command.show service
99
     *
100
     * @param \GitElephant\Repository $repository repository
101
     * @param string                  $outputLine output line
102
     *
103
     * @throws \InvalidArgumentException
104
     * @return Branch
105
     */
106 13
    public static function createFromOutputLine(Repository $repository, string $outputLine): \GitElephant\Objects\Branch
107
    {
108 13
        $matches = static::getMatches($outputLine);
109 13
        $branch = new self($repository, $matches[1]);
110 13
        $branch->parseOutputLine($outputLine);
111
112 13
        return $branch;
113
    }
114
115
    /**
116
     * @param \GitElephant\Repository $repository repository instance
117
     * @param string|TreeishInterface $name       branch name
118
     * @param bool                    $create     like checkout -b, create a branch and check it out
119
     *
120
     * @throws \RuntimeException
121
     * @throws \Symfony\Component\Process\Exception\RuntimeException
122
     * @return Branch
123
     */
124 2
    public static function checkout(Repository $repository, $name, $create = false): \GitElephant\Objects\Branch
125
    {
126 2
        $branch = $create ? self::create($repository, $name) : new self($repository, $name);
0 ignored issues
show
Bug introduced by
It seems like $name defined by parameter $name on line 124 can also be of type object<GitElephant\Objects\TreeishInterface>; however, GitElephant\Objects\Branch::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like $name defined by parameter $name on line 124 can also be of type object<GitElephant\Objects\TreeishInterface>; however, GitElephant\Objects\Branch::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
127
128 1
        $repository->checkout($branch);
129
130 1
        return $branch;
131
    }
132
133
    /**
134
     * Class constructor
135
     *
136
     * @param \GitElephant\Repository $repository repository instance
137
     * @param string                  $name       branch name
138
     *
139
     * @throws \RuntimeException
140
     * @throws \InvalidArgumentException
141
     * @throws \GitElephant\Exception\InvalidBranchNameException
142
     * @throws \Symfony\Component\Process\Exception\RuntimeException
143
     */
144 42
    public function __construct(Repository $repository, string $name)
145
    {
146 42
        $this->repository = $repository;
147 42
        $this->name = trim($name);
148 42
        $this->fullRef = 'refs/heads/' . $name;
149 42
        $this->createFromCommand();
150 42
    }
151
152
    /**
153
     * get the branch properties from command
154
     *
155
     * @throws \InvalidArgumentException
156
     */
157 42
    private function createFromCommand(): void
158
    {
159 42
        $command = BranchCommand::getInstance($this->getRepository())->listBranches();
160 42
        $outputLines = $this->repository->getCaller()->execute($command)->getOutputLines(true);
161 42
        foreach ($outputLines as $outputLine) {
162 42
            $matches = static::getMatches($outputLine);
163
164 42
            if ($this->name === $matches[1]) {
165 42
                $this->parseOutputLine($outputLine);
166
167 42
                return;
168
            }
169
        }
170
171 1
        throw new InvalidBranchNameException(sprintf('The %s branch doesn\'t exists', $this->name));
172
    }
173
174
    /**
175
     * parse an output line from the BranchCommand::singleInfo command
176
     *
177
     * @param string $branchString an output line for a branch
178
     *
179
     * @throws \InvalidArgumentException
180
     */
181 42
    public function parseOutputLine(string $branchString): void
182
    {
183 42
        if (preg_match('/^\* (.*)/', $branchString, $matches)) {
184 15
            $this->current = true;
185 15
            $branchString = substr($branchString, 2);
186
        } else {
187 33
            $branchString = trim($branchString);
188
        }
189
190 42
        $matches = static::getMatches($branchString);
191 42
        $this->name = $matches[1];
192 42
        $this->sha = $matches[2];
193 42
        $this->comment = $matches[3];
194 42
    }
195
196
    /**
197
     * get the matches from an output line
198
     *
199
     * @param string $branchString branch line output
200
     *
201
     * @throws \InvalidArgumentException
202
     * @return array
203
     */
204 45
    public static function getMatches(string $branchString): array
205
    {
206 45
        $branchString = trim($branchString);
207
        $regexList = [
208 45
            '/^\*?\ *?(\S+)\ +(\S{40})\ +(.+)$/',
209
            '/^\*?\ *?\(.*(detached).*\)\ +(\S{40})\ +(.+)$/',
210
        ];
211
212 45
        $matches = [];
213 45
        while (empty($matches) and $regex = array_pop($regexList)) {
214 45
            preg_match($regex, trim($branchString), $matches);
215
        }
216
217 45
        if (empty($matches)) {
218 2
            throw new \InvalidArgumentException(sprintf('the branch string is not valid: %s', $branchString));
219
        }
220
221 43
        return array_map('trim', $matches);
222
    }
223
224
    /**
225
     * toString magic method
226
     *
227
     * @return string the sha
228
     */
229 4
    public function __toString(): string
230
    {
231 4
        return $this->getSha();
232
    }
233
234
    /**
235
     * name setter
236
     *
237
     * @param string $name the branch name
238
     */
239
    public function setName(string $name): void
240
    {
241
        $this->name = $name;
242
    }
243
244
    /**
245
     * name setter
246
     *
247
     * @return string
248
     */
249 14
    public function getName(): string
250
    {
251 14
        return $this->name;
252
    }
253
254
    /**
255
     * sha setter
256
     *
257
     * @param string $sha the sha of the branch
258
     */
259
    public function setSha(string $sha): void
260
    {
261
        $this->sha = $sha;
262
    }
263
264
    /**
265
     * sha getter
266
     *
267
     * @return string
268
     */
269 9
    public function getSha(): string
270
    {
271 9
        return $this->sha;
272
    }
273
274
    /**
275
     * current setter
276
     *
277
     * @param bool $current whether if the branch is the current or not
278
     */
279
    public function setCurrent(bool $current): void
280
    {
281
        $this->current = $current;
282
    }
283
284
    /**
285
     * current getter
286
     *
287
     * @return bool
288
     */
289 5
    public function getCurrent(): bool
290
    {
291 5
        return $this->current;
292
    }
293
294
    /**
295
     * comment setter
296
     *
297
     * @param string $comment the branch comment
298
     */
299
    public function setComment(string $comment): void
300
    {
301
        $this->comment = $comment;
302
    }
303
304
    /**
305
     * comment getter
306
     *
307
     * @return string
308
     */
309 1
    public function getComment(): string
310
    {
311 1
        return $this->comment;
312
    }
313
314
    /**
315
     * fullref setter
316
     *
317
     * @param string $fullRef full git reference of the branch
318
     */
319
    public function setFullRef(string $fullRef): void
320
    {
321
        $this->fullRef = $fullRef;
322
    }
323
324
    /**
325
     * fullRef getter
326
     *
327
     * @return string
328
     */
329 2
    public function getFullRef(): string
330
    {
331 2
        return $this->fullRef;
332
    }
333
}
334