Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CakeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function printStatus(string $environment, ?string $format = null): array
$migrations = [];
$isJson = $format === 'json';
$defaultMigrations = $this->getMigrations('default');
if (count($defaultMigrations)) {
if ($defaultMigrations) {
$env = $this->getEnvironment($environment);
$versions = $env->getVersionLog();
$this->maxNameLength = $versions ? max(array_map(function ($version) {
Expand Down
15 changes: 11 additions & 4 deletions src/Command/MigrateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Cake\Event\EventDispatcherTrait;
use DateTime;
use Exception;
use LogicException;
use Migrations\Config\ConfigInterface;
use Migrations\Migration\ManagerFactory;
use Throwable;
Expand Down Expand Up @@ -126,9 +127,15 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
$date = $args->getOption('date');
$fake = (bool)$args->getOption('fake');

$count = $args->getOption('count');
if ($count) {
$io->abort('The `--count` option is not supported yet in this command. Use `--target` instead.');
$count = $args->getOption('count') !== null ? (int)$args->getOption('count') : null;
if ($count !== null && $count < 1) {
throw new LogicException('Count must be > 0.');
}
if ($count && $date) {
throw new LogicException('Can only use one of `--count` or `--date` options at a time.');
}
if ($version && $date) {
throw new LogicException('Can only use one of `--version` or `--date` options at a time.');
}

$factory = new ManagerFactory([
Expand Down Expand Up @@ -160,7 +167,7 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
if ($date !== null) {
$manager->migrateToDateTime(new DateTime((string)$date), $fake);
} else {
$manager->migrate($version, $fake);
$manager->migrate($version, $fake, $count);
}
$end = microtime(true);
} catch (Exception $e) {
Expand Down
21 changes: 20 additions & 1 deletion src/Command/RollbackCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use DateTime;
use Exception;
use InvalidArgumentException;
use LogicException;
use Migrations\Config\ConfigInterface;
use Migrations\Migration\ManagerFactory;
use Throwable;
Expand Down Expand Up @@ -77,6 +78,9 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
])->addOption('date', [
'short' => 'd',
'help' => 'The date to rollback to',
])->addOption('count', [
'short' => 'k',
'help' => 'The number of migrations to rollback',
])->addOption('fake', [
'help' => "Mark any migrations selected as run, but don't actually execute them",
'boolean' => true,
Expand Down Expand Up @@ -130,6 +134,17 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
$force = (bool)$args->getOption('force');
$dryRun = (bool)$args->getOption('dry-run');

$count = $args->getOption('count') !== null ? (int)$args->getOption('count') : null;
if ($count !== null && $count < 1) {
throw new LogicException('Count must be > 0.');
}
if ($count && $date) {
throw new LogicException('Can only use one of `--count` or `--date` options at a time.');
}
if ($version && $date) {
throw new LogicException('Can only use one of `--version` or `--date` options at a time.');
}

$factory = new ManagerFactory([
'plugin' => $args->getOption('plugin'),
'source' => $args->getOption('source'),
Expand Down Expand Up @@ -162,7 +177,11 @@ protected function executeMigrations(Arguments $args, ConsoleIo $io): ?int
try {
// run the migrations
$start = microtime(true);
$manager->rollback($target, $force, $targetMustMatch, $fake);
if ($count) {
$manager->rollbackByCount($count, $force, $fake);
} else {
$manager->rollback($target, $force, $targetMustMatch, $fake);
}
$end = microtime(true);
} catch (Exception $e) {
$io->err('<error>' . $e->getMessage() . '</error>');
Expand Down
43 changes: 39 additions & 4 deletions src/Migration/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function printStatus(?string $format = null): array
$migrations = [];
$isJson = $format === 'json';
$defaultMigrations = $this->getMigrations();
if (count($defaultMigrations)) {
if ($defaultMigrations) {
$env = $this->getEnvironment();
$versions = $env->getVersionLog();

Expand Down Expand Up @@ -361,13 +361,14 @@ public function markVersionsAsMigrated(string $path, array $versions): array
}

/**
* Migrate an environment to the specified version.
* Migrate an environment to the specified version or by count of migrations.
*
* @param int|null $version version to migrate to
* @param bool $fake flag that if true, we just record running the migration, but not actually do the migration
* @param int|null $count Number of migrations to run, all migrations will be run if not set and no version is given.
* @return void
*/
public function migrate(?int $version = null, bool $fake = false): void
public function migrate(?int $version = null, bool $fake = false, ?int $count = null): void
{
$migrations = $this->getMigrations();
$env = $this->getEnvironment();
Expand Down Expand Up @@ -409,13 +410,15 @@ public function migrate(?int $version = null, bool $fake = false): void
}

ksort($migrations);
$done = 0;
foreach ($migrations as $migration) {
if ($migration->getVersion() > $version) {
if ($migration->getVersion() > $version || ($count && $done >= $count)) {
break;
}

if (!in_array($migration->getVersion(), $versions)) {
$this->executeMigration($migration, MigrationInterface::UP, $fake);
$done++;
}
}
}
Expand Down Expand Up @@ -535,6 +538,38 @@ protected function printStatusOutput(string $name, string $status, ?string $dura
);
}

/**
* Rollback an environment by a specific count of migrations.
*
* Note: If the count is greater than the number of migrations, it will rollback all migrations.
*
* @param int $count Count
* @param bool $force Force
* @param bool $fake Flag that if true, we just record running the migration, but not actually do the migration
* @return void
*/
public function rollbackByCount(int $count, bool $force = false, bool $fake = false): void
{
// note that the version log are also indexed by name with the proper ascending order according to the version order
$executedVersions = $this->getEnvironment()->getVersionLog();

$total = count($executedVersions);
$pos = 0;
while ($pos < $count && $pos < $total) {
array_pop($executedVersions);
$pos++;
}

if ($executedVersions) {
$last = end($executedVersions);
$target = $last['version'];
} else {
$target = 0;
}

$this->rollback($target, $force, false, $fake);
}

/**
* Rollback an environment to the specified version.
*
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Command/CompletionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function testMigrationsOptionsRollback()
$this->exec('completion options migrations.migrations rollback');
$this->assertCount(1, $this->_out->messages());
$output = $this->_out->messages()[0];
$expected = '--connection -c --date -d --dry-run -x --fake --force -f --help -h --no-lock --plugin -p';
$expected = '--connection -c --count -k --date -d --dry-run -x --fake --force -f --help -h --no-lock --plugin -p';
$expected .= ' --quiet -q --source -s --target -t --verbose -v';
$outputExplode = explode(' ', trim($output));
sort($outputExplode);
Expand Down
Loading
Loading