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

Branch   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 299
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 79.73%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 5
dl 0
loc 299
ccs 59
cts 74
cp 0.7973
rs 10
c 0
b 0
f 0

18 Methods

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