From 03ec0cb0ed3b601d51a848cfe52ee387313e5654 Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Mon, 13 Jan 2020 07:37:26 +0100 Subject: [PATCH] added list command # Conflicts: # lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php --- UPGRADE.md | 2 + docs/en/reference/custom-configuration.rst | 4 +- docs/en/reference/custom-integration.rst | 4 +- .../Tools/Console/Command/ListCommand.php | 128 ++++++++++++++++++ .../Tools/Console/Command/StatusCommand.php | 77 ----------- .../Tools/Console/ConsoleRunner.php | 2 + .../Tools/Console/Command/ListCommandTest.php | 99 ++++++++++++++ .../Console/Command/StatusCommandTest.php | 76 +---------- .../Tests/Tools/Console/ConsoleRunnerTest.php | 4 +- 9 files changed, 240 insertions(+), 156 deletions(-) create mode 100644 lib/Doctrine/Migrations/Tools/Console/Command/ListCommand.php create mode 100644 tests/Doctrine/Migrations/Tests/Tools/Console/Command/ListCommandTest.php diff --git a/UPGRADE.md b/UPGRADE.md index 42b84f516f..211c2af3c8 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -9,6 +9,8 @@ please refer to the [Code BC breaks](#code-bc-breaks) section. please update your scripts. Console output is not covered by the BC promise, so please try not to rely on specific a output. Different levels of verbosity are available now (`-v`, `-vv` and `-vvv` ). +- The `--show-versions` option from `migrations:status` command has been removed, + use `migrations:list` instead. ## Migrations table diff --git a/docs/en/reference/custom-configuration.rst b/docs/en/reference/custom-configuration.rst index 20098a2f81..3b29ecd82c 100644 --- a/docs/en/reference/custom-configuration.rst +++ b/docs/en/reference/custom-configuration.rst @@ -57,10 +57,12 @@ Once you have your custom integration setup, you can modify it to look like the new Command\ExecuteCommand($dependencyFactory), new Command\GenerateCommand($dependencyFactory), new Command\LatestCommand($dependencyFactory), + new Command\ListCommand($dependencyFactory), new Command\MigrateCommand($dependencyFactory), new Command\RollupCommand($dependencyFactory), new Command\StatusCommand($dependencyFactory), - new Command\VersionCommand($dependencyFactory) + new Command\SyncMetadataCommand($dependencyFactory), + new Command\VersionCommand($dependencyFactory), )); $cli->run(); diff --git a/docs/en/reference/custom-integration.rst b/docs/en/reference/custom-integration.rst index 5e02ddb937..367c3a16e4 100644 --- a/docs/en/reference/custom-integration.rst +++ b/docs/en/reference/custom-integration.rst @@ -48,10 +48,12 @@ Now place the following code in the ``migrations`` file: new Command\ExecuteCommand($dependencyFactory), new Command\GenerateCommand($dependencyFactory), new Command\LatestCommand($dependencyFactory), + new Command\ListCommand($dependencyFactory), new Command\MigrateCommand($dependencyFactory), new Command\RollupCommand($dependencyFactory), new Command\StatusCommand($dependencyFactory), - new Command\VersionCommand($dependencyFactory) + new Command\SyncMetadataCommand($dependencyFactory), + new Command\VersionCommand($dependencyFactory), )); $cli->run(); diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/ListCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/ListCommand.php new file mode 100644 index 0000000000..bca9817ab7 --- /dev/null +++ b/lib/Doctrine/Migrations/Tools/Console/Command/ListCommand.php @@ -0,0 +1,128 @@ +setAliases(['list-migrations']) + ->setDescription('Display a list of all available migrations and their status.') + ->setHelp(<<%command.name% command outputs a list of all available migrations and their status: + + %command.full_name% +EOT + ); + + parent::configure(); + } + + public function execute(InputInterface $input, OutputInterface $output) : int + { + $this->showVersions( + $this->getDependencyFactory()->getMigrationRepository()->getMigrations(), // available migrations + $this->getDependencyFactory()->getMetadataStorage()->getExecutedMigrations(), // executed migrations + $output + ); + + return 0; + } + + private function showVersions( + AvailableMigrationsList $availableMigrations, + ExecutedMigrationsSet $executedMigrations, + OutputInterface $output + ) : void { + $table = new Table($output); + $table->setHeaders( + [ + [new TableCell('Migration Versions', ['colspan' => 4])], + ['Migration', 'Status', 'Migrated At', 'Execution Time', 'Description'], + ] + ); + + foreach ($this->getSortedVersions($availableMigrations, $executedMigrations) as $version) { + $description = null; + $executedAt = null; + $executionTime = null; + + if ($executedMigrations->hasMigration($version)) { + $executedMigration = $executedMigrations->getMigration($version); + $executionTime = $executedMigration->getExecutionTime(); + $executedAt = $executedMigration->getExecutedAt() instanceof DateTimeInterface + ? $executedMigration->getExecutedAt()->format('Y-m-d H:i:s') + : null; + } + + if ($availableMigrations->hasMigration($version)) { + $description = $availableMigrations->getMigration($version)->getMigration()->getDescription(); + } + + if ($executedMigrations->hasMigration($version) && $availableMigrations->hasMigration($version)) { + $status = 'migrated'; + } elseif ($executedMigrations->hasMigration($version)) { + $status = 'migrated, not available'; + } else { + $status = 'not migrated'; + } + + $table->addRow([ + (string) $version, + $status, + (string) $executedAt, + $executionTime !== null ? $executionTime . 's': '', + $description, + ]); + } + + $table->render(); + } + + /** + * @return Version[] + */ + private function getSortedVersions(AvailableMigrationsList $availableMigrations, ExecutedMigrationsSet $executedMigrations) : array + { + $availableVersions = array_map(static function (AvailableMigration $availableMigration) : Version { + return $availableMigration->getVersion(); + }, $availableMigrations->getItems()); + + $executedVersions = array_map(static function (ExecutedMigration $executedMigration) : Version { + return $executedMigration->getVersion(); + }, $executedMigrations->getItems()); + + $versions = array_unique(array_merge($availableVersions, $executedVersions)); + + $comparator = $this->getDependencyFactory()->getVersionComparator(); + uasort($versions, static function (Version $a, Version $b) use ($comparator) : int { + return $comparator->compare($a, $b); + }); + + return $versions; + } +} diff --git a/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php b/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php index 7e9966867b..42f3e73773 100644 --- a/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php +++ b/lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php @@ -4,15 +4,9 @@ namespace Doctrine\Migrations\Tools\Console\Command; -use DateTimeImmutable; -use Doctrine\Migrations\Metadata\AvailableMigrationsList; -use Doctrine\Migrations\Metadata\ExecutedMigrationsSet; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use function count; /** * The StatusCommand class is responsible for outputting what the current state is of all your migrations. It shows @@ -38,10 +32,6 @@ protected function configure() : void The %command.name% command outputs the status of a set of migrations: %command.full_name% - -You can output a list of all available migrations and their status with --show-versions: - - %command.full_name% --show-versions EOT ); @@ -63,73 +53,6 @@ public function execute(InputInterface $input, OutputInterface $output) : ?int $infosHelper = $this->getDependencyFactory()->getMigrationStatusInfosHelper(); $infosHelper->showMigrationsInfo($output, $availableMigrations, $executedMigrations, $newMigrations, $executedUnavailableMigrations); - if ($input->getOption('show-versions') === false) { - return 0; - } - - if (count($availableMigrations) !== 0) { - $this->showVersions($availableMigrations, $executedMigrations, $output); - } - - if (count($executedUnavailableMigrations) !== 0) { - $this->showUnavailableVersions($output, $executedUnavailableMigrations); - } - return 0; } - - private function showUnavailableVersions(OutputInterface $output, ExecutedMigrationsSet $executedUnavailableMigrations) : void - { - $table = new Table($output); - $table->setHeaders( - [ - [new TableCell('Previously Executed Unavailable Migration Versions', ['colspan' => 2])], - ['Migration', 'Migrated At'], - ] - ); - foreach ($executedUnavailableMigrations->getItems() as $executedUnavailableMigration) { - $table->addRow([ - (string) $executedUnavailableMigration->getVersion(), - $executedUnavailableMigration->getExecutedAt() !== null - ? $executedUnavailableMigration->getExecutedAt()->format('Y-m-d H:i:s') - : null, - ]); - } - - $table->render(); - } - - private function showVersions( - AvailableMigrationsList $availableMigrationsSet, - ExecutedMigrationsSet $executedMigrationsSet, - OutputInterface $output - ) : void { - $table = new Table($output); - $table->setHeaders( - [ - [new TableCell('Available Migration Versions', ['colspan' => 4])], - ['Migration', 'Migrated', 'Migrated At', 'Description'], - ] - ); - foreach ($availableMigrationsSet->getItems() as $availableMigration) { - $executedMigration = $executedMigrationsSet->hasMigration($availableMigration->getVersion()) - ? $executedMigrationsSet->getMigration($availableMigration->getVersion()) - : null; - - $executedAt = $executedMigration!==null && $executedMigration->getExecutedAt() instanceof DateTimeImmutable - ? $executedMigration->getExecutedAt()->format('Y-m-d H:i:s') - : null; - - $description = $availableMigration->getMigration()->getDescription(); - - $table->addRow([ - (string) $availableMigration->getVersion(), - $executedMigration !== null ? 'migrated' : 'not migrated', - (string) $executedAt, - $description, - ]); - } - - $table->render(); - } } diff --git a/lib/Doctrine/Migrations/Tools/Console/ConsoleRunner.php b/lib/Doctrine/Migrations/Tools/Console/ConsoleRunner.php index bba5af2750..dc7429d82d 100644 --- a/lib/Doctrine/Migrations/Tools/Console/ConsoleRunner.php +++ b/lib/Doctrine/Migrations/Tools/Console/ConsoleRunner.php @@ -11,6 +11,7 @@ use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand; use Doctrine\Migrations\Tools\Console\Command\GenerateCommand; use Doctrine\Migrations\Tools\Console\Command\LatestCommand; +use Doctrine\Migrations\Tools\Console\Command\ListCommand; use Doctrine\Migrations\Tools\Console\Command\MigrateCommand; use Doctrine\Migrations\Tools\Console\Command\RollupCommand; use Doctrine\Migrations\Tools\Console\Command\StatusCommand; @@ -109,6 +110,7 @@ public static function addCommands(Application $cli, ?DependencyFactory $depende new VersionCommand($dependencyFactory), new UpToDateCommand($dependencyFactory), new SyncMetadataCommand($dependencyFactory), + new ListCommand($dependencyFactory), ]); if ($dependencyFactory === null || ! $dependencyFactory->hasEntityManager()) { diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ListCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ListCommandTest.php new file mode 100644 index 0000000000..c85b954607 --- /dev/null +++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/ListCommandTest.php @@ -0,0 +1,99 @@ +setMetadataStorageConfiguration(new TableMetadataStorageConfiguration()); + $configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir()); + + $conn = $this->getSqliteConnection(); + + $dependencyFactory = DependencyFactory::fromConnection( + new Configuration\ExistingConfiguration($configuration), + new ExistingConnection($conn) + ); + + $this->migrationRepository = $dependencyFactory->getMigrationRepository(); + $this->metadataStorage = $dependencyFactory->getMetadataStorage(); + + $this->metadataStorage->ensureInitialized(); + + $this->command = new ListCommand($dependencyFactory); + $this->commandTester = new CommandTester($this->command); + } + + public function testExecute() : void + { + $migrationClass = $this->createMock(AbstractMigration::class); + $migrationClass + ->expects(self::atLeastOnce()) + ->method('getDescription') + ->willReturn('foo'); + + $this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass); + $this->migrationRepository->registerMigrationInstance(new Version('1230'), $migrationClass); + + $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04')); + $result->setTime(10.0); + $this->metadataStorage->complete($result); + + $result = new ExecutionResult(new Version('1229'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04')); + $this->metadataStorage->complete($result); + + $this->commandTester->execute([]); + + $lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true)))); + + self::assertSame( + [ + 0 => '+-----------+-------------------------+---------------------+----------------+-------------+', + 1 => '| Migration Versions | |', + 2 => '+-----------+-------------------------+---------------------+----------------+-------------+', + 3 => '| Migration | Status | Migrated At | Execution Time | Description |', + 4 => '+-----------+-------------------------+---------------------+----------------+-------------+', + 5 => '| 1229 | migrated, not available | 2010-01-01 02:03:04 | | |', + 6 => '| 1230 | migrated | 2010-01-01 02:03:04 | 10s | foo |', + 7 => '| 1231 | not migrated | | | foo |', + 8 => '+-----------+-------------------------+---------------------+----------------+-------------+', + ], + $lines + ); + } +} diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php index 88b2ecf0e3..7ebbe12eb4 100644 --- a/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php +++ b/tests/Doctrine/Migrations/Tests/Tools/Console/Command/StatusCommandTest.php @@ -5,13 +5,11 @@ namespace Doctrine\Migrations\Tests\Tools\Console\Command; use DateTimeImmutable; -use Doctrine\Migrations\AbstractMigration; use Doctrine\Migrations\Configuration\Configuration; use Doctrine\Migrations\Configuration\Connection\ExistingConnection; use Doctrine\Migrations\DependencyFactory; use Doctrine\Migrations\Metadata\Storage\MetadataStorage; use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration; -use Doctrine\Migrations\MigrationRepository; use Doctrine\Migrations\Tests\MigrationTestCase; use Doctrine\Migrations\Tools\Console\Command\StatusCommand; use Doctrine\Migrations\Version\Direction; @@ -31,9 +29,6 @@ class StatusCommandTest extends MigrationTestCase /** @var StatusCommand */ private $command; - /** @var MigrationRepository */ - private $migrationRepository; - /** @var MetadataStorage */ private $metadataStorage; @@ -53,8 +48,7 @@ protected function setUp() : void new ExistingConnection($conn) ); - $this->migrationRepository = $dependencyFactory->getMigrationRepository(); - $this->metadataStorage = $dependencyFactory->getMetadataStorage(); + $this->metadataStorage = $dependencyFactory->getMetadataStorage(); $this->metadataStorage->ensureInitialized(); @@ -114,72 +108,4 @@ public function testExecute() : void $lines ); } - - public function testExecuteDetails() : void - { - $migrationClass = $this->createMock(AbstractMigration::class); - $this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass); - $this->migrationRepository->registerMigrationInstance(new Version('1230'), $migrationClass); - - $result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04')); - $result->setTime(10.0); - $this->metadataStorage->complete($result); - - $result = new ExecutionResult(new Version('1233'), Direction::UP); - $this->metadataStorage->complete($result); - - $this->commandTester->execute( - ['--show-versions' => true], - ['interactive' => false] - ); - - $lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true)))); - self::assertSame( - [ - 0 => '+----------------------+----------------------+------------------------------------------------------------------------+', - 1 => '| Configuration |', - 2 => '+----------------------+----------------------+------------------------------------------------------------------------+', - 3 => '| Project | Doctrine Database Migrations |', - 4 => '|----------------------------------------------------------------------------------------------------------------------|', - 5 => '| Project | Doctrine Database Migrations |', - 6 => '|----------------------------------------------------------------------------------------------------------------------|', - 7 => '| Storage | Type | Doctrine\\Migrations\\Metadata\\Storage\\TableMetadataStorageConfiguration |', - 8 => '| | Table Name | doctrine_migration_versions |', - 9 => '| | Column Name | version |', - 10 => '|----------------------------------------------------------------------------------------------------------------------|', - 11 => '| Database | Driver | pdo_sqlite |', - 12 => '| | Host | |', - 13 => '| | Name | |', - 14 => '|----------------------------------------------------------------------------------------------------------------------|', - 15 => '| Versions | Previous | 1230 |', - 16 => '| | Current | 1233 |', - 17 => '| | Next | 1231 |', - 18 => '| | Latest | 1231 |', - 19 => '|----------------------------------------------------------------------------------------------------------------------|', - 20 => '| Migrations | Executed | 2 |', - 21 => '| | Executed Unavailable | 1 |', - 22 => '| | Available | 2 |', - 23 => '| | New | 1 |', - 24 => '|----------------------------------------------------------------------------------------------------------------------|', - 25 => sprintf('| Migration Namespaces | DoctrineMigrations | %s |', str_pad(sys_get_temp_dir(), 70)), - 26 => '+----------------------+----------------------+------------------------------------------------------------------------+', - 27 => '+-----------+--------------+---------------------+-------------+', - 28 => '| Available Migration Versions |', - 29 => '+-----------+--------------+---------------------+-------------+', - 30 => '| Migration | Migrated | Migrated At | Description |', - 31 => '+-----------+--------------+---------------------+-------------+', - 32 => '| 1230 | migrated | 2010-01-01 02:03:04 | |', - 33 => '| 1231 | not migrated | | |', - 34 => '+-----------+--------------+---------------------+-------------+', - 35 => '+---------------------------+---------------------------+', - 36 => '| Previously Executed Unavailable Migration Versions |', - 37 => '+---------------------------+---------------------------+', - 38 => '| Migration | Migrated At |', - 39 => '+---------------------------+---------------------------+', - 40 => '| 1233 | |', - 41 => '+---------------------------+---------------------------+', - ], - $lines - ); - } } diff --git a/tests/Doctrine/Migrations/Tests/Tools/Console/ConsoleRunnerTest.php b/tests/Doctrine/Migrations/Tests/Tools/Console/ConsoleRunnerTest.php index 43821b3907..eab2520fcc 100644 --- a/tests/Doctrine/Migrations/Tests/Tools/Console/ConsoleRunnerTest.php +++ b/tests/Doctrine/Migrations/Tests/Tools/Console/ConsoleRunnerTest.php @@ -172,7 +172,7 @@ public function testCreateApplication() : void { $application = ConsoleRunner::createApplication(); $commands = $application->all('migrations'); - self::assertCount(10, $commands); + self::assertCount(11, $commands); } public function testCreateApplicationWithEntityManager() : void @@ -185,7 +185,7 @@ public function testCreateApplicationWithEntityManager() : void $application = ConsoleRunner::createApplication([], $dependencyFactory); $commands = $application->all('migrations'); - self::assertCount(11, $commands); + self::assertCount(12, $commands); } protected function setUp() : void