Passed
Push — master ( 0e8768...db987b )
by Alexander
01:56
created

GitExecutor::getCommitDescription()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Vasoft\VersionIncrement;
6
7
use Vasoft\VersionIncrement\Commits\FileModifyType;
8
use Vasoft\VersionIncrement\Commits\ModifiedFile;
9
use Vasoft\VersionIncrement\Contract\VcsExecutorInterface;
10
use Vasoft\VersionIncrement\Exceptions\GitCommandException;
11
use Vasoft\VersionIncrement\Exceptions\VcsNoChangedFilesException;
12
13
class GitExecutor implements VcsExecutorInterface
14
{
15
    /**
16
     * @codeCoverageIgnore
17
     */
18
    public function setConfig(Config $config): void
19
    {
20
        // Do nothing
21
    }
22
23 1
    public function status(): array
24
    {
25 1
        return $this->runCommand('status --porcelain');
26
    }
27
28 1
    public function getCommitDescription(string $commitId): array
29
    {
30 1
        return $this->runCommand('log -1 --pretty=format:%b ' . $commitId);
31
    }
32
33 1
    public function addFile(string $file): void
34
    {
35 1
        $this->runCommand('add ' . $file);
36
    }
37
38 1
    public function setVersionTag(string $version): void
39
    {
40 1
        $this->runCommand('tag v' . $version);
41
    }
42
43 1
    public function commit(string $message): void
44
    {
45 1
        $this->runCommand("commit -am '" . $message . "'");
46
    }
47
48 2
    public function getCurrentBranch(): string
49
    {
50 2
        $branch = $this->runCommand('rev-parse --abbrev-ref HEAD');
51
52 1
        return trim($branch[0] ?? '');
53
    }
54
55 2
    public function getLastTag(): ?string
56
    {
57 2
        $tags = $this->runCommand('tag --sort=-creatordate');
58
59 2
        return $tags[0] ?? null;
60
    }
61
62 2
    public function getCommitsSinceLastTag(?string $lastTag): array
63
    {
64 2
        $command = $lastTag ? "log {$lastTag}..HEAD --pretty=format:\"%H %s\"" : 'log --pretty=format:"%H %s"';
65
66 2
        return $this->runCommand($command);
67
    }
68
69
    /**
70
     * @throws GitCommandException
71
     */
72 14
    private function runCommand(string $command): array
73
    {
74 14
        exec("git {$command} 2>&1", $output, $returnCode);
75 14
        if (0 !== $returnCode) {
76 1
            throw new GitCommandException($command, $output);
77
        }
78
79 13
        return $output;
80
    }
81
82
    /**
83
     * Retrieves the list of changed files since the specified Git tag.
84
     *
85
     * This method executes a `git diff` command to analyze changes between the given tag and the current state.
86
     * It categorizes files into added, removed, modified, renamed, and copied groups, ensuring no file appears
87
     * in conflicting categories (e.g., a file cannot be both added and removed).
88
     *
89
     * @param null|string $lastTag    The Git tag to compare against. If null, compares against the initial commit.
90
     * @param string      $pathFilter optional path filter to limit the scope of the diff operation
91
     *
92
     * @return array<ModifiedFile> List DTO of changed files
93
     *
94
     * @throws VcsNoChangedFilesException if no changes are found since the specified tag
95
     * @throws GitCommandException        if there's an issue executing the `git diff` command
96
     */
97 3
    public function getFilesSinceTag(?string $lastTag, string $pathFilter = ''): array
98
    {
99 3
        $command = "diff --name-status {$lastTag}...";
100 3
        if (!empty($pathFilter)) {
101 1
            $command .= " -- {$pathFilter}";
102
        }
103 3
        $files = $this->runCommand($command);
104 3
        if (empty($files)) {
105 1
            throw new VcsNoChangedFilesException($lastTag);
0 ignored issues
show
Bug introduced by
It seems like $lastTag can also be of type null; however, parameter $tag of Vasoft\VersionIncrement\...xception::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
            throw new VcsNoChangedFilesException(/** @scrutinizer ignore-type */ $lastTag);
Loading history...
106
        }
107 2
        $collection = [];
108 2
        foreach ($files as $file) {
109 2
            $fields = explode("\t", $file);
110 2
            if (count($fields) < 2) {
111 1
                continue;
112
            }
113 2
            $status = trim($fields[0]);
114 2
            $status = $status[0];
115 2
            $filePath = trim($fields[1]);
116 2
            $oldFilePath = trim($fields[2] ?? '');
117 2
            $type = FileModifyType::tryFrom($status);
118 2
            if (null === $type) {
119 1
                continue;
120
            }
121 2
            $collection[] = new ModifiedFile($type, $filePath, $oldFilePath);
122
        }
123
124 2
        return $collection;
125
    }
126
}
127