Skip to content

Commit ce15726

Browse files
committed
fix(binary): fix version checker for dolt and protoc
1 parent 5fc2846 commit ce15726

File tree

4 files changed

+178
-5
lines changed

4 files changed

+178
-5
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ Add the following to your `composer.json`:
176176
```
177177

178178
This configuration:
179+
179180
- Automatically downloads required binaries after `composer update`
180181
- Provides a custom command `composer get:binaries` to force download all binaries with detailed output
181182

resources/software.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
],
5151
"binary": {
5252
"name": "dolt",
53-
"version-command": "--version"
53+
"version-command": "version"
5454
}
5555
},
5656
{
@@ -137,4 +137,4 @@
137137
}
138138
}
139139
]
140-
}
140+
}

src/Module/Binary/Internal/VersionResolver.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class VersionResolver
1414
/**
1515
* Pattern to extract semantic version (X.Y.Z) from text.
1616
*/
17-
private const VERSION_PATTERN = '/(?:version:?\s*)?(?:v(?:er(?:sion)?)?\.?\s*)?(\d+\.\d+\.\d+(?:[-+][\w\.]+)?)/i';
17+
private const VERSION_PATTERN = '/(?:version:?\s*)?(?:v(?:er(?:sion)?)?\.?\s*)?(\d+\.\d+\.\d+(?:[-+][\w.]+)?)/i';
1818

1919
/**
2020
* Resolves the version from binary command output.
@@ -41,13 +41,18 @@ public function resolveVersion(string $output): ?string
4141
*/
4242
private function extractVersionWithFallbacks(string $output): ?string
4343
{
44+
// Fallback pattern for partial semver (e.g., "2.0")
45+
if (\preg_match('/version:?\s*(\d+\.\d+)/i', $output, $matches)) {
46+
return $matches[1];
47+
}
48+
4449
// Fallback pattern for simple digits-only version (e.g., "2", "15")
4550
if (\preg_match('/version:?\s*(\d+)/i', $output, $matches)) {
4651
return $matches[1];
4752
}
4853

49-
// Fallback pattern for partial semver (e.g., "2.0")
50-
if (\preg_match('/version:?\s*(\d+\.\d+)/i', $output, $matches)) {
54+
// Fallback pattern for 'libprotoc 30.2'
55+
if (\preg_match('/^[\w-]+\s+v?(\d+(?:\\.\d+){0,2})/i', $output, $matches)) {
5156
return $matches[1];
5257
}
5358

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Unit\Module\Binary\Internal;
6+
7+
use Internal\DLoad\Module\Binary\Internal\VersionResolver;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\DataProvider;
10+
use PHPUnit\Framework\TestCase;
11+
12+
#[CoversClass(VersionResolver::class)]
13+
final class VersionResolverTest extends TestCase
14+
{
15+
private VersionResolver $versionResolver;
16+
17+
/**
18+
* Provides test cases for semantic version extraction.
19+
*/
20+
public static function provideSemanticVersionOutputs(): \Generator
21+
{
22+
// Basic semantic versions
23+
yield 'simple semantic version' => [
24+
'App v1.2.3',
25+
'1.2.3',
26+
];
27+
28+
yield 'version with v prefix' => [
29+
'Version: v2.5.1',
30+
'2.5.1',
31+
];
32+
33+
yield 'version without v prefix' => [
34+
'Version: 3.7.12',
35+
'3.7.12',
36+
];
37+
38+
// Common version output formats
39+
yield 'CLI help with version' => [
40+
"MyApp CLI Tool\nVersion: 4.1.9\nUsage: myapp [options]",
41+
'4.1.9',
42+
];
43+
44+
yield 'verbose version output' => [
45+
"myapp version 2.0.10 (build 2023-04-15)\nCompiled with GCC 9.3.0",
46+
'2.0.10',
47+
];
48+
49+
// Version with pre-release or build metadata
50+
yield 'semver with pre-release' => [
51+
'Version 1.0.0-alpha.1',
52+
'1.0.0-alpha.1',
53+
];
54+
55+
yield 'semver with build metadata' => [
56+
'App version 2.3.4+20230415',
57+
'2.3.4+20230415',
58+
];
59+
60+
// Case insensitivity
61+
yield 'mixed case version string' => [
62+
'VERSION: 5.1.2',
63+
'5.1.2',
64+
];
65+
66+
// Spacing variations
67+
yield 'no space after version label' => [
68+
'version:1.0.5',
69+
'1.0.5',
70+
];
71+
72+
// RoadRunner
73+
yield 'roadrunner' => [
74+
'rr.exe version 2.12.3 (build time: 2023-02-16T13:08:35+0000, go1.20), OS: windows, arch: amd64',
75+
'2.12.3',
76+
];
77+
78+
// Protoc
79+
yield 'protoc' => [
80+
'libprotoc 30.2',
81+
'30.2',
82+
];
83+
84+
// Dolt
85+
yield 'dolt' => [
86+
'dolt version 1.51.1',
87+
'1.51.1',
88+
];
89+
}
90+
91+
/**
92+
* Provides test cases for fallback version extraction.
93+
*/
94+
public static function provideFallbackVersionOutputs(): \Generator
95+
{
96+
// Single digit version
97+
yield 'single digit version' => [
98+
'Version: 7',
99+
'7',
100+
];
101+
102+
// Partial semantic version
103+
yield 'partial semver with two components' => [
104+
'Application version 2.0',
105+
'2.0',
106+
];
107+
108+
// Edge cases
109+
yield 'version with text suffix' => [
110+
'version: 5 beta',
111+
'5',
112+
];
113+
114+
// Null cases
115+
yield 'non-version digit' => [
116+
'There are 5 items available',
117+
null,
118+
];
119+
}
120+
121+
/**
122+
* Tests that the resolver correctly extracts semantic versions.
123+
*/
124+
#[DataProvider('provideSemanticVersionOutputs')]
125+
public function testResolveVersionExtractsSemanticVersions(string $output, string $expectedVersion): void
126+
{
127+
// Act
128+
$result = $this->versionResolver->resolveVersion($output);
129+
130+
// Assert
131+
self::assertSame($expectedVersion, $result);
132+
}
133+
134+
/**
135+
* Tests that the resolver correctly extracts versions using fallback patterns.
136+
*/
137+
#[DataProvider('provideFallbackVersionOutputs')]
138+
public function testResolveVersionExtractsVersionsWithFallbacks(string $output, ?string $expectedVersion): void
139+
{
140+
// Act
141+
$result = $this->versionResolver->resolveVersion($output);
142+
143+
// Assert
144+
self::assertSame($expectedVersion, $result);
145+
}
146+
147+
/**
148+
* Tests that the resolver returns null when no version can be extracted.
149+
*/
150+
public function testResolveVersionReturnsNullWhenNoVersionFound(): void
151+
{
152+
// Arrange
153+
$output = 'This output contains no version information.';
154+
155+
// Act
156+
$result = $this->versionResolver->resolveVersion($output);
157+
158+
// Assert
159+
self::assertNull($result);
160+
}
161+
162+
protected function setUp(): void
163+
{
164+
// Arrange
165+
$this->versionResolver = new VersionResolver();
166+
}
167+
}

0 commit comments

Comments
 (0)