aboutsummaryrefslogtreecommitdiffstats
path: root/core/Command/Db/Migrations
diff options
context:
space:
mode:
Diffstat (limited to 'core/Command/Db/Migrations')
-rw-r--r--core/Command/Db/Migrations/ExecuteCommand.php35
-rw-r--r--core/Command/Db/Migrations/GenerateCommand.php77
-rw-r--r--core/Command/Db/Migrations/GenerateMetadataCommand.php79
-rw-r--r--core/Command/Db/Migrations/MigrateCommand.php30
-rw-r--r--core/Command/Db/Migrations/PreviewCommand.php111
-rw-r--r--core/Command/Db/Migrations/StatusCommand.php31
6 files changed, 235 insertions, 128 deletions
diff --git a/core/Command/Db/Migrations/ExecuteCommand.php b/core/Command/Db/Migrations/ExecuteCommand.php
index e87e133fa31..a89072c1ad1 100644
--- a/core/Command/Db/Migrations/ExecuteCommand.php
+++ b/core/Command/Db/Migrations/ExecuteCommand.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Core\Command\Db\Migrations;
@@ -35,13 +19,10 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ExecuteCommand extends Command implements CompletionAwareInterface {
- private Connection $connection;
- private IConfig $config;
-
- public function __construct(Connection $connection, IConfig $config) {
- $this->connection = $connection;
- $this->config = $config;
-
+ public function __construct(
+ private Connection $connection,
+ private IConfig $config,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php
index aa93adaebb4..a75280fa8b1 100644
--- a/core/Command/Db/Migrations/GenerateCommand.php
+++ b/core/Command/Db/Migrations/GenerateCommand.php
@@ -1,26 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Core\Command\Db\Migrations;
@@ -33,37 +16,21 @@ use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareI
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RuntimeException;
+use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
class GenerateCommand extends Command implements CompletionAwareInterface {
- protected static $_templateSimple =
- '<?php
+ protected static $_templateSimple
+ = '<?php
declare(strict_types=1);
/**
- * @copyright Copyright (c) {{year}} Your name <your@email.com>
- *
- * @author Your name <your@email.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: {{year}} Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace {{namespace}};
@@ -72,9 +39,10 @@ use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
+use Override;
/**
- * Auto-generated migration step: Please modify to your needs!
+ * FIXME Auto-generated migration step: Please modify to your needs!
*/
class {{classname}} extends SimpleMigrationStep {
@@ -83,6 +51,7 @@ class {{classname}} extends SimpleMigrationStep {
* @param Closure(): ISchemaWrapper $schemaClosure
* @param array $options
*/
+ #[Override]
public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
}
@@ -92,6 +61,7 @@ class {{classname}} extends SimpleMigrationStep {
* @param array $options
* @return null|ISchemaWrapper
*/
+ #[Override]
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
{{schemabody}}
}
@@ -99,20 +69,18 @@ class {{classname}} extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure(): ISchemaWrapper $schemaClosure
-g * @param array $options
+ * @param array $options
*/
+ #[Override]
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
}
}
';
- protected Connection $connection;
- protected IAppManager $appManager;
-
- public function __construct(Connection $connection, IAppManager $appManager) {
- $this->connection = $connection;
- $this->appManager = $appManager;
-
+ public function __construct(
+ protected Connection $connection,
+ protected IAppManager $appManager,
+ ) {
parent::__construct();
}
@@ -147,7 +115,7 @@ g * @param array $options
if ($fullVersion) {
[$major, $minor] = explode('.', $fullVersion);
- $shouldVersion = (string) ((int)$major * 1000 + (int)$minor);
+ $shouldVersion = (string)((int)$major * 1000 + (int)$minor);
if ($version !== $shouldVersion) {
$output->writeln('<comment>Unexpected migration version for current version: ' . $fullVersion . '</comment>');
$output->writeln('<comment> - Pattern: XYYY </comment>');
@@ -155,6 +123,7 @@ g * @param array $options
$output->writeln('<comment> - Actual: ' . $version . '</comment>');
if ($input->isInteractive()) {
+ /** @var QuestionHelper $helper */
$helper = $this->getHelper('question');
$question = new ConfirmationQuestion('Continue with your given version? (y/n) [n] ', false);
@@ -190,7 +159,7 @@ g * @param array $options
*/
public function completeArgumentValues($argumentName, CompletionContext $context) {
if ($argumentName === 'app') {
- $allApps = \OC_App::getAllApps();
+ $allApps = $this->appManager->getAllAppsInAppsFolders();
return array_diff($allApps, \OC_App::getEnabledApps(true, true));
}
@@ -235,7 +204,7 @@ g * @param array $options
$path = $dir . '/' . $className . '.php';
if (file_put_contents($path, $code) === false) {
- throw new RuntimeException('Failed to generate new migration step.');
+ throw new RuntimeException('Failed to generate new migration step. Could not write to ' . $path);
}
return $path;
diff --git a/core/Command/Db/Migrations/GenerateMetadataCommand.php b/core/Command/Db/Migrations/GenerateMetadataCommand.php
new file mode 100644
index 00000000000..581259c99df
--- /dev/null
+++ b/core/Command/Db/Migrations/GenerateMetadataCommand.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\Db\Migrations;
+
+use OC\Migration\MetadataManager;
+use OCP\App\IAppManager;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * @since 30.0.0
+ */
+class GenerateMetadataCommand extends Command {
+ public function __construct(
+ private readonly MetadataManager $metadataManager,
+ private readonly IAppManager $appManager,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this->setName('migrations:generate-metadata')
+ ->setHidden(true)
+ ->setDescription('Generate metadata from DB migrations - internal and should not be used');
+
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ $output->writeln(
+ json_encode(
+ [
+ 'migrations' => $this->extractMigrationMetadata()
+ ],
+ JSON_PRETTY_PRINT
+ )
+ );
+
+ return 0;
+ }
+
+ private function extractMigrationMetadata(): array {
+ return [
+ 'core' => $this->extractMigrationMetadataFromCore(),
+ 'apps' => $this->extractMigrationMetadataFromApps()
+ ];
+ }
+
+ private function extractMigrationMetadataFromCore(): array {
+ return $this->metadataManager->extractMigrationAttributes('core');
+ }
+
+ /**
+ * get all apps and extract attributes
+ *
+ * @return array
+ * @throws \Exception
+ */
+ private function extractMigrationMetadataFromApps(): array {
+ $allApps = $this->appManager->getAllAppsInAppsFolders();
+ $metadata = [];
+ foreach ($allApps as $appId) {
+ // We need to load app before being able to extract Migrations
+ $alreadyLoaded = $this->appManager->isAppLoaded($appId);
+ if (!$alreadyLoaded) {
+ $this->appManager->loadApp($appId);
+ }
+ $metadata[$appId] = $this->metadataManager->extractMigrationAttributes($appId);
+ }
+ return $metadata;
+ }
+}
diff --git a/core/Command/Db/Migrations/MigrateCommand.php b/core/Command/Db/Migrations/MigrateCommand.php
index f0f35716997..2e02f031479 100644
--- a/core/Command/Db/Migrations/MigrateCommand.php
+++ b/core/Command/Db/Migrations/MigrateCommand.php
@@ -1,24 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Core\Command\Db\Migrations;
@@ -33,10 +18,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MigrateCommand extends Command implements CompletionAwareInterface {
- private Connection $connection;
-
- public function __construct(Connection $connection) {
- $this->connection = $connection;
+ public function __construct(
+ private Connection $connection,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Db/Migrations/PreviewCommand.php b/core/Command/Db/Migrations/PreviewCommand.php
new file mode 100644
index 00000000000..f5b850fff76
--- /dev/null
+++ b/core/Command/Db/Migrations/PreviewCommand.php
@@ -0,0 +1,111 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\Db\Migrations;
+
+use OC\Migration\MetadataManager;
+use OC\Updater\ReleaseMetadata;
+use OCP\Migration\Attributes\MigrationAttribute;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Helper\TableCell;
+use Symfony\Component\Console\Helper\TableCellStyle;
+use Symfony\Component\Console\Helper\TableSeparator;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * @since 30.0.0
+ */
+class PreviewCommand extends Command {
+ private bool $initiated = false;
+ public function __construct(
+ private readonly MetadataManager $metadataManager,
+ private readonly ReleaseMetadata $releaseMetadata,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this
+ ->setName('migrations:preview')
+ ->setDescription('Get preview of available DB migrations in case of initiating an upgrade')
+ ->addArgument('version', InputArgument::REQUIRED, 'The destination version number');
+
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ $version = $input->getArgument('version');
+ if (filter_var($version, FILTER_VALIDATE_URL)) {
+ $metadata = $this->releaseMetadata->downloadMetadata($version);
+ } elseif (str_starts_with($version, '/')) {
+ $metadata = json_decode(file_get_contents($version), true, flags: JSON_THROW_ON_ERROR);
+ } else {
+ $metadata = $this->releaseMetadata->getMetadata($version);
+ }
+
+ $parsed = $this->metadataManager->getMigrationsAttributesFromReleaseMetadata($metadata['migrations'] ?? [], true);
+
+ $table = new Table($output);
+ $this->displayMigrations($table, 'core', $parsed['core'] ?? []);
+ foreach ($parsed['apps'] as $appId => $migrations) {
+ if (!empty($migrations)) {
+ $this->displayMigrations($table, $appId, $migrations);
+ }
+ }
+ $table->render();
+
+ $unsupportedApps = $this->metadataManager->getUnsupportedApps($metadata['migrations']);
+ if (!empty($unsupportedApps)) {
+ $output->writeln('');
+ $output->writeln('Those apps are not supporting metadata yet and might initiate migrations on upgrade: <info>' . implode(', ', $unsupportedApps) . '</info>');
+ }
+
+ return 0;
+ }
+
+ private function displayMigrations(Table $table, string $appId, array $data): void {
+ if (empty($data)) {
+ return;
+ }
+
+ if ($this->initiated) {
+ $table->addRow(new TableSeparator());
+ }
+ $this->initiated = true;
+
+ $table->addRow(
+ [
+ new TableCell(
+ $appId,
+ [
+ 'colspan' => 2,
+ 'style' => new TableCellStyle(['cellFormat' => '<info>%s</info>'])
+ ]
+ )
+ ]
+ )->addRow(new TableSeparator());
+
+ /** @var MigrationAttribute[] $attributes */
+ foreach ($data as $migration => $attributes) {
+ $attributesStr = [];
+ if (empty($attributes)) {
+ $attributesStr[] = '<comment>(metadata not set)</comment>';
+ }
+ foreach ($attributes as $attribute) {
+ $definition = '<info>' . $attribute->definition() . '</info>';
+ $definition .= empty($attribute->getDescription()) ? '' : "\n " . $attribute->getDescription();
+ $definition .= empty($attribute->getNotes()) ? '' : "\n <comment>" . implode("</comment>\n <comment>", $attribute->getNotes()) . '</comment>';
+ $attributesStr[] = $definition;
+ }
+ $table->addRow([$migration, implode("\n", $attributesStr)]);
+ }
+ }
+}
diff --git a/core/Command/Db/Migrations/StatusCommand.php b/core/Command/Db/Migrations/StatusCommand.php
index 725ee075215..97ecc76a924 100644
--- a/core/Command/Db/Migrations/StatusCommand.php
+++ b/core/Command/Db/Migrations/StatusCommand.php
@@ -1,25 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2017, ownCloud GmbH
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Robin Appelman <robin@icewind.nl>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2017 ownCloud GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Core\Command\Db\Migrations;
@@ -34,10 +18,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class StatusCommand extends Command implements CompletionAwareInterface {
- private Connection $connection;
-
- public function __construct(Connection $connection) {
- $this->connection = $connection;
+ public function __construct(
+ private Connection $connection,
+ ) {
parent::__construct();
}