Skip to content

Commit ae2527c

Browse files
committed
Add count to migrate/rollback
1 parent e13d291 commit ae2527c

File tree

4 files changed

+56
-8
lines changed

4 files changed

+56
-8
lines changed

src/Command/MigrateCommand.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Cake\Event\EventDispatcherTrait;
2121
use DateTime;
2222
use Exception;
23+
use LogicException;
2324
use Migrations\Config\ConfigInterface;
2425
use Migrations\Migration\ManagerFactory;
2526
use Throwable;
@@ -126,9 +127,12 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
126127
$date = $args->getOption('date');
127128
$fake = (bool)$args->getOption('fake');
128129

129-
$count = $args->getOption('count');
130-
if ($count) {
131-
$io->abort('The `--count` option is not supported yet in this command. Use `--target` instead.');
130+
$count = $args->getOption('count') !== null ? (int)$args->getOption('count') : null;
131+
if ($count && $date) {
132+
throw new LogicException('Can only use one of `--count` or `--date` options at a time.');
133+
}
134+
if ($version && $date) {
135+
throw new LogicException('Can only use one of `--version` or `--date` options at a time.');
132136
}
133137

134138
$factory = new ManagerFactory([
@@ -160,7 +164,7 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
160164
if ($date !== null) {
161165
$manager->migrateToDateTime(new DateTime((string)$date), $fake);
162166
} else {
163-
$manager->migrate($version, $fake);
167+
$manager->migrate($version, $fake, $count);
164168
}
165169
$end = microtime(true);
166170
} catch (Exception $e) {

src/Command/RollbackCommand.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use DateTime;
2222
use Exception;
2323
use InvalidArgumentException;
24+
use LogicException;
2425
use Migrations\Config\ConfigInterface;
2526
use Migrations\Migration\ManagerFactory;
2627
use Throwable;
@@ -77,6 +78,9 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
7778
])->addOption('date', [
7879
'short' => 'd',
7980
'help' => 'The date to rollback to',
81+
])->addOption('count', [
82+
'short' => 'k',
83+
'help' => 'The number of migrations to rollback',
8084
])->addOption('fake', [
8185
'help' => "Mark any migrations selected as run, but don't actually execute them",
8286
'boolean' => true,
@@ -130,6 +134,14 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
130134
$force = (bool)$args->getOption('force');
131135
$dryRun = (bool)$args->getOption('dry-run');
132136

137+
$count = $args->getOption('count') !== null ? (int)$args->getOption('count') : null;
138+
if ($count && $date) {
139+
throw new LogicException('Can only use one of `--count` or `--date` options at a time.');
140+
}
141+
if ($version && $date) {
142+
throw new LogicException('Can only use one of `--version` or `--date` options at a time.');
143+
}
144+
133145
$factory = new ManagerFactory([
134146
'plugin' => $args->getOption('plugin'),
135147
'source' => $args->getOption('source'),
@@ -162,7 +174,11 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
162174
try {
163175
// run the migrations
164176
$start = microtime(true);
165-
$manager->rollback($target, $force, $targetMustMatch, $fake);
177+
if ($count) {
178+
$manager->rollbackByCount($count, $force, $fake);
179+
} else {
180+
$manager->rollback($target, $force, $targetMustMatch, $fake);
181+
}
166182
$end = microtime(true);
167183
} catch (Exception $e) {
168184
$io->err('<error>' . $e->getMessage() . '</error>');

src/Migration/Manager.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,9 +365,10 @@ public function markVersionsAsMigrated(string $path, array $versions): array
365365
*
366366
* @param int|null $version version to migrate to
367367
* @param bool $fake flag that if true, we just record running the migration, but not actually do the migration
368+
* @param int|null $count Number of migrations to run, all migrations will be run if not set.
368369
* @return void
369370
*/
370-
public function migrate(?int $version = null, bool $fake = false): void
371+
public function migrate(?int $version = null, bool $fake = false, ?int $count = null): void
371372
{
372373
$migrations = $this->getMigrations();
373374
$env = $this->getEnvironment();
@@ -409,13 +410,15 @@ public function migrate(?int $version = null, bool $fake = false): void
409410
}
410411

411412
ksort($migrations);
413+
$done = 0;
412414
foreach ($migrations as $migration) {
413-
if ($migration->getVersion() > $version) {
415+
if ($migration->getVersion() > $version || ($count && $done >= $count)) {
414416
break;
415417
}
416418

417419
if (!in_array($migration->getVersion(), $versions)) {
418420
$this->executeMigration($migration, MigrationInterface::UP, $fake);
421+
$done++;
419422
}
420423
}
421424
}
@@ -535,6 +538,31 @@ protected function printStatusOutput(string $name, string $status, ?string $dura
535538
);
536539
}
537540

541+
/**
542+
* Rollback an environment to the specified version.
543+
*
544+
* @param int $count Count
545+
* @param bool $force Force
546+
* @param bool $fake Flag that if true, we just record running the migration, but not actually do the migration
547+
* @return void
548+
*/
549+
public function rollbackByCount(int $count, bool $force = false, bool $fake = false): void
550+
{
551+
// note that the version log are also indexed by name with the proper ascending order according to the version order
552+
$executedVersions = $this->getEnvironment()->getVersionLog();
553+
554+
$target = null;
555+
$total = count($executedVersions);
556+
$pos = 0;
557+
while ($pos < $total && $pos <= $count) {
558+
$last = array_pop($executedVersions);
559+
$target = $last['version'];
560+
$pos++;
561+
}
562+
563+
$this->rollback($target, $force, false, $fake);
564+
}
565+
538566
/**
539567
* Rollback an environment to the specified version.
540568
*

tests/TestCase/Command/CompletionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public function testMigrationsOptionsRollback()
103103
$this->exec('completion options migrations.migrations rollback');
104104
$this->assertCount(1, $this->_out->messages());
105105
$output = $this->_out->messages()[0];
106-
$expected = '--connection -c --date -d --dry-run -x --fake --force -f --help -h --no-lock --plugin -p';
106+
$expected = '--connection -c --count -k --date -d --dry-run -x --fake --force -f --help -h --no-lock --plugin -p';
107107
$expected .= ' --quiet -q --source -s --target -t --verbose -v';
108108
$outputExplode = explode(' ', trim($output));
109109
sort($outputExplode);

0 commit comments

Comments
 (0)