Skip to content

Commit 1126d57

Browse files
committed
Add the ability to find min required rr version
1 parent 5bb9aa2 commit 1126d57

8 files changed

Lines changed: 134 additions & 8 deletions

File tree

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
"license": "MIT",
1111
"require": {
1212
"php": "^8.1",
13-
"symfony/process": "^5.4 || ^6.0"
13+
"symfony/process": "^5.4 || ^6.0",
14+
"composer-runtime-api": "^2.0",
15+
"composer/semver": "^3.3"
1416
},
1517
"require-dev": {
1618
"phpunit/phpunit": "^9.6 || ^10.0",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RoadRunner\VersionChecker\Exception;
6+
7+
final class RequiredVersionException extends VersionCheckerException
8+
{
9+
}

src/Version/Comparator.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace RoadRunner\VersionChecker\Version;
66

7+
use Composer\Semver\Comparator as SemverComparator;
8+
79
final class Comparator implements ComparatorInterface
810
{
911
/**
@@ -12,7 +14,7 @@ final class Comparator implements ComparatorInterface
1214
*/
1315
public function greaterThan(string $requested, string $installed): bool
1416
{
15-
return \version_compare($installed, $requested) >= 0;
17+
return SemverComparator::greaterThanOrEqualTo($installed, $requested);
1618
}
1719

1820
/**
@@ -21,7 +23,7 @@ public function greaterThan(string $requested, string $installed): bool
2123
*/
2224
public function lessThan(string $requested, string $installed): bool
2325
{
24-
return \version_compare($installed, $requested) <= 0;
26+
return SemverComparator::lessThanOrEqualTo($installed, $requested);
2527
}
2628

2729
/**
@@ -30,6 +32,6 @@ public function lessThan(string $requested, string $installed): bool
3032
*/
3133
public function equal(string $requested, string $installed): bool
3234
{
33-
return \version_compare($installed, $requested) === 0;
35+
return SemverComparator::equalTo($installed, $requested);
3436
}
3537
}

src/Version/Required.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,55 @@
44

55
namespace RoadRunner\VersionChecker\Version;
66

7+
use Composer\InstalledVersions;
8+
use Composer\Semver\Comparator as SemverComparator;
9+
use Composer\Semver\VersionParser;
10+
711
final class Required implements RequiredInterface
812
{
13+
private const ROADRUNNER_PACKAGE = 'spiral/roadrunner';
14+
915
/**
16+
* @return non-empty-string|null
17+
*/
18+
public function getRequiredVersion(): ?string
19+
{
20+
$parser = new VersionParser();
21+
22+
$version = null;
23+
foreach (InstalledVersions::getInstalledPackages() as $package) {
24+
$path = InstalledVersions::getInstallPath($package);
25+
if ($path !== null && \file_exists($path . '/composer.json')) {
26+
/** @var array $composerJson */
27+
$composerJson = \json_decode(\file_get_contents($path . '/composer.json'), true);
28+
29+
if (isset($composerJson['require']) && \is_array($composerJson['require'])) {
30+
/** @var non-empty-string $packageVersion */
31+
foreach ($composerJson['require'] as $package => $packageVersion) {
32+
if ($package === self::ROADRUNNER_PACKAGE) {
33+
/** @var non-empty-string $packageVersion */
34+
$packageVersion = $parser->normalize($packageVersion);
35+
$version = $this->getMinimumVersion($packageVersion, $version);
36+
}
37+
}
38+
}
39+
}
40+
}
41+
42+
return $version;
43+
}
44+
45+
/**
46+
* @param non-empty-string $version
47+
* @param non-empty-string|null $previous
1048
* @return non-empty-string
1149
*/
12-
public function getRequiredVersion(): string
50+
private function getMinimumVersion(string $version, ?string $previous = null): string
1351
{
14-
return '1.0'; // TODO need implementation
52+
if ($previous === null) {
53+
return $version;
54+
}
55+
56+
return SemverComparator::lessThan($version, $previous) ? $version : $previous;
1557
}
1658
}

src/Version/RequiredInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
interface RequiredInterface
88
{
99
/**
10-
* @return non-empty-string
10+
* @return non-empty-string|null
1111
*/
12-
public function getRequiredVersion(): string;
12+
public function getRequiredVersion(): ?string;
1313
}

src/VersionChecker.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace RoadRunner\VersionChecker;
66

7+
use RoadRunner\VersionChecker\Exception\RequiredVersionException;
78
use RoadRunner\VersionChecker\Exception\RoadrunnerNotInstalledException;
89
use RoadRunner\VersionChecker\Exception\UnsupportedVersionException;
910
use RoadRunner\VersionChecker\Version\Comparator;
@@ -27,12 +28,21 @@ public function __construct(
2728
*
2829
* @throws UnsupportedVersionException
2930
* @throws RoadrunnerNotInstalledException
31+
* @throws RequiredVersionException
3032
*/
3133
public function greaterThan(?string $version = null): void
3234
{
3335
if (empty($version)) {
3436
$version = $this->requiredVersion->getRequiredVersion();
3537
}
38+
39+
if (empty($version)) {
40+
throw new RequiredVersionException(
41+
'Unable to determine required RoadRunner version.' .
42+
' Please specify the required version in the `$version` parameter.'
43+
);
44+
}
45+
3646
$installedVersion = $this->installedVersion->getInstalledVersion();
3747

3848
if (!$this->comparator->greaterThan($version, $installedVersion)) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace RoadRunner\VersionChecker\Tests\Unit\Version;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use RoadRunner\VersionChecker\Version\Required;
9+
10+
final class RequiredTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider versionsDataProvider
14+
*/
15+
public function testGetMinimumVersion(string $version, ?string $previous, string $expected): void
16+
{
17+
$required = new Required();
18+
$ref = new \ReflectionMethod($required, 'getMinimumVersion');
19+
20+
$this->assertSame($expected, $ref->invoke($required, $version, $previous));
21+
}
22+
23+
public static function versionsDataProvider(): \Traversable
24+
{
25+
// Test case with $previous === null
26+
yield ['1.0.0', null, '1.0.0'];
27+
28+
// Test case with $version < $previous
29+
yield ['1.0.0', '2.0.0', '1.0.0'];
30+
yield ['1.0.0-alpha', '1.0.0', '1.0.0-alpha'];
31+
32+
// Test case with $version >= $previous
33+
yield ['2.0.0', '1.0.0', '1.0.0'];
34+
yield ['1.0.0', '1.0.0-alpha', '1.0.0-alpha'];
35+
yield ['1.0.0', '1.0.0', '1.0.0'];
36+
}
37+
}

tests/src/Unit/VersionCheckerTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace RoadRunner\VersionChecker\Tests\Unit;
66

77
use PHPUnit\Framework\TestCase;
8+
use RoadRunner\VersionChecker\Exception\RequiredVersionException;
89
use RoadRunner\VersionChecker\Exception\UnsupportedVersionException;
910
use RoadRunner\VersionChecker\Version\ComparatorInterface;
1011
use RoadRunner\VersionChecker\Version\InstalledInterface;
@@ -61,6 +62,29 @@ public function testSuccessGreaterThanWithVersion(): void
6162
$checker->greaterThan('1.0');
6263
}
6364

65+
public function testGreaterThanWithoutVersionAndWithoutRoadRunnerPackage(): void
66+
{
67+
$comparator = $this->createMock(ComparatorInterface::class);
68+
$comparator
69+
->expects($this->never())
70+
->method('greaterThan');
71+
72+
$requiredVersion = $this->createMock(RequiredInterface::class);
73+
$requiredVersion
74+
->expects($this->once())
75+
->method('getRequiredVersion')
76+
->willReturn(null);
77+
78+
$checker = new VersionChecker(
79+
$this->createMock(InstalledInterface::class),
80+
$requiredVersion,
81+
$comparator
82+
);
83+
84+
$this->expectException(RequiredVersionException::class);
85+
$checker->greaterThan();
86+
}
87+
6488
/**
6589
* @dataProvider invalidVersionsDataProvider
6690
*/

0 commit comments

Comments
 (0)