From 5b0b076dcb44d38a183963cc0f2876362793e947 Mon Sep 17 00:00:00 2001 From: Adam Prager Date: Mon, 16 Aug 2021 20:03:39 +0200 Subject: [PATCH] Allow version aliases to be used with execute command --- .../Tools/Console/Command/ExecuteCommand.php | 36 +++++-- .../Console/Command/ExecuteCommandTest.php | 94 ++++++++++++++++++- 2 files changed, 118 insertions(+), 12 deletions(-) diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php index 77f5d9dcc..0180001a0 100644 --- a/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php +++ b/lib/Doctrine/Migrations/Tools/Console/Command/ExecuteCommand.php @@ -38,7 +38,10 @@ protected function configure(): void ->addArgument( 'versions', InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'The versions to execute.', + sprintf( + 'The versions to execute. Use the FQCN of the migration, or the following reserved aliases: %s', + implode(', ', ['first', 'current', 'prev', 'next', 'latest']) + ), null ) ->addOption( @@ -76,6 +79,10 @@ protected function configure(): void The %command.name% command executes migration versions up or down manually: %command.full_name% FQCN + +You can use version aliases instead of the FQCN: + + %command.full_name% current You can show more information about the process by increasing the verbosity level. To see the executed queries, set the level to debug with -vv: @@ -113,20 +120,31 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory(); $migratorConfiguration = $migratorConfigurationFactory->getMigratorConfiguration($input); + $aliasResolver = $this->getDependencyFactory()->getVersionAliasResolver(); - $question = sprintf( - 'WARNING! You are about to execute a migration in database "%s" that could result in schema changes and data loss. Are you sure you wish to continue?', - $this->getDependencyFactory()->getConnection()->getDatabase() ?? '' - ); - if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input)) { - $this->io->error('Migration cancelled!'); + $versions = $input->getArgument('versions'); - return 1; + foreach ($versions as &$version) { + $version = (string) $aliasResolver->resolveVersionAlias($version); + } + + if (! $migratorConfiguration->isDryRun()) { + $this->io->listing($versions); + + $question = sprintf( + 'WARNING! You are about to execute the migrations listed above in database "%s" that could result in schema changes and data loss. Are you sure you wish to continue?', + $this->getDependencyFactory()->getConnection()->getDatabase() ?? '' + ); + + if (! $this->canExecute($question, $input)) { + $this->io->error('Migration cancelled!'); + + return 1; + } } $this->getDependencyFactory()->getMetadataStorage()->ensureInitialized(); - $versions = $input->getArgument('versions'); $direction = $input->getOption('down') !== false ? Direction::DOWN : Direction::UP; diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php index f299f44fd..a85ed730f 100644 --- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php +++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ExecuteCommandTest.php @@ -9,6 +9,7 @@ use Doctrine\Migrations\Configuration\Connection\ExistingConnection; use Doctrine\Migrations\Configuration\Migration\ExistingConfiguration; use Doctrine\Migrations\DependencyFactory; +use Doctrine\Migrations\Exception\UnknownMigrationVersion; use Doctrine\Migrations\Metadata\MigrationPlan; use Doctrine\Migrations\Metadata\MigrationPlanList; use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration; @@ -17,6 +18,7 @@ use Doctrine\Migrations\QueryWriter; use Doctrine\Migrations\Tests\MigrationTestCase; use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand; +use Doctrine\Migrations\Version\AliasResolver; use Doctrine\Migrations\Version\Direction; use Doctrine\Migrations\Version\MigrationPlanCalculator; use Doctrine\Migrations\Version\Version; @@ -47,6 +49,9 @@ class ExecuteCommandTest extends MigrationTestCase /** @var MigrationPlanCalculator|MockObject */ private $planCalculator; + /** @var AliasResolver|MockObject */ + private $versionAliasResolver; + /** * @param bool|string|null $arg * @@ -63,6 +68,12 @@ public function testWriteSql(bool $dryRun, $arg, ?string $path): void return ['A']; }); + $this->versionAliasResolver + ->expects(self::once()) + ->method('resolveVersionAlias') + ->with('1') + ->willReturn(new Version('1')); + if ($arg === false) { $this->queryWriter ->expects(self::never()) @@ -116,6 +127,12 @@ public function testExecute(): void return ['A']; }); + $this->versionAliasResolver + ->expects(self::once()) + ->method('resolveVersionAlias') + ->with('1') + ->willReturn(new Version('1')); + $this->executeCommandTester->execute([ 'versions' => ['1'], '--down' => true, @@ -125,6 +142,63 @@ public function testExecute(): void self::assertStringContainsString('[notice] Executing 1 up', trim($this->executeCommandTester->getDisplay(true))); } + public function testExecuteVersionAlias(): void + { + $this->executeCommandTester->setInputs(['yes']); + + $this->migrator + ->expects(self::once()) + ->method('migrate') + ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration): array { + self::assertFalse($configuration->isDryRun()); + + return ['A']; + }); + + $this->versionAliasResolver + ->expects(self::once()) + ->method('resolveVersionAlias') + ->with('current') + ->willReturn(new Version('1')); + + $this->executeCommandTester->execute([ + 'versions' => ['current'], + '--down' => true, + ]); + + self::assertSame(0, $this->executeCommandTester->getStatusCode()); + self::assertStringContainsString('[notice] Executing 1 up', trim($this->executeCommandTester->getDisplay(true))); + } + + public function testExecuteVersionAliasException(): void + { + $this->executeCommandTester->setInputs(['yes']); + + $this->migrator + ->expects(self::never()) + ->method('migrate') + ->willReturnCallback(static function (MigrationPlanList $planList, MigratorConfiguration $configuration): array { + self::assertFalse($configuration->isDryRun()); + + return ['A']; + }); + + $exception = new UnknownMigrationVersion('not_a_valid_version_alias'); + + $this->versionAliasResolver + ->expects(self::once()) + ->method('resolveVersionAlias') + ->with('not_a_valid_version_alias') + ->willThrowException($exception); + + self::expectExceptionObject($exception); + + $this->executeCommandTester->execute([ + 'versions' => ['not_a_valid_version_alias'], + '--down' => true, + ]); + } + public function testExecuteMultiple(): void { $migration = $this->createMock(AbstractMigration::class); @@ -148,6 +222,12 @@ public function testExecuteMultiple(): void return ['A']; }); + $this->versionAliasResolver + ->expects(self::exactly(2)) + ->method('resolveVersionAlias') + ->withConsecutive(['1'], ['2']) + ->willReturnOnConsecutiveCalls(new Version('1'), new Version('2')); + $this->executeCommandTester->execute([ 'versions' => ['1', '2'], '--down' => true, @@ -174,6 +254,12 @@ public function testExecuteCancel(): void return ['A']; }); + $this->versionAliasResolver + ->expects(self::once()) + ->method('resolveVersionAlias') + ->with('1') + ->willReturn(new Version('1')); + $this->executeCommandTester->execute([ 'versions' => ['1'], '--down' => true, @@ -186,9 +272,10 @@ protected function setUp(): void { $connection = $this->getSqliteConnection(); - $this->migrator = $this->createMock(Migrator::class); - $this->queryWriter = $this->createMock(QueryWriter::class); - $migration = $this->createMock(AbstractMigration::class); + $this->migrator = $this->createMock(Migrator::class); + $this->queryWriter = $this->createMock(QueryWriter::class); + $this->versionAliasResolver = $this->createMock(AliasResolver::class); + $migration = $this->createMock(AbstractMigration::class); $p1 = new MigrationPlan(new Version('1'), $migration, Direction::UP); $pl = new MigrationPlanList([$p1], Direction::UP); @@ -207,6 +294,7 @@ protected function setUp(): void $this->dependencyFactory->setService(Migrator::class, $this->migrator); $this->dependencyFactory->setService(MigrationPlanCalculator::class, $this->planCalculator); $this->dependencyFactory->setService(QueryWriter::class, $this->queryWriter); + $this->dependencyFactory->setService(AliasResolver::class, $this->versionAliasResolver); $this->executeCommand = new ExecuteCommand($this->dependencyFactory);