• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / version-bumper / 30636491704

31 Jul 2026 01:56PM UTC coverage: 88.594% (-0.5%) from 89.113%
30636491704

push

github

web-flow
Merge pull request #160 from eliashaeussler/fix/merge

[BUGFIX] Perform deep-merge of objects when applying config presets

18 of 24 new or added lines in 2 files covered. (75.0%)

2 existing lines in 1 file now uncovered.

1235 of 1394 relevant lines covered (88.59%)

5.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/src/Config/VersionBumperConfig.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the Composer package "eliashaeussler/version-bumper".
7
 *
8
 * Copyright (C) 2024-2026 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 3 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\VersionBumper\Config;
25

26
use EliasHaeussler\VersionBumper\Version;
27
use Symfony\Component\Filesystem;
28

29
/**
30
 * VersionBumperConfig.
31
 *
32
 * @author Elias Häußler <elias@haeussler.dev>
33
 * @license GPL-3.0-or-later
34
 */
35
final class VersionBumperConfig
36
{
37
    /**
38
     * @param list<Preset\Preset>         $presets
39
     * @param list<FileToModify>          $filesToModify
40
     * @param list<VersionRangeIndicator> $versionRangeIndicators
41
     */
42
    public function __construct(
4✔
43
        private readonly array $presets = [],
44
        private array $filesToModify = [],
45
        private ?string $rootPath = null,
46
        private readonly ReleaseOptions $releaseOptions = new ReleaseOptions(),
47
        private readonly array $versionRangeIndicators = [],
48
    ) {
49
        $this->resolveWildcardsInFiles();
4✔
50
    }
51

52
    /**
53
     * @return list<Preset\Preset>
54
     */
55
    public function presets(): array
×
56
    {
57
        return $this->presets;
×
58
    }
59

60
    /**
61
     * @return list<FileToModify>
62
     */
63
    public function filesToModify(): array
3✔
64
    {
65
        return $this->filesToModify;
3✔
66
    }
67

68
    public function hasActions(Version\Action\ActionType $type): bool
1✔
69
    {
70
        foreach ($this->filesToModify as $fileToModify) {
1✔
71
            if ([] !== $fileToModify->getActionsByType($type)) {
1✔
72
                return true;
1✔
73
            }
74
        }
75

76
        return false;
1✔
77
    }
78

79
    public function rootPath(): ?string
×
80
    {
81
        return $this->rootPath;
×
82
    }
83

84
    public function setRootPath(string $rootPath): self
1✔
85
    {
86
        $previousRootPath = $this->rootPath;
1✔
87

88
        $this->rootPath = $rootPath;
1✔
89

90
        if ($previousRootPath !== $rootPath) {
1✔
91
            $this->resolveWildcardsInFiles();
1✔
92
        }
93

94
        return $this;
1✔
95
    }
96

97
    public function releaseOptions(): ReleaseOptions
×
98
    {
99
        return $this->releaseOptions;
×
100
    }
101

102
    /**
103
     * @return list<VersionRangeIndicator>
104
     */
105
    public function versionRangeIndicators(): array
×
106
    {
107
        return $this->versionRangeIndicators;
×
108
    }
109

110
    private function resolveWildcardsInFiles(): void
4✔
111
    {
112
        $modified = false;
4✔
113
        $filesToModify = [];
4✔
114

115
        foreach ($this->filesToModify as $fileToModify) {
4✔
116
            $path = $fileToModify->path();
4✔
117

118
            // Skip files without wildcards
119
            if (!str_contains($path, '*')) {
4✔
UNCOV
120
                $filesToModify[] = $fileToModify;
×
121

UNCOV
122
                continue;
×
123
            }
124

125
            $isRelative = Filesystem\Path::isRelative($path);
4✔
126

127
            if ($isRelative) {
4✔
128
                // We cannot process relative paths if root path is not set
129
                if (null === $this->rootPath) {
4✔
130
                    $filesToModify[] = $fileToModify;
4✔
131

132
                    continue;
4✔
133
                }
134

135
                $fullPath = $fileToModify->fullPath($this->rootPath);
2✔
136
            } else {
137
                $fullPath = $path;
4✔
138
            }
139

140
            $files = glob($fullPath);
4✔
141

142
            // Skip wildcard resolution if glob fails
143
            if (false === $files) {
4✔
144
                $filesToModify[] = $fileToModify;
×
145

146
                continue;
×
147
            }
148

149
            foreach ($files as $file) {
4✔
150
                $filesToModify[] = new FileToModify(
4✔
151
                    $isRelative ? Filesystem\Path::makeRelative($file, $this->rootPath) : $file,
4✔
152
                    $fileToModify->patterns(),
4✔
153
                    $fileToModify->reportUnmatched(),
4✔
154
                    $fileToModify->reportMissing(),
4✔
155
                    $fileToModify->preActions(),
4✔
156
                    $fileToModify->postActions(),
4✔
157
                );
4✔
158
            }
159

160
            $modified = true;
4✔
161
        }
162

163
        if ($modified) {
4✔
164
            $this->filesToModify = $filesToModify;
4✔
165
        }
166
    }
167
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc