Completed
Push — master ( ca4c8c...687844 )
by Sebastian
03:10
created

AnyFileChanged::getChangedFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * This file is part of CaptainHook.
4
 *
5
 * (c) Sebastian Feldmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace CaptainHook\App\Hook\Condition;
11
12
use CaptainHook\App\Config;
13
use CaptainHook\App\Console\IO;
14
use CaptainHook\App\Hook\Condition;
15
use SebastianFeldmann\Git\Repository;
16
17
/**
18
 * Class FileChange
19
 *
20
 * The FileChange condition in applicable for `post-merge` and `post-checkout` hooks.
21
 * For example it can be used to trigger an automatic composer install of the composer.json
22
 * or composer.lock file is changed during a checkout or merge.
23
 *
24
 * Example configuration:
25
 *
26
 * "action": "composer install"
27
 * "conditions": [
28
 *   {"exec": "\\CaptainHook\\App\\Hook\\Condition\\FileChange",
29
 *    "args": {
30
 *      "files": [
31
 *        "composer.json",
32
 *        "composer.lock"
33
 *      ]}}
34
 * ]
35
 *
36
 * @package CaptainHook
37
 * @author  Sebastian Feldmann <[email protected]>
38
 * @link    https://github.com/captainhookphp/captainhook
39
 * @since   Class available since Release 4.2.0
40
 */
41
class AnyFileChanged implements Condition
42
{
43
    /**
44
     * @var string[]
45
     */
46
    private $filesToWatch;
47
48
    /**
49
     * FileChange constructor.
50
     *
51
     * @param string[] $files
52
     */
53 3
    public function __construct(array $files)
54
    {
55 3
        $this->filesToWatch = $files;
56 3
    }
57
58
    /**
59
     * Evaluates a condition
60
     *
61
     * @param \CaptainHook\App\Console\IO       $io
62
     * @param \SebastianFeldmann\Git\Repository $repository
63
     * @return bool
64
     */
65 3
    public function isTrue(IO $io, Repository $repository): bool
66
    {
67 3
        return $this->didFileChange($this->getChangedFiles($io, $repository));
68
    }
69
70
    /**
71
     * Use 'diff-tree' to find the changed files after this merge or checkout
72
     *
73
     * In case of a checkout it is easy because the arguments 'previousHead' and 'newHead' exist.
74
     * In case of a merge determining this hashes is more difficult so we are using the 'ref-log'
75
     * to do it and using 'HEAD@{1}' as the last position before the merge and 'HEAD' as the
76
     * current position after the merge.
77
     *
78
     * @param \CaptainHook\App\Console\IO       $io
79
     * @param \SebastianFeldmann\Git\Repository $repository
80
     * @return array|string[]
81
     */
82 3
    private function getChangedFiles(IO $io, Repository $repository)
83
    {
84 3
        $oldHash = $io->getArgument('previousHead', 'HEAD@{1}');
85 3
        $newHash = $io->getArgument('newHead', 'HEAD');
86
87 3
        return $repository->getDiffOperator()->getChangedFiles($oldHash, $newHash);
88
    }
89
90
    /**
91
     * Check if the configured files where changed within the applied change set
92
     *
93
     * @param  array  $changedFiles
94
     * @return bool
95
     */
96 3
    private function didFileChange(array $changedFiles) : bool
97
    {
98 3
        foreach ($this->filesToWatch as $file) {
99 3
            if (in_array($file, $changedFiles)) {
100 3
                return true;
101
            }
102
        }
103 1
        return false;
104
    }
105
}
106