This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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; |
||
22 | |||
23 | use GitElephant\Command\BranchCommand; |
||
24 | use GitElephant\Command\Caller\Caller; |
||
25 | use GitElephant\Command\Caller\CallerInterface; |
||
26 | use GitElephant\Command\CatFileCommand; |
||
27 | use GitElephant\Command\FetchCommand; |
||
28 | use GitElephant\Command\LogCommand; |
||
29 | use GitElephant\Command\LsTreeCommand; |
||
30 | use GitElephant\Command\MainCommand; |
||
31 | use GitElephant\Command\MergeCommand; |
||
32 | use GitElephant\Command\PullCommand; |
||
33 | use GitElephant\Command\PushCommand; |
||
34 | use GitElephant\Command\RemoteCommand; |
||
35 | use GitElephant\Command\ResetCommand; |
||
36 | use GitElephant\Command\RevParseCommand; |
||
37 | use GitElephant\Command\StashCommand; |
||
38 | use GitElephant\Command\SubmoduleCommand; |
||
39 | use GitElephant\Command\TagCommand; |
||
40 | use GitElephant\Objects\Author; |
||
41 | use GitElephant\Objects\Branch; |
||
42 | use GitElephant\Objects\Commit; |
||
43 | use GitElephant\Objects\Diff\Diff; |
||
44 | use GitElephant\Objects\Log; |
||
45 | use GitElephant\Objects\LogRange; |
||
46 | use GitElephant\Objects\NodeObject; |
||
47 | use GitElephant\Objects\Remote; |
||
48 | use GitElephant\Objects\Tag; |
||
49 | use GitElephant\Objects\Tree; |
||
50 | use GitElephant\Objects\TreeishInterface; |
||
51 | use GitElephant\Objects\TreeObject; |
||
52 | use GitElephant\Status\Status; |
||
53 | use GitElephant\Status\StatusIndex; |
||
54 | use GitElephant\Status\StatusWorkingTree; |
||
55 | use Symfony\Component\Filesystem\Filesystem; |
||
56 | use Symfony\Component\Finder\Finder; |
||
57 | use Symfony\Component\Finder\SplFileInfo; |
||
58 | use Symfony\Component\Process\Exception\InvalidArgumentException; |
||
59 | |||
60 | /** |
||
61 | * Repository |
||
62 | * |
||
63 | * Base Class for repository operations |
||
64 | * |
||
65 | * @author Matteo Giachino <[email protected]> |
||
66 | * @author Dhaval Patel <[email protected]> |
||
67 | * @author Kirk Madera <[email protected]> |
||
68 | */ |
||
69 | class Repository |
||
70 | { |
||
71 | /** |
||
72 | * the repository path |
||
73 | * |
||
74 | * @var string |
||
75 | */ |
||
76 | private $path; |
||
77 | |||
78 | /** |
||
79 | * the caller instance |
||
80 | * |
||
81 | * @var \GitElephant\Command\Caller\CallerInterface |
||
82 | */ |
||
83 | private $caller; |
||
84 | |||
85 | /** |
||
86 | * A general repository name |
||
87 | * |
||
88 | * @var string the repository name |
||
89 | */ |
||
90 | private $name; |
||
91 | |||
92 | /** |
||
93 | * A list of global configs to apply to every command |
||
94 | * |
||
95 | * @var array |
||
96 | */ |
||
97 | private $globalConfigs = []; |
||
98 | |||
99 | /** |
||
100 | * A list of global options to apply to every command |
||
101 | * |
||
102 | * @var array |
||
103 | */ |
||
104 | private $globalOptions = []; |
||
105 | |||
106 | /** |
||
107 | * A list of global arguments to apply to every command |
||
108 | * |
||
109 | * @var array |
||
110 | */ |
||
111 | private $globalCommandArguments = []; |
||
112 | |||
113 | /** |
||
114 | * Class constructor |
||
115 | * |
||
116 | * @param string $repositoryPath the path of the git repository |
||
117 | * @param string|null $binary the path to the git binary |
||
118 | * @param string $name a repository name |
||
119 | * |
||
120 | * @throws Exception\InvalidRepositoryPathException |
||
121 | */ |
||
122 | 108 | public function __construct($repositoryPath, string $binary = null, $name = null) |
|
123 | { |
||
124 | 108 | $this->path = $repositoryPath; |
|
125 | 108 | $this->caller = new Caller($binary, $repositoryPath); |
|
126 | 108 | $this->name = $name; |
|
127 | 108 | } |
|
128 | |||
129 | /** |
||
130 | * Factory method |
||
131 | * |
||
132 | * @param string $repositoryPath the path of the git repository |
||
133 | * @param string|null $binary the path to the git binary |
||
134 | * @param string $name a repository name |
||
135 | * |
||
136 | * @return \GitElephant\Repository |
||
137 | */ |
||
138 | 107 | public static function open($repositoryPath, string $binary = null, $name = null): \GitElephant\Repository |
|
139 | { |
||
140 | 107 | return new self($repositoryPath, $binary, $name); |
|
141 | } |
||
142 | |||
143 | /** |
||
144 | * create a repository from a remote git url, or a local filesystem |
||
145 | * and save it in a temp folder |
||
146 | * |
||
147 | * @param string|Repository $git the git remote url, or the filesystem path |
||
148 | * @param string|null $repositoryPath path |
||
149 | * @param string|null $binary the path to the git binary |
||
150 | * @param string|null $name repository name |
||
151 | * |
||
152 | * @throws \RuntimeException |
||
153 | * @throws \Symfony\Component\Filesystem\Exception\IOException |
||
154 | * @return Repository |
||
155 | */ |
||
156 | 1 | public static function createFromRemote( |
|
157 | $git, |
||
158 | $repositoryPath = null, |
||
159 | string $binary = null, |
||
160 | $name = null |
||
161 | ): \GitElephant\Repository { |
||
162 | 1 | if (null === $repositoryPath) { |
|
163 | 1 | $tempDir = realpath(sys_get_temp_dir()); |
|
164 | 1 | $repositoryPath = sprintf('%s%s%s', $tempDir, DIRECTORY_SEPARATOR, sha1(uniqid())); |
|
165 | 1 | $fs = new Filesystem(); |
|
166 | 1 | $fs->mkdir($repositoryPath); |
|
167 | } |
||
168 | 1 | $repository = new Repository($repositoryPath, $binary, $name); |
|
169 | 1 | if ($git instanceof Repository) { |
|
170 | $git = $git->getPath(); |
||
171 | } |
||
172 | 1 | $repository->cloneFrom($git, $repositoryPath); |
|
173 | 1 | $repository->checkoutAllRemoteBranches(); |
|
174 | |||
175 | 1 | return $repository; |
|
176 | } |
||
177 | |||
178 | /** |
||
179 | * Init the repository |
||
180 | * |
||
181 | * @param bool $bare created a bare repository |
||
182 | * |
||
183 | * @throws \RuntimeException |
||
184 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
185 | * @throws InvalidArgumentException |
||
186 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
187 | * @return Repository |
||
188 | */ |
||
189 | 95 | public function init($bare = false): self |
|
190 | { |
||
191 | 95 | $this->caller->execute(MainCommand::getInstance($this)->init($bare)); |
|
192 | |||
193 | 95 | return $this; |
|
194 | } |
||
195 | |||
196 | /** |
||
197 | * Stage the working tree content |
||
198 | * |
||
199 | * @param string|NodeObject $path the path to store |
||
200 | * |
||
201 | * @throws \RuntimeException |
||
202 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
203 | * @throws InvalidArgumentException |
||
204 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
205 | * @return Repository |
||
206 | */ |
||
207 | 91 | public function stage($path = '.'): self |
|
208 | { |
||
209 | 91 | $this->caller->execute(MainCommand::getInstance($this)->add($path)); |
|
0 ignored issues
–
show
|
|||
210 | |||
211 | 91 | return $this; |
|
212 | } |
||
213 | |||
214 | /** |
||
215 | * Unstage a tree content |
||
216 | * |
||
217 | * @param string|NodeObject $path the path to unstage |
||
218 | * |
||
219 | * @throws \RuntimeException |
||
220 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
221 | * @throws InvalidArgumentException |
||
222 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
223 | * @return Repository |
||
224 | */ |
||
225 | 2 | public function unstage($path): self |
|
226 | { |
||
227 | 2 | if ($this->caller instanceof Caller) { |
|
228 | 2 | $this->caller->execute(MainCommand::getInstance($this)->unstage($path), true, null, [0, 1]); |
|
0 ignored issues
–
show
It seems like
$path defined by parameter $path on line 225 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Command\MainCommand::unstage() 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...
|
|||
229 | } else { |
||
230 | $this->caller->execute(MainCommand::getInstance($this)->unstage($path), true, null); |
||
0 ignored issues
–
show
It seems like
$path defined by parameter $path on line 225 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Command\MainCommand::unstage() 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...
|
|||
231 | } |
||
232 | |||
233 | 2 | return $this; |
|
234 | } |
||
235 | |||
236 | /** |
||
237 | * Move a file/directory |
||
238 | * |
||
239 | * @param string|NodeObject $from source path |
||
240 | * @param string|NodeObject $to destination path |
||
241 | * |
||
242 | * @throws \RuntimeException |
||
243 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
244 | * @throws \InvalidArgumentException |
||
245 | * @throws InvalidArgumentException |
||
246 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
247 | * @return Repository |
||
248 | */ |
||
249 | 1 | public function move($from, $to): self |
|
250 | { |
||
251 | 1 | $this->caller->execute(MainCommand::getInstance($this)->move($from, $to)); |
|
252 | |||
253 | 1 | return $this; |
|
254 | } |
||
255 | |||
256 | /** |
||
257 | * Remove a file/directory |
||
258 | * |
||
259 | * @param string|NodeObject $path the path to remove |
||
260 | * @param bool $recursive recurse |
||
261 | * @param bool $force force |
||
262 | * |
||
263 | * @throws \RuntimeException |
||
264 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
265 | * @throws \InvalidArgumentException |
||
266 | * @throws InvalidArgumentException |
||
267 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
268 | * @return Repository |
||
269 | */ |
||
270 | 1 | public function remove($path, $recursive = false, $force = false): self |
|
271 | { |
||
272 | 1 | $this->caller->execute(MainCommand::getInstance($this)->remove($path, $recursive, $force)); |
|
273 | |||
274 | 1 | return $this; |
|
275 | } |
||
276 | |||
277 | /** |
||
278 | * Commit content to the repository, eventually staging all unstaged content |
||
279 | * |
||
280 | * @param string $message the commit message |
||
281 | * @param bool $stageAll whether to stage on not everything before commit |
||
282 | * @param string|null $ref the reference to commit to (checkout -> commit -> checkout previous) |
||
283 | * @param string|Author $author override the author for this commit |
||
284 | * @param bool $allowEmpty override the author for this commit |
||
285 | * @param \DateTimeInterface|null $date |
||
286 | * |
||
287 | * @throws \RuntimeException |
||
288 | * @throws \InvalidArgumentException |
||
289 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
290 | * @return Repository |
||
291 | */ |
||
292 | 86 | public function commit( |
|
293 | string $message, |
||
294 | $stageAll = false, |
||
295 | $ref = null, |
||
296 | $author = null, |
||
297 | $allowEmpty = false, |
||
298 | \DateTimeInterface $date = null |
||
299 | ): self { |
||
300 | 86 | $currentBranch = null; |
|
301 | 86 | if (!is_null($ref)) { |
|
302 | 1 | $currentBranch = $this->getMainBranch(); |
|
303 | 1 | $this->checkout($ref); |
|
304 | } |
||
305 | 86 | if ($stageAll) { |
|
306 | 84 | $this->stage(); |
|
307 | } |
||
308 | 86 | $this->caller->execute( |
|
309 | 86 | MainCommand::getInstance($this)->commit($message, $stageAll, $author, $allowEmpty, $date) |
|
310 | ); |
||
311 | 86 | if (!is_null($ref)) { |
|
312 | 1 | $this->checkout($currentBranch); |
|
0 ignored issues
–
show
It seems like
$currentBranch defined by null on line 300 can be null ; however, GitElephant\Repository::checkout() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
Loading history...
|
|||
313 | } |
||
314 | |||
315 | 86 | return $this; |
|
316 | } |
||
317 | |||
318 | /** |
||
319 | * rev-parse command - often used to return a commit tag. |
||
320 | * |
||
321 | * @param array $options the options to apply to rev-parse |
||
322 | * @param string|NodeObject|Commit $arg the argument (may be a branch head, etc) |
||
323 | * |
||
324 | * @throws \RuntimeException |
||
325 | * @throws \InvalidArgumentException |
||
326 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
327 | * @return array |
||
328 | */ |
||
329 | 1 | public function revParse($arg = null, array $options = []): array |
|
330 | { |
||
331 | 1 | $this->caller->execute(RevParseCommand::getInstance()->revParse($arg, $options)); |
|
0 ignored issues
–
show
It seems like
$arg defined by parameter $arg on line 329 can also be of type object<GitElephant\Objects\Commit> or object<GitElephant\Objects\NodeObject> ; however, GitElephant\Command\RevParseCommand::revParse() does only seem to accept object<GitElephant\Objects\Branch>|string|null , 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...
|
|||
332 | |||
333 | 1 | return array_map('trim', $this->caller->getOutputLines(true)); |
|
334 | } |
||
335 | |||
336 | /** |
||
337 | * Check if this is a bare repository |
||
338 | * |
||
339 | * @return boolean |
||
340 | */ |
||
341 | 1 | public function isBare(): bool |
|
342 | { |
||
343 | 1 | $options = [RevParseCommand::OPTION_IS_BARE_REPOSIORY]; |
|
344 | 1 | $this->caller->execute(RevParseCommand::getInstance()->revParse(null, $options)); |
|
345 | |||
346 | 1 | return trim($this->caller->getOutput()) === 'true'; |
|
347 | } |
||
348 | |||
349 | /** |
||
350 | * @param TreeishInterface|Commit|string $arg |
||
351 | * @param array $options |
||
352 | */ |
||
353 | 2 | public function reset($arg, $options): void |
|
354 | { |
||
355 | 2 | $this->caller->execute(ResetCommand::getInstance($this)->reset($arg, $options)); |
|
356 | 2 | } |
|
357 | |||
358 | /** |
||
359 | * Get the repository status |
||
360 | * |
||
361 | * @return Status |
||
362 | */ |
||
363 | 6 | public function getStatus(): \GitElephant\Status\Status |
|
364 | { |
||
365 | 6 | return Status::get($this); |
|
366 | } |
||
367 | |||
368 | /** |
||
369 | * @return Status |
||
370 | */ |
||
371 | 1 | public function getWorkingTreeStatus(): \GitElephant\Status\Status |
|
372 | { |
||
373 | 1 | return StatusWorkingTree::get($this); |
|
374 | } |
||
375 | |||
376 | /** |
||
377 | * @return Status |
||
378 | */ |
||
379 | 4 | public function getIndexStatus(): \GitElephant\Status\Status |
|
380 | { |
||
381 | 4 | return StatusIndex::get($this); |
|
382 | } |
||
383 | |||
384 | /** |
||
385 | * isClean Return true if the repository is not dirty. |
||
386 | * |
||
387 | * @return boolean |
||
388 | */ |
||
389 | public function isClean(): bool |
||
390 | { |
||
391 | return $this->getStatus()->all()->isEmpty(); |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * isDirty Return true if the repository has some modified files. |
||
396 | * |
||
397 | * @return boolean |
||
398 | */ |
||
399 | public function isDirty(): bool |
||
400 | { |
||
401 | return !$this->isClean(); |
||
402 | } |
||
403 | |||
404 | /** |
||
405 | * Get the repository status as a string |
||
406 | * |
||
407 | * @throws \RuntimeException |
||
408 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
409 | * @throws InvalidArgumentException |
||
410 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
411 | * @return array |
||
412 | */ |
||
413 | 4 | public function getStatusOutput(): array |
|
414 | { |
||
415 | 4 | $this->caller->execute(MainCommand::getInstance($this)->status()); |
|
416 | |||
417 | 4 | return array_map('trim', $this->caller->getOutputLines()); |
|
418 | } |
||
419 | |||
420 | /** |
||
421 | * Create a new branch |
||
422 | * |
||
423 | * @param string $name the new branch name |
||
424 | * @param string|null $startPoint the reference to create the branch from |
||
425 | * |
||
426 | * @throws \RuntimeException |
||
427 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
428 | * @return Repository |
||
429 | */ |
||
430 | 27 | public function createBranch(string $name, $startPoint = null): self |
|
431 | { |
||
432 | 27 | Branch::create($this, $name, $startPoint); |
|
433 | |||
434 | 27 | return $this; |
|
435 | } |
||
436 | |||
437 | /** |
||
438 | * Delete a branch by its name |
||
439 | * This function change the state of the repository on the filesystem |
||
440 | * |
||
441 | * @param string $name The branch to delete |
||
442 | * @param bool $force Force the delete |
||
443 | * |
||
444 | * @throws \RuntimeException |
||
445 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
446 | * @throws InvalidArgumentException |
||
447 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
448 | * @return Repository |
||
449 | */ |
||
450 | 1 | public function deleteBranch(string $name, bool $force = false): self |
|
451 | { |
||
452 | 1 | $this->caller->execute(BranchCommand::getInstance($this)->delete($name, $force)); |
|
453 | |||
454 | 1 | return $this; |
|
455 | } |
||
456 | |||
457 | /** |
||
458 | * An array of Branch objects |
||
459 | * |
||
460 | * @param bool $namesOnly return an array of branch names as a string |
||
461 | * @param bool $all lists also remote branches |
||
462 | * |
||
463 | * @throws \RuntimeException |
||
464 | * @throws InvalidArgumentException |
||
465 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
466 | * @throws \InvalidArgumentException |
||
467 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
468 | * @return array |
||
469 | */ |
||
470 | 17 | public function getBranches(bool $namesOnly = false, bool $all = false): array |
|
471 | { |
||
472 | 17 | $branches = []; |
|
473 | 17 | if ($namesOnly) { |
|
474 | 6 | $outputLines = $this->caller |
|
475 | 6 | ->execute(BranchCommand::getInstance($this)->listBranches($all, true)) |
|
476 | 6 | ->getOutputLines(true); |
|
477 | |||
478 | 6 | $branches = array_map( |
|
479 | function ($v) { |
||
480 | 6 | return ltrim($v, '* '); |
|
481 | 6 | }, |
|
482 | 6 | $outputLines |
|
483 | ); |
||
484 | } else { |
||
485 | 14 | $outputLines = $this->caller |
|
486 | 14 | ->execute(BranchCommand::getInstance($this)->listBranches($all)) |
|
487 | 14 | ->getOutputLines(true); |
|
488 | |||
489 | 14 | foreach ($outputLines as $branchLine) { |
|
490 | 14 | $branches[] = Branch::createFromOutputLine($this, $branchLine); |
|
491 | } |
||
492 | } |
||
493 | |||
494 | 17 | return $branches; |
|
495 | } |
||
496 | |||
497 | /** |
||
498 | * Return the actually checked out branch |
||
499 | * |
||
500 | * @throws \RuntimeException |
||
501 | * @throws \InvalidArgumentException |
||
502 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
503 | * @return Objects\Branch |
||
504 | */ |
||
505 | 5 | public function getMainBranch(): \GitElephant\Objects\Branch |
|
506 | { |
||
507 | 5 | $filtered = array_filter( |
|
508 | 5 | $this->getBranches(), |
|
509 | function (Branch $branch) { |
||
510 | 5 | return $branch->getCurrent(); |
|
511 | 5 | } |
|
512 | ); |
||
513 | 5 | sort($filtered); |
|
514 | |||
515 | 5 | return $filtered[0]; |
|
516 | } |
||
517 | |||
518 | /** |
||
519 | * Retrieve a Branch object by a branch name |
||
520 | * |
||
521 | * @param string $name The branch name |
||
522 | * |
||
523 | * @throws \RuntimeException |
||
524 | * @throws \InvalidArgumentException |
||
525 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
526 | * @return null|Branch |
||
527 | */ |
||
528 | 9 | public function getBranch(string $name): ?\GitElephant\Objects\Branch |
|
529 | { |
||
530 | /** @var Branch $branch */ |
||
531 | 9 | foreach ($this->getBranches() as $branch) { |
|
532 | 9 | if ($branch->getName() === $name) { |
|
533 | 9 | return $branch; |
|
534 | } |
||
535 | } |
||
536 | |||
537 | 1 | return null; |
|
538 | } |
||
539 | |||
540 | /** |
||
541 | * Checkout all branches from the remote and make them local |
||
542 | * |
||
543 | * @param string $remote remote to fetch from |
||
544 | * |
||
545 | * @throws \RuntimeException |
||
546 | * @throws \InvalidArgumentException |
||
547 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
548 | * @return Repository |
||
549 | */ |
||
550 | 1 | public function checkoutAllRemoteBranches($remote = 'origin'): self |
|
551 | { |
||
552 | 1 | $actualBranch = $this->getMainBranch(); |
|
553 | 1 | $actualBranches = $this->getBranches(true, false); |
|
554 | 1 | $allBranches = $this->getBranches(true, true); |
|
555 | |||
556 | 1 | $realBranches = array_filter( |
|
557 | 1 | $allBranches, |
|
558 | function (string $branch) use ($actualBranches) { |
||
559 | 1 | return !in_array($branch, $actualBranches) |
|
560 | 1 | && preg_match('/^remotes(.+)$/', $branch) |
|
561 | 1 | && !preg_match('/^(.+)(HEAD)(.*?)$/', $branch); |
|
562 | 1 | } |
|
563 | ); |
||
564 | |||
565 | 1 | foreach ($realBranches as $realBranch) { |
|
566 | 1 | $this->checkout(str_replace(sprintf('remotes/%s/', $remote), '', $realBranch)); |
|
567 | } |
||
568 | |||
569 | 1 | $this->checkout($actualBranch); |
|
570 | |||
571 | 1 | return $this; |
|
572 | } |
||
573 | |||
574 | /** |
||
575 | * Merge a Branch in the current checked out branch |
||
576 | * |
||
577 | * @param Objects\Branch $branch The branch to merge in the current checked out branch |
||
578 | * @param string $message The message for the merge commit, if merge is 3-way |
||
579 | * @param string $mode The merge mode: ff-only, no-ff or auto |
||
580 | * |
||
581 | * @throws \RuntimeException |
||
582 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
583 | * @throws InvalidArgumentException |
||
584 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
585 | * @return Repository |
||
586 | */ |
||
587 | 2 | public function merge(Branch $branch, string $message = '', string $mode = 'auto'): self |
|
588 | { |
||
589 | $valid_modes = [ |
||
590 | 2 | 'auto', // deafult git behavior |
|
591 | 'ff-only', // force fast forward merge |
||
592 | 'no-ff', // force 3-way merge |
||
593 | ]; |
||
594 | |||
595 | 2 | if (!in_array($mode, $valid_modes)) { |
|
596 | throw new InvalidArgumentException("Invalid merge mode: $mode."); |
||
597 | } |
||
598 | |||
599 | 2 | $options = []; |
|
600 | 2 | switch ($mode) { |
|
601 | 2 | case 'ff-only': |
|
602 | 1 | $options[] = MergeCommand::MERGE_OPTION_FF_ONLY; |
|
603 | 1 | break; |
|
604 | 2 | case 'no-ff': |
|
605 | 1 | $options[] = MergeCommand::MERGE_OPTION_NO_FF; |
|
606 | 1 | break; |
|
607 | } |
||
608 | |||
609 | 2 | $this->caller->execute(MergeCommand::getInstance($this)->merge($branch, $message, $options)); |
|
610 | |||
611 | 2 | return $this; |
|
612 | } |
||
613 | |||
614 | /** |
||
615 | * Create a new tag |
||
616 | * This function change the state of the repository on the filesystem |
||
617 | * |
||
618 | * @param string $name The new tag name |
||
619 | * @param string|null $startPoint The reference to create the tag from |
||
620 | * @param string|null $message the tag message |
||
621 | * |
||
622 | * @throws \RuntimeException |
||
623 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
624 | * @return Repository |
||
625 | */ |
||
626 | 25 | public function createTag(string $name, $startPoint = null, string $message = null): self |
|
627 | { |
||
628 | 25 | Tag::create($this, $name, $startPoint, $message); |
|
629 | |||
630 | 25 | return $this; |
|
631 | } |
||
632 | |||
633 | /** |
||
634 | * Delete a tag by it's name or by passing a Tag object |
||
635 | * This function change the state of the repository on the filesystem |
||
636 | * |
||
637 | * @param string|Tag $tag The tag name or the Tag object |
||
638 | * |
||
639 | * @throws \RuntimeException |
||
640 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
641 | * @return Repository |
||
642 | */ |
||
643 | 2 | public function deleteTag($tag): self |
|
644 | { |
||
645 | 2 | if ($tag instanceof Tag) { |
|
646 | 1 | $tag->delete(); |
|
647 | } else { |
||
648 | 1 | Tag::pick($this, $tag)->delete(); |
|
649 | } |
||
650 | |||
651 | 2 | return $this; |
|
652 | } |
||
653 | |||
654 | /** |
||
655 | * add a git submodule to the repository |
||
656 | * |
||
657 | * @param string $gitUrl git url of the submodule |
||
658 | * @param string $path path to register the submodule to |
||
659 | * |
||
660 | * @throws \RuntimeException |
||
661 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
662 | * @throws InvalidArgumentException |
||
663 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
664 | * @return Repository |
||
665 | */ |
||
666 | 1 | public function addSubmodule(string $gitUrl, $path = null): self |
|
667 | { |
||
668 | 1 | $this->caller->execute(SubmoduleCommand::getInstance($this)->add($gitUrl, $path)); |
|
669 | |||
670 | 1 | return $this; |
|
671 | } |
||
672 | |||
673 | /** |
||
674 | * initialize submodules |
||
675 | * |
||
676 | * @param string $path init only submodules at the specified path |
||
677 | * |
||
678 | * @return Repository |
||
679 | */ |
||
680 | public function initSubmodule($path = null): self |
||
681 | { |
||
682 | $this->caller->execute(SubmoduleCommand::getInstance($this)->init($path)); |
||
683 | |||
684 | return $this; |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * update submodules |
||
689 | * |
||
690 | * @param bool $recursive update recursively |
||
691 | * @param bool $init init before update |
||
692 | * @param bool $force force the checkout as part of update |
||
693 | * @param string $path update only a specific submodule path |
||
694 | * |
||
695 | * @return Repository |
||
696 | */ |
||
697 | public function updateSubmodule( |
||
698 | bool $recursive = false, |
||
699 | bool $init = false, |
||
700 | bool $force = false, |
||
701 | $path = null |
||
702 | ): self { |
||
703 | $this->caller->execute(SubmoduleCommand::getInstance($this)->update($recursive, $init, $force, $path)); |
||
704 | |||
705 | return $this; |
||
706 | } |
||
707 | |||
708 | /** |
||
709 | * Gets an array of Tag objects |
||
710 | * |
||
711 | * @throws \RuntimeException |
||
712 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
713 | * @throws InvalidArgumentException |
||
714 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
715 | * @return array |
||
716 | */ |
||
717 | 4 | public function getTags(): array |
|
718 | { |
||
719 | 4 | $tags = []; |
|
720 | 4 | $this->caller->execute(TagCommand::getInstance($this)->listTags()); |
|
721 | |||
722 | 4 | foreach ($this->caller->getOutputLines() as $tagString) { |
|
723 | 4 | if ($tagString != '') { |
|
724 | 3 | $tags[] = new Tag($this, trim($tagString)); |
|
725 | } |
||
726 | } |
||
727 | |||
728 | 4 | return $tags; |
|
729 | } |
||
730 | |||
731 | /** |
||
732 | * Return a tag object |
||
733 | * |
||
734 | * @param string $name The tag name |
||
735 | * |
||
736 | * @throws \RuntimeException |
||
737 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
738 | * @return Tag|null |
||
739 | */ |
||
740 | 28 | public function getTag(string $name): ?\GitElephant\Objects\Tag |
|
741 | { |
||
742 | 28 | $tagFinderOutput = $this->caller |
|
743 | 28 | ->execute(TagCommand::getInstance()->listTags()) |
|
744 | 28 | ->getOutputLines(true); |
|
745 | |||
746 | 28 | foreach ($tagFinderOutput as $line) { |
|
747 | 28 | if ($line === $name) { |
|
748 | 28 | return new Tag($this, $name); |
|
749 | } |
||
750 | } |
||
751 | |||
752 | 1 | return null; |
|
753 | } |
||
754 | |||
755 | /** |
||
756 | * Return the last created tag |
||
757 | * |
||
758 | * @throws \LogicException |
||
759 | * @throws \RuntimeException |
||
760 | * @throws \InvalidArgumentException |
||
761 | * @return Tag|null |
||
762 | */ |
||
763 | 1 | public function getLastTag(): ?\GitElephant\Objects\Tag |
|
764 | { |
||
765 | 1 | $finder = Finder::create() |
|
766 | 1 | ->files() |
|
767 | 1 | ->in(sprintf('%s/.git/refs/tags', $this->path)) |
|
768 | 1 | ->sortByChangedTime(); |
|
769 | |||
770 | 1 | if ($finder->count() === 0) { |
|
771 | return null; |
||
772 | } |
||
773 | |||
774 | 1 | $files = iterator_to_array($finder->getIterator(), false); |
|
775 | 1 | $files = array_reverse($files); |
|
776 | /** @var SplFileInfo $firstFile */ |
||
777 | 1 | $firstFile = $files[0]; |
|
778 | 1 | $tagName = $firstFile->getFilename(); |
|
779 | |||
780 | 1 | return Tag::pick($this, $tagName); |
|
781 | } |
||
782 | |||
783 | /** |
||
784 | * Try to get a branch or a tag by its name. |
||
785 | * |
||
786 | * @param string $name the reference name (a tag name or a branch name) |
||
787 | * |
||
788 | * @throws \RuntimeException |
||
789 | * @throws \InvalidArgumentException |
||
790 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
791 | * @return \GitElephant\Objects\Tag|\GitElephant\Objects\Branch|null |
||
792 | */ |
||
793 | 1 | public function getBranchOrTag(string $name) |
|
794 | { |
||
795 | 1 | if (in_array($name, $this->getBranches(true))) { |
|
796 | 1 | return new Branch($this, $name); |
|
797 | } |
||
798 | |||
799 | 1 | $tagFinderOutput = $this->caller |
|
800 | 1 | ->execute(TagCommand::getInstance($this)->listTags()) |
|
801 | 1 | ->getOutputLines(true); |
|
802 | |||
803 | 1 | foreach ($tagFinderOutput as $line) { |
|
804 | 1 | if ($line === $name) { |
|
805 | 1 | return new Tag($this, $name); |
|
806 | } |
||
807 | } |
||
808 | |||
809 | 1 | return null; |
|
810 | } |
||
811 | |||
812 | /** |
||
813 | * Return a Commit object |
||
814 | * |
||
815 | * @param string $ref The commit reference |
||
816 | * |
||
817 | * @throws \RuntimeException |
||
818 | * @return Objects\Commit |
||
819 | */ |
||
820 | 15 | public function getCommit($ref = 'HEAD'): \GitElephant\Objects\Commit |
|
821 | { |
||
822 | 15 | return Commit::pick($this, $ref); |
|
823 | } |
||
824 | |||
825 | /** |
||
826 | * count the commit to arrive to the given treeish |
||
827 | * |
||
828 | * @param string $start |
||
829 | * |
||
830 | * @throws \RuntimeException |
||
831 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
832 | * @return int |
||
833 | */ |
||
834 | 3 | public function countCommits($start = 'HEAD'): int |
|
835 | { |
||
836 | 3 | $commit = Commit::pick($this, $start); |
|
837 | |||
838 | 3 | return $commit->count(); |
|
839 | } |
||
840 | |||
841 | /** |
||
842 | * Get a log for a ref |
||
843 | * |
||
844 | * @param string|TreeishInterface|array $ref the treeish to check, as a string, as an object or as an array |
||
845 | * @param string|NodeObject $path the physical path to the tree relative to the repository root |
||
846 | * @param int $limit limit to n entries |
||
847 | * @param int|null $offset skip n entries |
||
848 | * @param boolean|false $firstParent skip commits brought in to branch by a merge |
||
849 | * |
||
850 | * @return \GitElephant\Objects\Log |
||
851 | */ |
||
852 | 20 | public function getLog( |
|
853 | $ref = 'HEAD', |
||
854 | $path = null, |
||
855 | int $limit = 10, |
||
856 | ?int $offset = null, |
||
857 | bool $firstParent = false |
||
858 | ): \GitElephant\Objects\Log { |
||
859 | 20 | return new Log($this, $ref, $path, $limit, $offset, $firstParent); |
|
0 ignored issues
–
show
It seems like
$path defined by parameter $path on line 854 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Objects\Log::__construct() does only seem to accept string|null , 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...
|
|||
860 | } |
||
861 | |||
862 | /** |
||
863 | * Get a log for a range ref |
||
864 | * |
||
865 | * @param string $refStart |
||
866 | * @param string $refEnd |
||
867 | * @param string|NodeObject $path the physical path to the tree relative to the repository root |
||
868 | * @param int $limit limit to n entries |
||
869 | * @param int|null $offset skip n entries |
||
870 | * @param boolean|false $firstParent skip commits brought in to branch by a merge |
||
871 | * |
||
872 | * @return \GitElephant\Objects\LogRange|\GitElephant\Objects\Log |
||
873 | */ |
||
874 | public function getLogRange( |
||
875 | $refStart, |
||
876 | $refEnd, |
||
877 | $path = null, |
||
878 | int $limit = 10, |
||
879 | int $offset = null, |
||
880 | bool $firstParent = false |
||
881 | ) { |
||
882 | // Handle when clients provide bad start reference on branch creation |
||
883 | if (preg_match('~^[0]+$~', $refStart)) { |
||
884 | return new Log($this, $refEnd, $path, $limit, $offset, $firstParent); |
||
0 ignored issues
–
show
It seems like
$path defined by parameter $path on line 877 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Objects\Log::__construct() does only seem to accept string|null , 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...
|
|||
885 | } |
||
886 | |||
887 | // Handle when clients provide bad end reference on branch deletion |
||
888 | if (preg_match('~^[0]+$~', $refEnd)) { |
||
889 | $refEnd = $refStart; |
||
890 | } |
||
891 | |||
892 | return new LogRange($this, $refStart, $refEnd, $path, $limit, $offset, $firstParent); |
||
0 ignored issues
–
show
It seems like
$path defined by parameter $path on line 877 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Objects\LogRange::__construct() does only seem to accept string|null , 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...
|
|||
893 | } |
||
894 | |||
895 | /** |
||
896 | * Get a log for an object |
||
897 | * |
||
898 | * @param \GitElephant\Objects\NodeObject $obj The Object instance |
||
899 | * @param null|string|\GitElephant\Objects\Branch $branch The branch to read from |
||
900 | * @param int $limit Limit to n entries |
||
901 | * @param int|null $offset Skip n entries |
||
902 | * |
||
903 | * @throws \RuntimeException |
||
904 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
905 | * @throws InvalidArgumentException |
||
906 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
907 | * @return \GitElephant\Objects\Log |
||
908 | */ |
||
909 | 3 | public function getObjectLog( |
|
910 | NodeObject $obj, |
||
911 | $branch = null, |
||
912 | int $limit = 1, |
||
913 | int $offset = null |
||
914 | ): \GitElephant\Objects\Log { |
||
915 | 3 | $command = LogCommand::getInstance($this)->showObjectLog($obj, $branch, $limit, $offset); |
|
916 | |||
917 | 3 | return Log::createFromOutputLines($this, $this->caller->execute($command)->getOutputLines()); |
|
918 | } |
||
919 | |||
920 | /** |
||
921 | * Checkout a branch |
||
922 | * This function change the state of the repository on the filesystem |
||
923 | * |
||
924 | * @param string|TreeishInterface $ref the reference to checkout |
||
925 | * @param bool $create like -b on the command line |
||
926 | * |
||
927 | * @throws \RuntimeException |
||
928 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
929 | * @throws InvalidArgumentException |
||
930 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
931 | * @return Repository |
||
932 | */ |
||
933 | 24 | public function checkout($ref, bool $create = false): self |
|
934 | { |
||
935 | 24 | if ($create && is_null($this->getBranch($ref))) { |
|
0 ignored issues
–
show
It seems like
$ref defined by parameter $ref on line 933 can also be of type object<GitElephant\Objects\TreeishInterface> ; however, GitElephant\Repository::getBranch() 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...
|
|||
936 | $this->createBranch($ref); |
||
0 ignored issues
–
show
It seems like
$ref defined by parameter $ref on line 933 can also be of type object<GitElephant\Objects\TreeishInterface> ; however, GitElephant\Repository::createBranch() 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...
|
|||
937 | } |
||
938 | 24 | $this->caller->execute(MainCommand::getInstance($this)->checkout($ref)); |
|
939 | |||
940 | 24 | return $this; |
|
941 | } |
||
942 | |||
943 | /** |
||
944 | * Retrieve an instance of Tree |
||
945 | * Tree Object is Countable, Iterable and has ArrayAccess for easy manipulation |
||
946 | * |
||
947 | * @param string|TreeishInterface $ref the treeish to check |
||
948 | * @param string|NodeObject $path Object or null for root |
||
949 | * |
||
950 | * @throws \RuntimeException |
||
951 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
952 | * @throws InvalidArgumentException |
||
953 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
954 | * @return Objects\Tree |
||
955 | */ |
||
956 | 15 | public function getTree($ref = 'HEAD', $path = null): \GitElephant\Objects\Tree |
|
957 | { |
||
958 | 15 | if (is_string($path) && '' !== $path) { |
|
959 | $outputLines = $this |
||
960 | 9 | ->getCaller() |
|
961 | 9 | ->execute(LsTreeCommand::getInstance($this)->tree($ref, $path)) |
|
962 | 9 | ->getOutputLines(true); |
|
963 | |||
964 | 9 | $path = TreeObject::createFromOutputLine($this, $outputLines[0]); |
|
965 | } |
||
966 | |||
967 | 15 | return new Tree($this, $ref, $path); |
|
0 ignored issues
–
show
It seems like
$ref defined by parameter $ref on line 956 can also be of type object<GitElephant\Objects\TreeishInterface> ; however, GitElephant\Objects\Tree::__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...
It seems like
$path defined by parameter $path on line 956 can also be of type string ; however, GitElephant\Objects\Tree::__construct() does only seem to accept null|object<GitElephant\Objects\NodeObject> , 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...
|
|||
968 | } |
||
969 | |||
970 | /** |
||
971 | * Get a Diff object for a commit with its parent, by default the diff is between the current head and its parent |
||
972 | * |
||
973 | * @param \GitElephant\Objects\Commit|TreeishInterface|string|null $commit1 The first commit to compare |
||
974 | * @param \GitElephant\Objects\Commit|TreeishInterface|string|null $commit2 The commit to compare to |
||
975 | * @param null|string|NodeObject $path The path to get the diff for or a Object instance |
||
976 | * |
||
977 | * @throws \RuntimeException |
||
978 | * @throws \InvalidArgumentException |
||
979 | * @return Objects\Diff\Diff |
||
980 | */ |
||
981 | 2 | public function getDiff( |
|
982 | $commit1 = null, |
||
983 | $commit2 = null, |
||
984 | $path = null |
||
985 | ): \GitElephant\Objects\Diff\Diff { |
||
986 | 2 | return Diff::create($this, $commit1, $commit2, $path); |
|
0 ignored issues
–
show
It seems like
$commit1 defined by parameter $commit1 on line 982 can also be of type object<GitElephant\Objects\TreeishInterface> ; however, GitElephant\Objects\Diff\Diff::create() does only seem to accept null|string|object<GitElephant\Objects\Commit> , 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...
It seems like
$commit2 defined by parameter $commit2 on line 983 can also be of type object<GitElephant\Objects\TreeishInterface> ; however, GitElephant\Objects\Diff\Diff::create() does only seem to accept null|string|object<GitElephant\Objects\Commit> , 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...
It seems like
$path defined by parameter $path on line 984 can also be of type object<GitElephant\Objects\NodeObject> ; however, GitElephant\Objects\Diff\Diff::create() does only seem to accept null|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...
|
|||
987 | } |
||
988 | |||
989 | /** |
||
990 | * Clone a repository |
||
991 | * |
||
992 | * @param string $url the repository url (i.e. git://github.com/matteosister/GitElephant.git) |
||
993 | * @param string|null $to where to clone the repo |
||
994 | * @param string|null $repoReference Repo reference to clone. Required if performing a shallow clone. |
||
995 | * @param int|null $depth Depth to clone repo. Specify 1 to perform a shallow clone |
||
996 | * @param bool $recursive Whether to recursively clone child repos. |
||
997 | * |
||
998 | * @throws \RuntimeException |
||
999 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1000 | * @throws \Symfony\Component\Process\Exception\InvalidArgumentException |
||
1001 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1002 | * @return Repository |
||
1003 | */ |
||
1004 | 2 | public function cloneFrom( |
|
1005 | string $url, |
||
1006 | string $to = null, |
||
1007 | string $repoReference = null, |
||
1008 | int $depth = null, |
||
1009 | bool $recursive = false |
||
1010 | ): self { |
||
1011 | 2 | $command = Command\CloneCommand::getInstance($this) |
|
1012 | 2 | ->cloneUrl($url, $to, $repoReference, $depth, $recursive); |
|
1013 | 2 | $this->caller->execute($command); |
|
1014 | |||
1015 | 2 | return $this; |
|
1016 | } |
||
1017 | |||
1018 | /** |
||
1019 | * @param string $name remote name |
||
1020 | * @param string $url remote url |
||
1021 | * |
||
1022 | * @throws \RuntimeException |
||
1023 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1024 | * @throws InvalidArgumentException |
||
1025 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1026 | * @return Repository |
||
1027 | */ |
||
1028 | 7 | public function addRemote(string $name, string $url): self |
|
1029 | { |
||
1030 | 7 | $this->caller->execute(RemoteCommand::getInstance($this)->add($name, $url)); |
|
1031 | |||
1032 | 7 | return $this; |
|
1033 | } |
||
1034 | |||
1035 | /** |
||
1036 | * @param string $name remote name |
||
1037 | * @param bool $queryRemotes Fetch new information from remotes |
||
1038 | * |
||
1039 | * @return \GitElephant\Objects\Remote |
||
1040 | */ |
||
1041 | 1 | public function getRemote(string $name, bool $queryRemotes = true): \GitElephant\Objects\Remote |
|
1042 | { |
||
1043 | 1 | return Remote::pick($this, $name, $queryRemotes); |
|
1044 | } |
||
1045 | |||
1046 | /** |
||
1047 | * gets a list of remote objects |
||
1048 | * |
||
1049 | * @param bool $queryRemotes Fetch new information from remotes |
||
1050 | * |
||
1051 | * @throws \RuntimeException |
||
1052 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1053 | * @throws InvalidArgumentException |
||
1054 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1055 | * @return array |
||
1056 | */ |
||
1057 | 1 | public function getRemotes(bool $queryRemotes = true): array |
|
1058 | { |
||
1059 | 1 | $remoteNames = $this->caller |
|
1060 | 1 | ->execute(RemoteCommand::getInstance($this)->show(null, $queryRemotes)) |
|
1061 | 1 | ->getOutputLines(true); |
|
1062 | |||
1063 | 1 | $remotes = []; |
|
1064 | 1 | foreach ($remoteNames as $remoteName) { |
|
1065 | 1 | $remotes[] = $this->getRemote($remoteName, $queryRemotes); |
|
1066 | } |
||
1067 | |||
1068 | 1 | return $remotes; |
|
1069 | } |
||
1070 | |||
1071 | /** |
||
1072 | * Download objects and refs from another repository |
||
1073 | * |
||
1074 | * @param string $from |
||
1075 | * @param string $ref |
||
1076 | * @param bool $tags |
||
1077 | * |
||
1078 | * @throws \RuntimeException |
||
1079 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1080 | * @throws InvalidArgumentException |
||
1081 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1082 | */ |
||
1083 | 1 | public function fetch($from = null, $ref = null, bool $tags = false): void |
|
1084 | { |
||
1085 | 1 | $options = []; |
|
1086 | 1 | if ($tags) { |
|
1087 | 1 | $options = ['--tags']; |
|
1088 | } |
||
1089 | 1 | $this->caller->execute(FetchCommand::getInstance($this)->fetch($from, $ref, $options)); |
|
1090 | 1 | } |
|
1091 | |||
1092 | /** |
||
1093 | * Fetch from and merge with another repository or a local branch |
||
1094 | * |
||
1095 | * @param string $from |
||
1096 | * @param string $ref |
||
1097 | * @param bool $rebase |
||
1098 | * |
||
1099 | * @throws \RuntimeException |
||
1100 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1101 | * @throws InvalidArgumentException |
||
1102 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1103 | */ |
||
1104 | 2 | public function pull($from = null, $ref = null, bool $rebase = true): void |
|
1105 | { |
||
1106 | 2 | $this->caller->execute(PullCommand::getInstance($this)->pull($from, $ref, $rebase)); |
|
1107 | 2 | } |
|
1108 | |||
1109 | /** |
||
1110 | * Push changes to remote repository |
||
1111 | * |
||
1112 | * @param string $to |
||
1113 | * @param string $ref |
||
1114 | * @param string $args |
||
1115 | * |
||
1116 | * @throws \RuntimeException |
||
1117 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1118 | * @throws InvalidArgumentException |
||
1119 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1120 | */ |
||
1121 | 1 | public function push($to = null, $ref = null, string $args = null): void |
|
1122 | { |
||
1123 | 1 | $this->caller->execute(PushCommand::getInstance($this)->push($to, $ref, $args)); |
|
1124 | 1 | } |
|
1125 | |||
1126 | /** |
||
1127 | * get the humanish name of the repository |
||
1128 | * |
||
1129 | * @return string |
||
1130 | */ |
||
1131 | 2 | public function getHumanishName(): string |
|
1132 | { |
||
1133 | 2 | $name = substr($this->getPath(), strrpos($this->getPath(), '/') + 1); |
|
1134 | 2 | $name = str_replace('.git', '.', $name); |
|
1135 | |||
1136 | 2 | return str_replace('.bundle', '.', $name); |
|
1137 | } |
||
1138 | |||
1139 | /** |
||
1140 | * output a node content as an array of lines |
||
1141 | * |
||
1142 | * @param \GitElephant\Objects\NodeObject $obj The Object of type BLOB |
||
1143 | * @param \GitElephant\Objects\TreeishInterface|string $treeish A treeish object |
||
1144 | * |
||
1145 | * @throws \RuntimeException |
||
1146 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1147 | * @throws InvalidArgumentException |
||
1148 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1149 | * @return array |
||
1150 | */ |
||
1151 | 1 | public function outputContent(NodeObject $obj, $treeish): array |
|
1152 | { |
||
1153 | 1 | $command = CatFileCommand::getInstance($this)->content($obj, $treeish); |
|
1154 | |||
1155 | 1 | return $this->caller->execute($command)->getOutputLines(); |
|
1156 | } |
||
1157 | |||
1158 | /** |
||
1159 | * output a node raw content |
||
1160 | * |
||
1161 | * @param \GitElephant\Objects\NodeObject $obj The Object of type BLOB |
||
1162 | * @param \GitElephant\Objects\TreeishInterface|string $treeish A treeish object |
||
1163 | * |
||
1164 | * @throws \RuntimeException |
||
1165 | * @throws \Symfony\Component\Process\Exception\LogicException |
||
1166 | * @throws InvalidArgumentException |
||
1167 | * @throws \Symfony\Component\Process\Exception\RuntimeException |
||
1168 | * @return string |
||
1169 | */ |
||
1170 | public function outputRawContent(NodeObject $obj, $treeish): string |
||
1171 | { |
||
1172 | $command = CatFileCommand::getInstance($this)->content($obj, $treeish); |
||
1173 | |||
1174 | return $this->caller->execute($command)->getRawOutput(); |
||
1175 | } |
||
1176 | |||
1177 | /** |
||
1178 | * Get the path |
||
1179 | * |
||
1180 | * @return string |
||
1181 | */ |
||
1182 | 64 | public function getPath(): string |
|
1183 | { |
||
1184 | 64 | return $this->path; |
|
1185 | } |
||
1186 | |||
1187 | /** |
||
1188 | * Get the repository name |
||
1189 | * |
||
1190 | * @return string |
||
1191 | */ |
||
1192 | 1 | public function getName(): string |
|
1193 | { |
||
1194 | 1 | return $this->name; |
|
1195 | } |
||
1196 | |||
1197 | /** |
||
1198 | * Set the repository name |
||
1199 | * |
||
1200 | * @param string $name the repository name |
||
1201 | */ |
||
1202 | 1 | public function setName(string $name): void |
|
1203 | { |
||
1204 | 1 | $this->name = $name; |
|
1205 | 1 | } |
|
1206 | |||
1207 | /** |
||
1208 | * Caller setter |
||
1209 | * |
||
1210 | * @param CallerInterface $caller the caller variable |
||
1211 | */ |
||
1212 | public function setCaller(CallerInterface $caller): void |
||
1213 | { |
||
1214 | $this->caller = $caller; |
||
1215 | } |
||
1216 | |||
1217 | /** |
||
1218 | * Caller getter |
||
1219 | * |
||
1220 | * @return CallerInterface the caller to use to call commands |
||
1221 | */ |
||
1222 | 92 | public function getCaller(): CallerInterface |
|
1223 | { |
||
1224 | 92 | return $this->caller; |
|
1225 | } |
||
1226 | |||
1227 | /** |
||
1228 | * get global config list |
||
1229 | * |
||
1230 | * @return array Global config list |
||
1231 | */ |
||
1232 | 98 | public function getGlobalConfigs(): array |
|
1233 | { |
||
1234 | 98 | return $this->globalConfigs; |
|
1235 | } |
||
1236 | |||
1237 | /** |
||
1238 | * add a key/value pair to the global config list |
||
1239 | * |
||
1240 | * @param string $name The config name |
||
1241 | * @param mixed $value The config value |
||
1242 | */ |
||
1243 | 1 | public function addGlobalConfig(string $name, $value): void |
|
1244 | { |
||
1245 | 1 | $this->globalConfigs[$name] = $value; |
|
1246 | 1 | } |
|
1247 | |||
1248 | /** |
||
1249 | * remove an element form the global config list, identified by key |
||
1250 | * |
||
1251 | * @param string $name The config name |
||
1252 | */ |
||
1253 | 1 | public function removeGlobalConfig(string $name): void |
|
1254 | { |
||
1255 | 1 | if (isset($this->globalConfigs[$name])) { |
|
1256 | 1 | unset($this->globalConfigs[$name]); |
|
1257 | } |
||
1258 | 1 | } |
|
1259 | |||
1260 | /** |
||
1261 | * get global options list |
||
1262 | * |
||
1263 | * @return array Global options list |
||
1264 | */ |
||
1265 | 98 | public function getGlobalOptions(): array |
|
1266 | { |
||
1267 | 98 | return $this->globalOptions; |
|
1268 | } |
||
1269 | |||
1270 | /** |
||
1271 | * add a key/value pair to the global option list |
||
1272 | * |
||
1273 | * @param string $name The option name |
||
1274 | * @param mixed $value The option value |
||
1275 | */ |
||
1276 | 1 | public function addGlobalOption(string $name, $value): void |
|
1277 | { |
||
1278 | 1 | $this->globalOptions[$name] = $value; |
|
1279 | 1 | } |
|
1280 | |||
1281 | /** |
||
1282 | * remove an element form the global option list, identified by key |
||
1283 | * |
||
1284 | * @param string $name The option name |
||
1285 | */ |
||
1286 | 1 | public function removeGlobalOption(string $name): void |
|
1287 | { |
||
1288 | 1 | if (isset($this->globalOptions[$name])) { |
|
1289 | 1 | unset($this->globalOptions[$name]); |
|
1290 | } |
||
1291 | 1 | } |
|
1292 | |||
1293 | /** |
||
1294 | * get global command arguments list |
||
1295 | * |
||
1296 | * @return array Global command arguments list |
||
1297 | */ |
||
1298 | 98 | public function getGlobalCommandArguments(): array |
|
1299 | { |
||
1300 | 98 | return $this->globalCommandArguments; |
|
1301 | } |
||
1302 | |||
1303 | /** |
||
1304 | * add a value to the global command argument list |
||
1305 | * |
||
1306 | * @param string $value The command argument |
||
1307 | */ |
||
1308 | 1 | public function addGlobalCommandArgument($value): void |
|
1309 | { |
||
1310 | 1 | if (!in_array($value, $this->globalCommandArguments, true)) { |
|
1311 | 1 | $this->globalCommandArguments[] = $value; |
|
1312 | } |
||
1313 | 1 | } |
|
1314 | |||
1315 | /** |
||
1316 | * remove an element form the global command argument list, identified by |
||
1317 | * value |
||
1318 | * |
||
1319 | * @param string $value The command argument |
||
1320 | */ |
||
1321 | 1 | public function removeGlobalCommandArgument($value): void |
|
1322 | { |
||
1323 | 1 | if (in_array($value, $this->globalCommandArguments, true)) { |
|
1324 | 1 | $index = array_search($value, $this->globalCommandArguments); |
|
1325 | 1 | unset($this->globalCommandArguments[$index]); |
|
1326 | } |
||
1327 | 1 | } |
|
1328 | |||
1329 | /** |
||
1330 | * Save your local modifications to a new stash, and run git reset --hard to revert them. |
||
1331 | * |
||
1332 | * @param string|null $message |
||
1333 | * @param boolean $includeUntracked |
||
1334 | * @param boolean $keepIndex |
||
1335 | */ |
||
1336 | 2 | public function stash(string $message = null, bool $includeUntracked = false, bool $keepIndex = false): void |
|
1337 | { |
||
1338 | 2 | $stashCommand = StashCommand::getInstance($this); |
|
1339 | 2 | $command = $stashCommand->save($message, $includeUntracked, $keepIndex); |
|
1340 | 2 | $this->caller->execute($command); |
|
1341 | 1 | } |
|
1342 | |||
1343 | /** |
||
1344 | * Shows stash list |
||
1345 | * |
||
1346 | * @param array|null $options |
||
1347 | * |
||
1348 | * @return array |
||
1349 | */ |
||
1350 | 1 | public function stashList(array $options = null): array |
|
1351 | { |
||
1352 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1353 | 1 | $command = $stashCommand->listStashes($options); |
|
1354 | 1 | $this->caller->execute($command); |
|
1355 | |||
1356 | 1 | return array_map('trim', $this->caller->getOutputLines(true)); |
|
1357 | } |
||
1358 | |||
1359 | /** |
||
1360 | * Shows details for a stash |
||
1361 | * |
||
1362 | * @param string|int $stash |
||
1363 | * |
||
1364 | * @return string |
||
1365 | */ |
||
1366 | 1 | public function stashShow($stash): string |
|
1367 | { |
||
1368 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1369 | 1 | $command = $stashCommand->show($stash); |
|
1370 | 1 | $this->caller->execute($command); |
|
1371 | |||
1372 | 1 | return $this->caller->getOutput(); |
|
1373 | } |
||
1374 | |||
1375 | /** |
||
1376 | * Drops a stash |
||
1377 | * |
||
1378 | * @param string|int $stash |
||
1379 | */ |
||
1380 | 1 | public function stashDrop($stash): void |
|
1381 | { |
||
1382 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1383 | 1 | $command = $stashCommand->drop($stash); |
|
1384 | 1 | $this->caller->execute($command); |
|
1385 | 1 | } |
|
1386 | |||
1387 | /** |
||
1388 | * Applies a stash |
||
1389 | * |
||
1390 | * @param string|int $stash |
||
1391 | * @param boolean $index |
||
1392 | */ |
||
1393 | 1 | public function stashApply($stash, bool $index = false): void |
|
1394 | { |
||
1395 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1396 | 1 | $command = $stashCommand->apply($stash, $index); |
|
1397 | 1 | $this->caller->execute($command); |
|
1398 | 1 | } |
|
1399 | |||
1400 | /** |
||
1401 | * Applies a stash, then removes it from the stash |
||
1402 | * |
||
1403 | * @param string|int $stash |
||
1404 | * @param boolean $index |
||
1405 | */ |
||
1406 | 1 | public function stashPop($stash, bool $index = false): void |
|
1407 | { |
||
1408 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1409 | 1 | $command = $stashCommand->pop($stash, $index); |
|
1410 | 1 | $this->caller->execute($command); |
|
1411 | 1 | } |
|
1412 | |||
1413 | /** |
||
1414 | * Creates and checks out a new branch named <branchname> starting from the commit at which the <stash> was originally created |
||
1415 | * |
||
1416 | * @param string $branch |
||
1417 | * @param string|int $stash |
||
1418 | */ |
||
1419 | 1 | public function stashBranch(string $branch, $stash): void |
|
1420 | { |
||
1421 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1422 | 1 | $command = $stashCommand->branch($branch, $stash); |
|
1423 | 1 | $this->caller->execute($command); |
|
1424 | 1 | } |
|
1425 | |||
1426 | /** |
||
1427 | * Save your local modifications to a new stash, and run git reset --hard to revert them. |
||
1428 | */ |
||
1429 | public function stashClear(): void |
||
1430 | { |
||
1431 | $stashCommand = StashCommand::getInstance($this); |
||
1432 | $command = $stashCommand->clear(); |
||
1433 | $this->caller->execute($command); |
||
1434 | } |
||
1435 | |||
1436 | /** |
||
1437 | * Create a stash (which is a regular commit object) and return its object name, without storing it anywhere in the |
||
1438 | * ref namespace. |
||
1439 | * |
||
1440 | * @return string |
||
1441 | */ |
||
1442 | 1 | public function stashCreate(): string |
|
1443 | { |
||
1444 | 1 | $stashCommand = StashCommand::getInstance($this); |
|
1445 | 1 | $command = $stashCommand->clear(); |
|
1446 | 1 | $this->caller->execute($command); |
|
1447 | |||
1448 | 1 | return $this->caller->getOutput(); |
|
1449 | } |
||
1450 | } |
||
1451 |
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.