Skip to content

Commit 8407e6b

Browse files
authored
Add support for incrementing prerelease (#11)
1 parent 4301679 commit 8407e6b

10 files changed

Lines changed: 146 additions & 24 deletions

.vscode/settings.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"editor.defaultFormatter": "vscode.json-language-features"
7575
},
7676
"[php]": {
77-
"editor.defaultFormatter": "valeryanm.vscode-phpsab"
77+
"editor.defaultFormatter": "wongjn.php-sniffer"
7878
},
7979
"files.exclude": {
8080
"**/.git": true,
@@ -92,6 +92,5 @@
9292
"**/CVS/**"
9393
],
9494
"intelephense.compatibility.preferPsalmPhpstanPrefixedAnnotations": true,
95-
"phpsab.snifferMode": "onSave",
96-
"phpsab.snifferShowSources": true,
95+
"phpSniffer.run": "onSave",
9796
}

app/Commands/IncrementCommand.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
use Throwable;
1515
use Version\Version;
1616

17+
use function is_numeric;
1718
use function is_string;
1819
use function sprintf;
20+
use function trim;
1921

2022
final class IncrementCommand extends Command
2123
{
@@ -28,7 +30,7 @@ protected function configure(): void
2830
$this->setDescription('Increment a version');
2931
$this->setAliases(['incr']);
3032
$this->addArgument('version', InputArgument::REQUIRED, 'Version to increment');
31-
$this->addOption('part', 'p', InputArgument::OPTIONAL, 'Part to increment (major, minor, patch)', 'patch');
33+
$this->addOption('part', 'p', InputArgument::OPTIONAL, 'Part to increment (major, minor, patch, and prerelease)', 'patch');
3234
$this->addOption('build', 'b', InputArgument::OPTIONAL, 'Build metadata to append to the version');
3335
$this->addOption('pre', null, InputArgument::OPTIONAL, 'Pre-release identifier to append to the version');
3436
$this->setHelp(<<<'HELP'
@@ -104,11 +106,34 @@ private function increment(Version $version, string $part, $pre = null, $build =
104106
$version = $version->incrementPatch();
105107
break;
106108

109+
case 'prerelease':
110+
$currentPrerelease = $version->getPreRelease();
111+
112+
if ($currentPrerelease === null) {
113+
throw new InvalidArgumentException('Unable to increment prerelease on a version without a prerelease tag.');
114+
}
115+
116+
if ($pre !== null && is_string($pre) && $pre !== '') {
117+
throw new InvalidArgumentException('Specifying a prerelease tag when incrementing the prerelease part is not allowed.');
118+
}
119+
120+
$identifier = $currentPrerelease->getIdentifiers();
121+
$preTag = isset($identifier[0]) && is_string($identifier[0]) ? trim($identifier[0]) : null;
122+
123+
if ($preTag === null || $preTag === '') {
124+
throw new InvalidArgumentException('Unable to determine the prerelease tag for incrementing.');
125+
}
126+
127+
$preVersion = isset($identifier[1]) && is_numeric($identifier[1]) ? (int) $identifier[1] : 0;
128+
$version = $version->withPreRelease(sprintf('%s.%d', $preTag, $preVersion + 1));
129+
130+
break;
131+
107132
default:
108-
throw new InvalidArgumentException(sprintf("Invalid part '%s' provided. Expected 'major', 'minor', or 'patch'.", $part));
133+
throw new InvalidArgumentException(sprintf("Invalid part '%s' provided. Expected 'major', 'minor', 'patch', or 'prerelease'.", $part));
109134
}
110135

111-
if (is_string($pre) && $pre !== '') {
136+
if ($part !== 'prerelease' && is_string($pre) && $pre !== '') {
112137
$version = $version->withPreRelease($pre);
113138
}
114139

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
},
2424
"autoload-dev": {
2525
"psr-4": {
26-
"Syntatis\\Tests\\": "tests/"
26+
"Syntatis\\Tests\\": ["tests/", "tests/phpunit/"]
2727
}
2828
},
2929
"require": {

tests/bashunit/test_increment.sh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function test_increment_major() {
1717
}
1818

1919
# @data_provider data_increment_with_pre_release
20-
function test_increment_with_pre_release() {
20+
function test_increment_with_prerelease() {
2121
ver=$(bin/version increment $1 --pre alpha);
2222
assert_equals $ver $2;
2323
}
@@ -34,6 +34,16 @@ function test_increment_with_pre_release_and_build() {
3434
assert_equals $ver $2;
3535
}
3636

37+
# @data_provider data_increment_prerelease
38+
function test_increment_with_prerelease_and_build() {
39+
ver=$(bin/version increment $1 --part prerelease);
40+
assert_equals $ver $2;
41+
}
42+
43+
function data_increment_prerelease() {
44+
echo "1.0.0-beta" "1.0.0-beta.1";
45+
}
46+
3747
function data_increment_patch() {
3848
echo "0.0.0" "0.0.1";
3949
echo "1.0.0" "1.0.1";
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Syntatis\Tests\Commands;
6+
7+
use PHPUnit\Framework\TestCase;
8+
9+
use function preg_replace;
10+
use function str_replace;
11+
use function trim;
12+
13+
abstract class CommandTestCase extends TestCase
14+
{
15+
protected static function normalizeOutput(string $value): string
16+
{
17+
$output = self::canonicalize($value);
18+
$output = str_replace("\n", ' ', $output);
19+
$output = preg_replace('/\s+/', ' ', $output);
20+
21+
if ($output === null) {
22+
return $value;
23+
}
24+
25+
return trim($output);
26+
}
27+
28+
protected static function canonicalize(string $str): string
29+
{
30+
// normalize EOL style
31+
$str = str_replace("\r\n", "\n", $str);
32+
33+
// trim newlines at end
34+
$str = rtrim($str, "\n");
35+
36+
// remove trailing whitespace on all lines
37+
$lines = explode("\n", $str);
38+
$lines = array_map(static function ($line): string {
39+
return rtrim($line, " \t");
40+
}, $lines);
41+
42+
return implode("\n", $lines);
43+
}
44+
}

tests/phpunit/Commands/EqualCommandTest.php

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

55
namespace Syntatis\Tests\Commands;
66

7+
use Syntatis\Tests\Commands\CommandTestCase;
78
use PHPUnit\Framework\TestCase;
89
use Symfony\Component\Console\Tester\CommandTester;
910
use Syntatis\Version\CLI\Commander;
1011

1112
use function sprintf;
1213

13-
class EqualCommandTest extends TestCase
14+
class EqualCommandTest extends CommandTestCase
1415
{
1516
private Commander $commander;
1617
private CommandTester $tester;
@@ -30,7 +31,7 @@ public function testComparison(string $versionA, string $versionB, string $expec
3031

3132
self::assertStringContainsString(
3233
$expect,
33-
$this->tester->getDisplay(),
34+
self::normalizeOutput($this->tester->getDisplay()),
3435
);
3536
}
3637

tests/phpunit/Commands/GreaterThanCommandTest.php

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

55
namespace Syntatis\Tests\Commands;
66

7+
use Syntatis\Tests\Commands\CommandTestCase;
78
use PHPUnit\Framework\TestCase;
89
use Symfony\Component\Console\Tester\CommandTester;
910
use Syntatis\Version\CLI\Commander;
1011

1112
use function sprintf;
1213

13-
class GreaterThanCommandTest extends TestCase
14+
class GreaterThanCommandTest extends CommandTestCase
1415
{
1516
private Commander $commander;
1617
private CommandTester $tester;
@@ -30,7 +31,7 @@ public function testComparison(string $versionA, string $versionB, string $expec
3031

3132
self::assertStringContainsString(
3233
$expect,
33-
$this->tester->getDisplay(),
34+
self::normalizeOutput($this->tester->getDisplay()),
3435
);
3536
}
3637

tests/phpunit/Commands/IncrementCommandTest.php

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
namespace Syntatis\Tests\Commands;
66

7+
use Syntatis\Tests\Commands\CommandTestCase;
78
use PHPUnit\Framework\TestCase;
89
use Symfony\Component\Console\Tester\CommandTester;
910
use Syntatis\Version\CLI\Commander;
1011

1112
use function sprintf;
1213

13-
class IncrementCommandTest extends TestCase
14+
class IncrementCommandTest extends CommandTestCase
1415
{
1516
private Commander $commander;
1617
private CommandTester $tester;
@@ -30,7 +31,7 @@ public function testInvalidVersionArgument(string $version): void
3031

3132
self::assertStringContainsString(
3233
sprintf("[ERROR] Version string '%s' is not valid and cannot be parsed", $version),
33-
$this->tester->getDisplay(),
34+
self::normalizeOutput($this->tester->getDisplay()),
3435
);
3536
}
3637

@@ -40,7 +41,7 @@ public function testIncrementPatch(): void
4041

4142
self::assertStringContainsString(
4243
'1.0.1',
43-
$this->tester->getDisplay(),
44+
self::normalizeOutput($this->tester->getDisplay()),
4445
);
4546
}
4647

@@ -50,7 +51,7 @@ public function testIncrementMinor(): void
5051

5152
self::assertStringContainsString(
5253
'1.1.0',
53-
$this->tester->getDisplay(),
54+
self::normalizeOutput($this->tester->getDisplay()),
5455
);
5556
}
5657

@@ -60,7 +61,7 @@ public function testIncrementMajor(): void
6061

6162
self::assertStringContainsString(
6263
'2.0.0',
63-
$this->tester->getDisplay(),
64+
self::normalizeOutput($this->tester->getDisplay()),
6465
);
6566
}
6667

@@ -70,7 +71,7 @@ public function testIncrementWithBuildMetadata(): void
7071

7172
self::assertStringContainsString(
7273
'1.0.1+123',
73-
$this->tester->getDisplay(),
74+
self::normalizeOutput($this->tester->getDisplay()),
7475
);
7576
}
7677

@@ -80,7 +81,46 @@ public function testIncrementWithPreRelease(): void
8081

8182
self::assertStringContainsString(
8283
'1.0.1-beta',
83-
$this->tester->getDisplay(),
84+
self::normalizeOutput($this->tester->getDisplay()),
85+
);
86+
}
87+
88+
/**
89+
* @dataProvider dataIncrementPrerelease
90+
*/
91+
public function testIncrementPrerelease(string $version, string $expect): void
92+
{
93+
$this->tester->execute(['version' => $version, '--part' => 'prerelease']);
94+
95+
self::assertStringContainsString(
96+
$expect,
97+
self::normalizeOutput($this->tester->getDisplay()),
98+
);
99+
}
100+
101+
public static function dataIncrementPrerelease(): iterable
102+
{
103+
yield ['1.0.0-beta', '1.0.0-beta.1'];
104+
yield ['1.0.0-alpha.1', '1.0.0-alpha.2'];
105+
}
106+
107+
public function testIncrementPrereleaseWithPreTag(): void
108+
{
109+
$this->tester->execute(['version' => '1.0.0-beta', '--part' => 'prerelease', '--pre' => 'rc']);
110+
111+
self::assertStringContainsString(
112+
"[ERROR] Specifying a prerelease tag when incrementing the prerelease part is not allowed.",
113+
self::normalizeOutput($this->tester->getDisplay()),
114+
);
115+
}
116+
117+
public function testIncrementPrereleaseWithoutReleaseTag(): void
118+
{
119+
$this->tester->execute(['version' => '1.0.0', '--part' => 'prerelease']);
120+
121+
self::assertStringContainsString(
122+
"[ERROR] Unable to increment prerelease on a version without a prerelease tag.",
123+
self::normalizeOutput($this->tester->getDisplay()),
84124
);
85125
}
86126

tests/phpunit/Commands/LessThanCommandTest.php

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

55
namespace Syntatis\Tests\Commands;
66

7+
use Syntatis\Tests\Commands\CommandTestCase;
78
use PHPUnit\Framework\TestCase;
89
use Symfony\Component\Console\Tester\CommandTester;
910
use Syntatis\Version\CLI\Commander;
1011

1112
use function sprintf;
1213

13-
class LessThanCommandTest extends TestCase
14+
class LessThanCommandTest extends CommandTestCase
1415
{
1516
private Commander $commander;
1617
private CommandTester $tester;
@@ -30,7 +31,7 @@ public function testComparison(string $versionA, string $versionB, string $expec
3031

3132
self::assertStringContainsString(
3233
$expect,
33-
$this->tester->getDisplay(),
34+
self::normalizeOutput($this->tester->getDisplay()),
3435
);
3536
}
3637

tests/phpunit/Commands/ValidateCommandTest.php

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

55
namespace Syntatis\Tests\Commands;
66

7+
use Syntatis\Tests\Commands\CommandTestCase;
78
use PHPUnit\Framework\TestCase;
89
use Symfony\Component\Console\Tester\CommandTester;
910
use Syntatis\Version\CLI\Commander;
1011

1112
use function sprintf;
1213

13-
class ValidateCommandTest extends TestCase
14+
class ValidateCommandTest extends CommandTestCase
1415
{
1516
private Commander $commander;
1617
private CommandTester $tester;
@@ -30,7 +31,7 @@ public function testInvalidVersionArgument(string $version): void
3031

3132
self::assertStringContainsString(
3233
sprintf("[ERROR] Version string '%s' is not valid and cannot be parsed", $version),
33-
$this->tester->getDisplay(),
34+
self::normalizeOutput($this->tester->getDisplay()),
3435
);
3536
}
3637

@@ -41,7 +42,7 @@ public function testValidVersionArgument(string $version): void
4142

4243
self::assertStringContainsString(
4344
sprintf("[OK] Version string '%s' is valid and can be parsed", $version),
44-
$this->tester->getDisplay(),
45+
self::normalizeOutput($this->tester->getDisplay()),
4546
);
4647
}
4748

0 commit comments

Comments
 (0)