diff --git a/core/Command/Maintenance/Repair.php b/core/Command/Maintenance/Repair.php
index a1a75099214e..f3552c1b672a 100644
--- a/core/Command/Maintenance/Repair.php
+++ b/core/Command/Maintenance/Repair.php
@@ -26,7 +26,9 @@
namespace OC\Core\Command\Maintenance;
use Exception;
+use OCP\App\IAppManager;
use OCP\IConfig;
+use OCP\Migration\IRuntimeRepairStep;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
@@ -46,15 +48,18 @@ class Repair extends Command {
private $progress;
/** @var OutputInterface */
private $output;
+ /** @var IAppManager */
+ private $appManager;
/**
* @param \OC\Repair $repair
* @param IConfig $config
*/
- public function __construct(\OC\Repair $repair, IConfig $config, EventDispatcherInterface $dispatcher) {
+ public function __construct(\OC\Repair $repair, IConfig $config, EventDispatcherInterface $dispatcher, IAppManager $appManager) {
$this->repair = $repair;
$this->config = $config;
$this->dispatcher = $dispatcher;
+ $this->appManager = $appManager;
parent::__construct();
}
@@ -66,39 +71,27 @@ protected function configure() {
'include-expensive',
null,
InputOption::VALUE_NONE,
+ 'Use this option when you want to include resource and load expensive tasks.')
+ ->addOption(
+ 'runtime',
+ null,
+ InputOption::VALUE_NONE,
'Use this option when you want to include resource and load expensive tasks.');
}
protected function execute(InputInterface $input, OutputInterface $output) {
- $includeExpensive = $input->getOption('include-expensive');
- if ($includeExpensive) {
- foreach ($this->repair->getExpensiveRepairSteps() as $step) {
- $this->repair->addStep($step);
- }
- }
+ $this->output = $output;
- $apps = \OC::$server->getAppManager()->getInstalledApps();
- foreach ($apps as $app) {
- if (!\OC_App::isEnabled($app)) {
- continue;
- }
- $info = \OC_App::getAppInfo($app);
- if (!\is_array($info)) {
- continue;
- }
- \OC_App::loadApp($app);
- $steps = $info['repair-steps']['post-migration'];
- foreach ($steps as $step) {
- try {
- $this->repair->addStep($step);
- } catch (Exception $ex) {
- $output->writeln("Failed to load repair step for $app: {$ex->getMessage()}");
- }
- }
- }
+ $includeExpensive = $input->getOption('include-expensive');
+ $runtime = $input->getOption('runtime');
+ $this->buildRepairList($includeExpensive, $runtime, $this->repair);
+ // If not runtime mode, we need maintenance mode
$maintenanceMode = $this->config->getSystemValue('maintenance', false);
- $this->config->setSystemValue('maintenance', true);
+ if (!$runtime) {
+ $this->output->writeln('Enabling maintenance mode...');
+ $this->config->setSystemValue('maintenance', true);
+ }
$this->progress = new ProgressBar($output);
$this->output = $output;
@@ -112,7 +105,50 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$this->repair->run();
- $this->config->setSystemValue('maintenance', $maintenanceMode);
+ if (!$runtime) {
+ $this->output->writeln('Resetting maintenance mode...');
+ $this->config->setSystemValue('maintenance', $maintenanceMode);
+ }
+ }
+
+ public function buildRepairList($includeExpensive, $runtimeSteps, \OC\Repair $repair) {
+ $repair->clearSteps();
+ $steps = [];
+ $steps = array_merge($steps, \OC\Repair::getRepairSteps());
+ if ($includeExpensive) {
+ $steps = array_merge($steps, $repair->getExpensiveRepairSteps());
+ }
+ $apps = $this->appManager->getInstalledApps();
+ foreach ($apps as $app) {
+ if (!$this->appManager->isEnabledForUser($app)) {
+ continue;
+ }
+ $info = $this->appManager->getAppInfo($app);
+ if (!\is_array($info)) {
+ continue;
+ }
+ \OC_App::loadApp($app);
+ $appSteps = $info['repair-steps']['post-migration'];
+ foreach ($appSteps as $step) {
+ $steps[] = $step;
+ }
+ }
+ // Add to repair lib
+ foreach ($steps as $step) {
+ if (\is_string($step)) {
+ $step = \OC::$server->query($step);
+ }
+ // Skip step if runtime only and this one isnt
+ if ($runtimeSteps && !$step instanceof IRuntimeRepairStep) {
+ continue;
+ }
+ try {
+ $repair->addStep($step);
+ } catch (\Exception $e) {
+ $stepName = get_class($step);
+ $this->output->writeln("Problem loading repair step: $stepName");
+ }
+ }
}
public function handleRepairFeedBack($event) {
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index 5fe3b4aa2f8f..0032d8b9fd51 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -92,6 +92,13 @@ public function run() {
}
}
+ /**
+ * Clears the list of steps to run
+ */
+ public function clearSteps() {
+ $this->repairSteps = [];
+ }
+
/**
* Add repair step
*
diff --git a/lib/private/Repair/MoveAvatarOutsideHome.php b/lib/private/Repair/MoveAvatarOutsideHome.php
index 8725f4a22510..963598f458e7 100644
--- a/lib/private/Repair/MoveAvatarOutsideHome.php
+++ b/lib/private/Repair/MoveAvatarOutsideHome.php
@@ -27,19 +27,19 @@
use OCP\ILogger;
use OCP\IUserManager;
use OCP\Migration\IOutput;
-use OCP\Migration\IRepairStep;
use OCP\IUser;
use OC\Avatar;
use OCP\IConfig;
use OCP\IAvatarManager;
use OCP\Files\NotFoundException;
+use OCP\Migration\IRuntimeRepairStep;
/**
* Move avatars outside of their homes to the new location
*
* @package OC\Repair
*/
-class MoveAvatarOutsideHome implements IRepairStep {
+class MoveAvatarOutsideHome implements IRuntimeRepairStep {
/** @var \OCP\IConfig */
protected $config;
diff --git a/lib/public/Migration/IRuntimeRepairStep.php b/lib/public/Migration/IRuntimeRepairStep.php
new file mode 100644
index 000000000000..df0a66e62b28
--- /dev/null
+++ b/lib/public/Migration/IRuntimeRepairStep.php
@@ -0,0 +1,25 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @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
+ *
+ */
+namespace OCP\Migration;
+
+interface IRuntimeRepairStep extends IRepairStep {
+
+}
\ No newline at end of file
diff --git a/tests/lib/Command/Maintenance/RepairTest.php b/tests/lib/Command/Maintenance/RepairTest.php
new file mode 100644
index 000000000000..1d7af7ce31a7
--- /dev/null
+++ b/tests/lib/Command/Maintenance/RepairTest.php
@@ -0,0 +1,80 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @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
+ *
+ */
+
+namespace Test\Command\Maintenance;
+
+use OC\Core\Command\Maintenance\Repair;
+use OCP\App\IAppManager;
+use OCP\IConfig;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Test\TestCase;
+
+/**
+ * Class RepairTest
+ *
+ * @package Test\Command\Maintenance
+ * @group DB
+ */
+class RepairTest extends TestCase {
+
+ /** @var \OC\Repair */
+ protected $repair;
+ /** @var Repair */
+ protected $command;
+ /** @var IConfig */
+ protected $config;
+ /** @var EventDispatcherInterface */
+ protected $dispatcher;
+ /** @var IAppManager */
+ protected $appManager;
+
+ public function setUp() {
+ parent::setUp();
+ $this->repair = $this->createMock(\OC\Repair::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->dispatcher = $this->createMock(EventDispatcherInterface::class);
+ $this->appManager = $this->createMock(IAppManager::class);
+ $this->command = new Repair($this->repair, $this->config, $this->dispatcher, $this->appManager);
+ }
+
+ /**
+ * @dataProvider buildStepsData
+ * @param $expensiveSteps
+ * @param $runtimeSteps
+ * @param $expensive
+ * @param $runtimeMode
+ * @param $expected
+ */
+ public function testBuildSteps($expensiveSteps, $runtimeSteps, $expensive, $runtimeMode, $expectedCount) {
+ $this->appManager->method('getInstalledApps')->willReturn([]);
+ $this->repair->expects($this->exactly($expectedCount))->method('addStep');
+ $this->command->buildRepairList($expensive, $runtimeMode, $this->repair);
+ //$this->assertSame($expected, $this->command->buildRepairList($expected, $runtimeMode, $this->repair));
+ //$this->assertAttributeEquals($expected, '$repairSteps', )
+ }
+
+ public function buildStepsData() {
+ return [
+ [[], [], false, false, []]
+ ];
+ }
+
+}