Passed
Push — rm-test ( e2c1fb )
by Sebastian
03:48
created

PrePush::collectChangedFiles()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7.0145

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 15
c 2
b 0
f 0
nc 8
nop 2
dl 0
loc 24
ccs 14
cts 15
cp 0.9333
crap 7.0145
rs 8.8333
1
<?php
2
3
/**
4
 * This file is part of CaptainHook.
5
 *
6
 * (c) Sebastian Feldmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CaptainHook\App\Git\ChangedFiles\Detector;
13
14
use CaptainHook\App\Console\IO;
15
use CaptainHook\App\Git\ChangedFiles\Detector;
16
use CaptainHook\App\Git\Range\Detector\PrePush as RangeDetector;
17
use CaptainHook\App\Git\Range\PrePush as Range;
18
use CaptainHook\App\Git\Rev\Util;
19
use SebastianFeldmann\Git\Repository;
20
21
/**
22
 * Class PrePush
23
 *
24
 * @package CaptainHook
25
 * @author  Sebastian Feldmann <[email protected]>
26
 * @link    https://github.com/captainhook-git/captainhook
27
 * @since   Class available since Release 5.20.0
28
 */
29
class PrePush extends Detector
30
{
31
    /**
32
     * Reflog fallback switch
33
     *
34
     * @var bool
35
     */
36
    private bool $reflogFallback = false;
37
38
    /**
39
     * Activate the reflog fallback file detection
40
     *
41
     * @param bool $bool
42
     * @return void
43
     */
44 2
    public function useReflogFallback(bool $bool): void
45
    {
46 2
        $this->reflogFallback = $bool;
47
    }
48
49
    /**
50
     * Return list of changed files
51
     *
52
     * @param  array<string> $filter
53
     * @return array<string>
54
     */
55 8
    public function getChangedFiles(array $filter = []): array
56
    {
57 8
        $ranges = $this->getRanges();
58 8
        if (empty($ranges)) {
59 1
            return [];
60
        }
61 7
        $files = $this->collectChangedFiles($ranges, $filter);
62 7
        if (count($files) > 0 || !$this->reflogFallback) {
63 6
            return $files;
64
        }
65
        // by now we should have found something, but if the "branch: created" entry is gone from the reflog,
66
        // try to find as many commits belonging to this branch as possible
67 1
        $branch    = $ranges[0]->to()->branch();
68 1
        $revisions = $this->repository->getLogOperator()->getBranchRevsFromRefLog($branch);
69 1
        return $this->repository->getLogOperator()->getChangedFilesInRevisions($revisions);
70
    }
71
72
    /**
73
     * Create ranges from stdIn
74
     *
75
     * @return array<\CaptainHook\App\Git\Range\PrePush>
76
     */
77 8
    private function getRanges(): array
78
    {
79 8
        $detector = new RangeDetector();
80 8
        return $detector->getRanges($this->io);
81
    }
82
83
    /**
84
     * Collect all changed files from all ranges
85
     *
86
     * @param  array<\CaptainHook\App\Git\Range\PrePush> $ranges
87
     * @param  array<string> $filter
88
     * @return array<string>
89
     */
90 7
    private function collectChangedFiles(array $ranges, array $filter): array
91
    {
92 7
        $files = [];
93 7
        foreach ($ranges as $range) {
94 7
            if ($this->isKnownBranch($range)) {
95 4
                $oldHash = $range->from()->id();
96 4
                $newHash = $range->to()->id();
97
            } else {
98 3
                if (!$this->reflogFallback) {
99 1
                    continue;
100
                }
101
                // the remote branch does not exist
102
                // try to find the branch starting point with the reflog
103 2
                $oldHash = $this->repository->getLogOperator()->getBranchRevFromRefLog($range->to()->branch());
104 2
                $newHash = 'HEAD';
105
            }
106 6
            if (Util::isZeroHash($oldHash) || Util::isZeroHash($newHash)) {
107
                continue;
108
            }
109 6
            if (!empty($oldHash)) {
110 5
                $files[] = $this->repository->getDiffOperator()->getChangedFiles($oldHash, $newHash, $filter);
111
            }
112
        }
113 7
        return array_unique(array_merge(...$files));
114
    }
115
116
    /**
117
     * If the remote branch is known the diff can  be easily determined
118
     *
119
     * @param  \CaptainHook\App\Git\Range\PrePush $range
120
     * @return bool
121
     */
122 7
    private function isKnownBranch(Range $range): bool
123
    {
124 7
        return !$range->from()->isZeroRev();
125
    }
126
}
127