diff --git a/lib/private/Repair/AssetCache.php b/lib/private/Repair/AssetCache.php
index 72fe99bbe1af6345cfcc0f65c258d62a5ba29a8f..e4787bab95fbed45eccc2c2730c8d6cce9751036 100644
--- a/lib/private/Repair/AssetCache.php
+++ b/lib/private/Repair/AssetCache.php
@@ -23,23 +23,23 @@
 
 namespace OC\Repair;
 
-use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class AssetCache extends BasicEmitter implements \OC\RepairStep {
+class AssetCache implements IRepairStep {
 
 	public function getName() {
 		return 'Clear asset cache after upgrade';
 	}
 
-	public function run() {
+	public function run(IOutput $output) {
 		if (!\OC_Template::isAssetPipelineEnabled()) {
-			$this->emit('\OC\Repair', 'info', array('Asset pipeline disabled -> nothing to do'));
+			$output->info('Asset pipeline disabled -> nothing to do');
 			return;
 		}
 		$assetDir = \OC::$server->getConfig()->getSystemValue('assetdirectory', \OC::$SERVERROOT) . '/assets';
 		\OC_Helper::rmdirr($assetDir, false);
-		$this->emit('\OC\Repair', 'info', array('Asset cache cleared.'));
+		$output->info('Asset cache cleared.');
 	}
 }
 
diff --git a/lib/private/Repair/CleanTags.php b/lib/private/Repair/CleanTags.php
index 537c4da78aaa2f5b276689671a0a43eb0676dc5b..2607151cd9c979e4b1e1a19da8a92df0c806b4ee 100644
--- a/lib/private/Repair/CleanTags.php
+++ b/lib/private/Repair/CleanTags.php
@@ -22,17 +22,17 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OCP\DB\QueryBuilder\IQueryBuilder;
 use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Class RepairConfig
  *
  * @package OC\Repair
  */
-class CleanTags extends BasicEmitter implements RepairStep {
+class CleanTags implements IRepairStep {
 
 	/** @var IDBConnection */
 	protected $connection;
@@ -54,17 +54,18 @@ class CleanTags extends BasicEmitter implements RepairStep {
 	/**
 	 * Updates the configuration after running an update
 	 */
-	public function run() {
-		$this->deleteOrphanFileEntries();
-		$this->deleteOrphanTagEntries();
-		$this->deleteOrphanCategoryEntries();
+	public function run(IOutput $output) {
+		$this->deleteOrphanFileEntries($output);
+		$this->deleteOrphanTagEntries($output);
+		$this->deleteOrphanCategoryEntries($output);
 	}
 
 	/**
 	 * Delete tag entries for deleted files
 	 */
-	protected function deleteOrphanFileEntries() {
+	protected function deleteOrphanFileEntries(IOutput $output) {
 		$this->deleteOrphanEntries(
+			$output,
 			'%d tags for delete files have been removed.',
 			'vcategory_to_object', 'objid',
 			'filecache', 'fileid', 'path_hash'
@@ -74,8 +75,9 @@ class CleanTags extends BasicEmitter implements RepairStep {
 	/**
 	 * Delete tag entries for deleted tags
 	 */
-	protected function deleteOrphanTagEntries() {
+	protected function deleteOrphanTagEntries(IOutput $output) {
 		$this->deleteOrphanEntries(
+			$output,
 			'%d tag entries for deleted tags have been removed.',
 			'vcategory_to_object', 'categoryid',
 			'vcategory', 'id', 'uid'
@@ -85,8 +87,9 @@ class CleanTags extends BasicEmitter implements RepairStep {
 	/**
 	 * Delete tags that have no entries
 	 */
-	protected function deleteOrphanCategoryEntries() {
+	protected function deleteOrphanCategoryEntries(IOutput $output) {
 		$this->deleteOrphanEntries(
+			$output,
 			'%d tags with no entries have been removed.',
 			'vcategory', 'id',
 			'vcategory_to_object', 'categoryid', 'type'
@@ -108,7 +111,7 @@ class CleanTags extends BasicEmitter implements RepairStep {
 	 * @param string $sourceNullColumn	If this column is null in the source table,
 	 * 								the entry is deleted in the $deleteTable
 	 */
-	protected function deleteOrphanEntries($repairInfo, $deleteTable, $deleteId, $sourceTable, $sourceId, $sourceNullColumn) {
+	protected function deleteOrphanEntries(IOutput $output, $repairInfo, $deleteTable, $deleteId, $sourceTable, $sourceId, $sourceNullColumn) {
 		$qb = $this->connection->getQueryBuilder();
 
 		$qb->select('d.' . $deleteId)
@@ -141,7 +144,7 @@ class CleanTags extends BasicEmitter implements RepairStep {
 		}
 
 		if ($repairInfo) {
-			$this->emit('\OC\Repair', 'info', array(sprintf($repairInfo, sizeof($orphanItems))));
+			$output->info(sprintf($repairInfo, sizeof($orphanItems)));
 		}
 	}
 }
diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php
index 48035f8d33143ade2e6c3e0d3e746befe5aa940e..1376785e17d371638128c08c32c0b0e0714c07bd 100644
--- a/lib/private/Repair/Collation.php
+++ b/lib/private/Repair/Collation.php
@@ -23,9 +23,10 @@
 namespace OC\Repair;
 
 use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class Collation extends BasicEmitter implements \OC\RepairStep {
+class Collation implements IRepairStep {
 	/**
 	 * @var \OCP\IConfig
 	 */
@@ -52,15 +53,15 @@ class Collation extends BasicEmitter implements \OC\RepairStep {
 	/**
 	 * Fix mime types
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
-			$this->emit('\OC\Repair', 'info', array('Not a mysql database -> nothing to no'));
+			$output->info('Not a mysql database -> nothing to no');
 			return;
 		}
 
 		$tables = $this->getAllNonUTF8BinTables($this->connection);
 		foreach ($tables as $table) {
-			$this->emit('\OC\Repair', 'info', array("Change collation for $table ..."));
+			$output->info("Change collation for $table ...");
 			$query = $this->connection->prepare('ALTER TABLE `' . $table . '` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;');
 			$query->execute();
 		}
diff --git a/lib/private/Repair/DropOldJobs.php b/lib/private/Repair/DropOldJobs.php
index 594af83e51144a8ce83d4c42d9e182ad24802261..489b89d0869687ca220cb7f565477311e8448baf 100644
--- a/lib/private/Repair/DropOldJobs.php
+++ b/lib/private/Repair/DropOldJobs.php
@@ -22,11 +22,11 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class DropOldJobs extends BasicEmitter implements RepairStep {
+class DropOldJobs implements IRepairStep {
 
 	/** @var IJobList */
 	protected $jobList;
@@ -53,7 +53,7 @@ class DropOldJobs extends BasicEmitter implements RepairStep {
 	 *
 	 * @throws \Exception in case of failure
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		$oldJobs = $this->oldJobs();
 		foreach($oldJobs as $job) {
 			if($this->jobList->has($job['class'], $job['arguments'])) {
diff --git a/lib/private/Repair/DropOldTables.php b/lib/private/Repair/DropOldTables.php
index 67eafaa930e003ea4184148381a843b010b9311a..15d5b9a3577d3e1fcc226ced91826268f1b8da73 100644
--- a/lib/private/Repair/DropOldTables.php
+++ b/lib/private/Repair/DropOldTables.php
@@ -23,11 +23,11 @@
 namespace OC\Repair;
 
 
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class DropOldTables extends BasicEmitter implements RepairStep {
+class DropOldTables implements IRepairStep {
 
 	/** @var IDBConnection */
 	protected $connection;
@@ -54,12 +54,10 @@ class DropOldTables extends BasicEmitter implements RepairStep {
 	 *
 	 * @throws \Exception in case of failure
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		foreach ($this->oldDatabaseTables() as $tableName) {
 			if ($this->connection->tableExists($tableName)){
-				$this->emit('\OC\Repair', 'info', [
-					sprintf('Table %s has been deleted', $tableName)
-				]);
+				$output->info(sprintf('Table %s has been deleted', $tableName));
 				$this->connection->dropTable($tableName);
 			}
 		}
diff --git a/lib/private/Repair/FillETags.php b/lib/private/Repair/FillETags.php
index dc2ffdcbc365f5112e9f191bb259a5ac90b16219..7ed55f20ac185a935204caf8ad39276299704b99 100644
--- a/lib/private/Repair/FillETags.php
+++ b/lib/private/Repair/FillETags.php
@@ -23,9 +23,10 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class FillETags extends BasicEmitter implements \OC\RepairStep {
+class FillETags implements IRepairStep {
 
 	/** @var \OCP\IDBConnection */
 	protected $connection;
@@ -41,7 +42,7 @@ class FillETags extends BasicEmitter implements \OC\RepairStep {
 		return 'Generate ETags for file where no ETag is present.';
 	}
 
-	public function run() {
+	public function run(IOutput $output) {
 		$qb = $this->connection->getQueryBuilder();
 		$qb->update('filecache')
 			->set('etag', $qb->expr()->literal('xxx'))
@@ -49,7 +50,7 @@ class FillETags extends BasicEmitter implements \OC\RepairStep {
 			->orWhere($qb->expr()->isNull('etag'));
 
 		$result = $qb->execute();
-		$this->emit('\OC\Repair', 'info', array("ETags have been fixed for $result files/folders."));
+		$output->info("ETags have been fixed for $result files/folders.");
 	}
 }
 
diff --git a/lib/private/Repair/InnoDB.php b/lib/private/Repair/InnoDB.php
index 4e157e66045e5a557c582ffa963e806846e91940..ed119dcc03287d2f3fcc31a46c12e9b0cbad3037 100644
--- a/lib/private/Repair/InnoDB.php
+++ b/lib/private/Repair/InnoDB.php
@@ -25,9 +25,10 @@
 namespace OC\Repair;
 
 use Doctrine\DBAL\Platforms\MySqlPlatform;
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class InnoDB extends BasicEmitter implements \OC\RepairStep {
+class InnoDB implements IRepairStep {
 
 	public function getName() {
 		return 'Repair MySQL database engine';
@@ -36,10 +37,10 @@ class InnoDB extends BasicEmitter implements \OC\RepairStep {
 	/**
 	 * Fix mime types
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		$connection = \OC::$server->getDatabaseConnection();
 		if (!$connection->getDatabasePlatform() instanceof MySqlPlatform) {
-			$this->emit('\OC\Repair', 'info', array('Not a mysql database -> nothing to do'));
+			$output->info('Not a mysql database -> nothing to do');
 			return;
 		}
 
@@ -47,7 +48,7 @@ class InnoDB extends BasicEmitter implements \OC\RepairStep {
 		if (is_array($tables)) {
 			foreach ($tables as $table) {
 				$connection->exec("ALTER TABLE $table ENGINE=InnoDB;");
-				$this->emit('\OC\Repair', 'info', array("Fixed $table"));
+				$output->info("Fixed $table");
 			}
 		}
 	}
diff --git a/lib/private/Repair/OldGroupMembershipShares.php b/lib/private/Repair/OldGroupMembershipShares.php
index 627645b116d61dc51c07afa91b7f7e0185f489c6..e982dd81f3b720450f664d709fdd98f9942595ef 100644
--- a/lib/private/Repair/OldGroupMembershipShares.php
+++ b/lib/private/Repair/OldGroupMembershipShares.php
@@ -21,14 +21,13 @@
 
 namespace OC\Repair;
 
-
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OCP\IDBConnection;
 use OCP\IGroupManager;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 use OCP\Share;
 
-class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
+class OldGroupMembershipShares implements IRepairStep {
 
 	/** @var \OCP\IDBConnection */
 	protected $connection;
@@ -65,7 +64,7 @@ class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
 	 *
 	 * @throws \Exception in case of failure
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		$deletedEntries = 0;
 
 		$query = $this->connection->getQueryBuilder();
@@ -92,7 +91,7 @@ class OldGroupMembershipShares extends BasicEmitter implements RepairStep {
 		$result->closeCursor();
 
 		if ($deletedEntries) {
-			$this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore'));
+			$output->info('Removed ' . $deletedEntries . ' shares where user is not a member of the group anymore');
 		}
 	}
 
diff --git a/lib/private/Repair/Preview.php b/lib/private/Repair/Preview.php
index 481e98b42d12eafbd2c6f12a9be49cfdb0f5a7ed..7e26e45cb80c1ba368279b47113f7d83a2383c75 100644
--- a/lib/private/Repair/Preview.php
+++ b/lib/private/Repair/Preview.php
@@ -21,15 +21,16 @@
 namespace OC\Repair;
 
 use OC\Files\View;
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class Preview extends BasicEmitter implements \OC\RepairStep {
+class Preview implements IRepairStep {
 
 	public function getName() {
 		return 'Cleaning-up broken previews';
 	}
 
-	public function run() {
+	public function run(IOutput $out) {
 		$view = new View('/');
 		$children = $view->getDirectoryContent('/');
 
@@ -42,4 +43,4 @@ class Preview extends BasicEmitter implements \OC\RepairStep {
 			}
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/lib/private/Repair/RemoveGetETagEntries.php b/lib/private/Repair/RemoveGetETagEntries.php
index e118da7973a91cad11feef6fd91ea5bf1582cabd..67bfb53bf14048d0713f5b7f18ba0656d97a9552 100644
--- a/lib/private/Repair/RemoveGetETagEntries.php
+++ b/lib/private/Repair/RemoveGetETagEntries.php
@@ -21,10 +21,11 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
 use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class RemoveGetETagEntries extends BasicEmitter {
+class RemoveGetETagEntries implements IRepairStep {
 
 	/**
 	 * @var IDBConnection
@@ -45,15 +46,11 @@ class RemoveGetETagEntries extends BasicEmitter {
 	/**
 	 * Removes all entries with the key "{DAV:}getetag" from the table properties
 	 */
-	public function run() {
+	public function run(IOutput $out) {
 		$sql = 'DELETE FROM `*PREFIX*properties`'
 			. ' WHERE `propertyname` = ?';
 		$deletedRows = $this->connection->executeUpdate($sql, ['{DAV:}getetag']);
 
-		$this->emit(
-			'\OC\Repair',
-			'info',
-			['Removed ' . $deletedRows . ' unneeded "{DAV:}getetag" entries from properties table.']
-		);
+		$out->info('Removed ' . $deletedRows . ' unneeded "{DAV:}getetag" entries from properties table.');
 	}
 }
diff --git a/lib/private/Repair/RepairInvalidShares.php b/lib/private/Repair/RepairInvalidShares.php
index beef5e3779898f052025fc72d906cb41f78dd625..e30b4ab0d31bc8f06222398c0ace147ea48da1f4 100644
--- a/lib/private/Repair/RepairInvalidShares.php
+++ b/lib/private/Repair/RepairInvalidShares.php
@@ -23,23 +23,20 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Repairs shares with invalid data
  */
-class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
+class RepairInvalidShares implements IRepairStep {
 
 	const CHUNK_SIZE = 200;
 
-	/**
-	 * @var \OCP\IConfig
-	 */
+	/** @var \OCP\IConfig */
 	protected $config;
 
-	/**
-	 * @var \OCP\IDBConnection
-	 */
+	/** @var \OCP\IDBConnection */
 	protected $connection;
 
 	/**
@@ -59,7 +56,7 @@ class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
 	 * Past bugs would make it possible to set an expiration date on user shares even
 	 * though it is not supported. This functions removes the expiration date from such entries.
 	 */
-	private function removeExpirationDateFromNonLinkShares() {
+	private function removeExpirationDateFromNonLinkShares(IOutput $out) {
 		$builder = $this->connection->getQueryBuilder();
 		$builder
 			->update('share')
@@ -69,14 +66,14 @@ class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
 
 		$updatedEntries = $builder->execute();
 		if ($updatedEntries > 0) {
-			$this->emit('\OC\Repair', 'info', array('Removed invalid expiration date from ' . $updatedEntries . ' shares'));
+			$out->info('Removed invalid expiration date from ' . $updatedEntries . ' shares');
 		}
 	}
 
 	/**
 	 * Remove shares where the parent share does not exist anymore
 	 */
-	private function removeSharesNonExistingParent() {
+	private function removeSharesNonExistingParent(IOutput $out) {
 		$deletedEntries = 0;
 
 		$query = $this->connection->getQueryBuilder();
@@ -105,17 +102,17 @@ class RepairInvalidShares extends BasicEmitter implements \OC\RepairStep {
 		}
 
 		if ($deletedEntries) {
-			$this->emit('\OC\Repair', 'info', array('Removed ' . $deletedEntries . ' shares where the parent did not exist'));
+			$out->info('Removed ' . $deletedEntries . ' shares where the parent did not exist');
 		}
 	}
 
-	public function run() {
+	public function run(IOutput $out) {
 		$ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
 		if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.7', '<')) {
 			// this situation was only possible before 8.2
-			$this->removeExpirationDateFromNonLinkShares();
+			$this->removeExpirationDateFromNonLinkShares($out);
 		}
 
-		$this->removeSharesNonExistingParent();
+		$this->removeSharesNonExistingParent($out);
 	}
 }
diff --git a/lib/private/Repair/RepairLegacyStorages.php b/lib/private/Repair/RepairLegacyStorages.php
index ee189110a87487db4bcae51c4e14c6d71168c096..9582629b1a325637c925bb7e618cfc3fa109efd4 100644
--- a/lib/private/Repair/RepairLegacyStorages.php
+++ b/lib/private/Repair/RepairLegacyStorages.php
@@ -24,10 +24,11 @@
 namespace OC\Repair;
 
 use OC\Files\Cache\Storage;
-use OC\Hooks\BasicEmitter;
 use OC\RepairException;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class RepairLegacyStorages extends BasicEmitter {
+class RepairLegacyStorages implements IRepairStep{
 	/**
 	 * @var \OCP\IConfig
 	 */
@@ -149,7 +150,7 @@ class RepairLegacyStorages extends BasicEmitter {
 	 * Converts legacy home storage ids in the format
 	 * "local::/data/dir/path/userid/" to the new format "home::userid"
 	 */
-	public function run() {
+	public function run(IOutput $out) {
 		// only run once
 		if ($this->config->getAppValue('core', 'repairlegacystoragesdone') === 'yes') {
 			return;
@@ -186,11 +187,7 @@ class RepairLegacyStorages extends BasicEmitter {
 			}
 			catch (RepairException $e) {
 				$hasWarnings = true;
-				$this->emit(
-					'\OC\Repair',
-					'warning',
-					array('Could not repair legacy storage ' . $currentId . ' automatically.')
-				);
+				$out->warning('Could not repair legacy storage ' . $currentId . ' automatically.');
 			}
 		}
 
@@ -233,11 +230,7 @@ class RepairLegacyStorages extends BasicEmitter {
 						}
 						catch (RepairException $e) {
 							$hasWarnings = true;
-							$this->emit(
-								'\OC\Repair',
-								'warning',
-								array('Could not repair legacy storage ' . $storageId . ' automatically.')
-							);
+							$out->warning('Could not repair legacy storage ' . $storageId . ' automatically.');
 						}
 					}
 				}
@@ -245,16 +238,12 @@ class RepairLegacyStorages extends BasicEmitter {
 			} while (count($results) >= $limit);
 		}
 
-		$this->emit('\OC\Repair', 'info', array('Updated ' . $count . ' legacy home storage ids'));
+		$out->info('Updated ' . $count . ' legacy home storage ids');
 
 		$this->connection->commit();
 
 		if ($hasWarnings) {
-			$this->emit(
-				'\OC\Repair',
-				'warning',
-				array('Some legacy storages could not be repaired. Please manually fix them then re-run ./occ maintenance:repair')
-			);
+			$out->warning('Some legacy storages could not be repaired. Please manually fix them then re-run ./occ maintenance:repair');
 		} else {
 			// if all were done, no need to redo the repair during next upgrade
 			$this->config->setAppValue('core', 'repairlegacystoragesdone', 'yes');
diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php
index c5180302443ddcfd0d560a94764b4859f14809f1..0d56245312aaaad1fee28da35676a828b5666952 100644
--- a/lib/private/Repair/RepairMimeTypes.php
+++ b/lib/private/Repair/RepairMimeTypes.php
@@ -28,9 +28,10 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
+class RepairMimeTypes implements IRepairStep {
 	/**
 	 * @var \OCP\IConfig
 	 */
@@ -308,7 +309,7 @@ class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
 	/**
 	 * Fix mime types
 	 */
-	public function run() {
+	public function run(IOutput $out) {
 
 		$ocVersionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
 
@@ -318,60 +319,60 @@ class RepairMimeTypes extends BasicEmitter implements \OC\RepairStep {
 		// only update mime types if necessary as it can be expensive
 		if (version_compare($ocVersionFromBeforeUpdate, '8.2.0', '<')) {
 			if ($this->fixOfficeMimeTypes()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed office mime types'));
+				$out->info('Fixed office mime types');
 			}
 
 			if ($this->fixApkMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed APK mime type'));
+				$out->info('Fixed APK mime type');
 			}
 
 			if ($this->fixFontsMimeTypes()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed fonts mime types'));
+				$out->info('Fixed fonts mime types');
 			}
 
 			if ($this->fixPostscriptMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed Postscript mime types'));
+				$out->info('Fixed Postscript mime types');
 			}
 
 			if ($this->introduceRawMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed Raw mime types'));
+				$out->info('Fixed Raw mime types');
 			}
 
 			if ($this->introduce3dImagesMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed 3D images mime types'));
+				$out->info('Fixed 3D images mime types');
 			}
 
 			if ($this->introduceConfMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed Conf/cnf mime types'));
+				$out->info('Fixed Conf/cnf mime types');
 			}
 
 			if ($this->introduceYamlMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed Yaml/Yml mime types'));
+				$out->info('Fixed Yaml/Yml mime types');
 			}
 		}
 
 		// Mimetype updates from #19272
 		if (version_compare($ocVersionFromBeforeUpdate, '8.2.0.8', '<')) {
 			if ($this->introduceJavaMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed java/class mime types'));
+				$out->info('Fixed java/class mime types');
 			}
 
 			if ($this->introduceHppMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed hpp mime type'));
+				$out->info('Fixed hpp mime type');
 			}
 
 			if ($this->introduceRssMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed rss mime type'));
+				$out->info('Fixed rss mime type');
 			}
 
 			if ($this->introduceRtfMimeType()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed rtf mime type'));
+				$out->info('Fixed rtf mime type');
 			}
 		}
 
 		if (version_compare($ocVersionFromBeforeUpdate, '9.0.0.10', '<')) {
 			if ($this->introduceRichDocumentsMimeTypes()) {
-				$this->emit('\OC\Repair', 'info', array('Fixed richdocuments additional office mime types'));
+				$out->info('Fixed richdocuments additional office mime types');
 			}
 		}
 	}
diff --git a/lib/private/Repair/SearchLuceneTables.php b/lib/private/Repair/SearchLuceneTables.php
index 9f3601eeb032f66629aa070759bb9bba7d24e446..56bae6ff655c4cb84b1b5b06c957020f07876b11 100644
--- a/lib/private/Repair/SearchLuceneTables.php
+++ b/lib/private/Repair/SearchLuceneTables.php
@@ -22,9 +22,10 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
-class SearchLuceneTables extends BasicEmitter implements \OC\RepairStep {
+class SearchLuceneTables implements IRepairStep {
 
 	public function getName() {
 		return 'Repair duplicate entries in oc_lucene_status';
@@ -51,10 +52,10 @@ class SearchLuceneTables extends BasicEmitter implements \OC\RepairStep {
 	 *
 	 * search_lucene will then reindex the fileids without a status when the next indexing job is executed
 	 */
-	public function run() {
+	public function run(IOutput $out) {
 		$connection = \OC::$server->getDatabaseConnection();
 		if ($connection->tableExists('lucene_status')) {
-			$this->emit('\OC\Repair', 'info', array('removing duplicate entries from lucene_status'));
+			$out->info('removing duplicate entries from lucene_status');
 
 			$query = $connection->prepare('
 				DELETE FROM `*PREFIX*lucene_status`
@@ -69,7 +70,7 @@ class SearchLuceneTables extends BasicEmitter implements \OC\RepairStep {
 				)');
 			$query->execute();
 		} else {
-			$this->emit('\OC\Repair', 'info', array('lucene_status table does not exist -> nothing to do'));
+			$out->info('lucene_status table does not exist -> nothing to do');
 		}
 	}
 
diff --git a/lib/private/Repair/SharePropagation.php b/lib/private/Repair/SharePropagation.php
index 26d7a9e128c32ab83aba027600bf9606caaefcd5..cd0c091b325b4b61736c49f38765cab9273c4d77 100644
--- a/lib/private/Repair/SharePropagation.php
+++ b/lib/private/Repair/SharePropagation.php
@@ -20,10 +20,12 @@
  */
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
 use OCP\IConfig;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class SharePropagation implements IRepairStep {
 
-class SharePropagation extends BasicEmitter implements \OC\RepairStep {
 	/** @var  IConfig */
 	private $config;
 
@@ -40,7 +42,7 @@ class SharePropagation extends BasicEmitter implements \OC\RepairStep {
 		return 'Remove old share propagation app entries';
 	}
 
-	public function run() {
+	public function run(IOutput $out ) {
 		$keys = $this->config->getAppKeys('files_sharing');
 
 		foreach ($keys as $key) {
diff --git a/lib/private/Repair/SqliteAutoincrement.php b/lib/private/Repair/SqliteAutoincrement.php
index d7cac57229d317075e60801556b04818246f46fd..e6f90dcece3050a3fe1cacb18eb472fbb6462461 100644
--- a/lib/private/Repair/SqliteAutoincrement.php
+++ b/lib/private/Repair/SqliteAutoincrement.php
@@ -26,13 +26,14 @@ use Doctrine\DBAL\Schema\SchemaException;
 use Doctrine\DBAL\Schema\SchemaDiff;
 use Doctrine\DBAL\Schema\TableDiff;
 use Doctrine\DBAL\Schema\ColumnDiff;
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Fixes Sqlite autoincrement by forcing the SQLite table schemas to be
  * altered in order to retrigger SQL schema generation through OCSqlitePlatform.
  */
-class SqliteAutoincrement extends BasicEmitter implements \OC\RepairStep {
+class SqliteAutoincrement implements IRepairStep {
 	/**
 	 * @var \OC\DB\Connection
 	 */
@@ -52,7 +53,7 @@ class SqliteAutoincrement extends BasicEmitter implements \OC\RepairStep {
 	/**
 	 * Fix mime types
 	 */
-	public function run() {
+	public function run(IOutput $out) {
 		if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
 			return;
 		}
diff --git a/lib/private/Repair/UpdateCertificateStore.php b/lib/private/Repair/UpdateCertificateStore.php
index ae7585f07f681562d6ce2fd4097ef4c9a120637d..9397fc77bce0c3480402cde49c7c31e4937ab866 100644
--- a/lib/private/Repair/UpdateCertificateStore.php
+++ b/lib/private/Repair/UpdateCertificateStore.php
@@ -22,10 +22,10 @@
 namespace OC\Repair;
 
 use OC\Files\View;
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OC\Server;
 use OCP\IConfig;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Class UpdateCertificateStore rewrites the user specific certificate store after
@@ -34,7 +34,7 @@ use OCP\IConfig;
  *
  * @package OC\Repair
  */
-class UpdateCertificateStore extends BasicEmitter implements RepairStep {
+class UpdateCertificateStore implements IRepairStep {
 	/**
 	 * FIXME: The certificate manager does only allow specifying the user
 	 *        within the constructor. This makes DI impossible.
@@ -60,7 +60,7 @@ class UpdateCertificateStore extends BasicEmitter implements RepairStep {
 	}
 
 	/** {@inheritDoc} */
-	public function run() {
+	public function run(IOutput $out) {
 		$rootView = new View();
 		$dataDirectory = $this->config->getSystemValue('datadirectory', null);
 		if(is_null($dataDirectory)) {
diff --git a/lib/private/Repair/UpdateOutdatedOcsIds.php b/lib/private/Repair/UpdateOutdatedOcsIds.php
index 60024b3055ce86cd29d7a19a2b99d2858532660d..4c768e93bd600aebe4c8dc2a53fb7c0c852ceff7 100644
--- a/lib/private/Repair/UpdateOutdatedOcsIds.php
+++ b/lib/private/Repair/UpdateOutdatedOcsIds.php
@@ -21,9 +21,9 @@
 
 namespace OC\Repair;
 
-use OC\Hooks\BasicEmitter;
-use OC\RepairStep;
 use OCP\IConfig;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Class UpdateOutdatedOcsIds is used to update invalid outdated OCS IDs, this is
@@ -33,7 +33,7 @@ use OCP\IConfig;
  *
  * @package OC\Repair
  */
-class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
+class UpdateOutdatedOcsIds implements IRepairStep {
 	/** @var IConfig */
 	private $config;
 
@@ -71,7 +71,7 @@ class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
 	/**
 	 * {@inheritdoc}
 	 */
-	public function run() {
+	public function run(IOutput $output) {
 		$appsToUpdate = [
 			'contacts' => [
 				'old' => '166044',
@@ -97,11 +97,7 @@ class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
 
 		foreach($appsToUpdate as $appName => $ids) {
 			if ($this->fixOcsId($appName, $ids['old'], $ids['new'])) {
-				$this->emit(
-					'\OC\Repair',
-					'info',
-					[sprintf('Fixed invalid %s OCS id', $appName)]
-				);
+				$output->info("Fixed invalid $appName OCS id");
 			}
 		}
 	}
diff --git a/lib/private/repair.php b/lib/private/repair.php
index 28fe993db0716093261ffe43bef7dfd0f2a3ad87..586e4e42b13160fb0fcebfcbdca8f75cc8a6462d 100644
--- a/lib/private/repair.php
+++ b/lib/private/repair.php
@@ -46,11 +46,13 @@ use OC\Repair\RepairMimeTypes;
 use OC\Repair\SearchLuceneTables;
 use OC\Repair\UpdateOutdatedOcsIds;
 use OC\Repair\RepairInvalidShares;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\GenericEvent;
 
-class Repair extends BasicEmitter {
-	/* @var RepairStep[] */
+class Repair extends BasicEmitter implements IOutput{
+	/* @var IRepairStep[] */
 	private $repairSteps;
 	/** @var EventDispatcher */
 	private $dispatcher;
@@ -58,7 +60,7 @@ class Repair extends BasicEmitter {
 	/**
 	 * Creates a new repair step runner
 	 *
-	 * @param RepairStep[] $repairSteps array of RepairStep instances
+	 * @param IRepairStep[] $repairSteps array of RepairStep instances
 	 * @param EventDispatcher $dispatcher
 	 */
 	public function __construct($repairSteps = [], EventDispatcher $dispatcher = null) {
@@ -88,24 +90,24 @@ class Repair extends BasicEmitter {
 				});
 			}
 
-			$step->run();
+			$step->run($this);
 		}
 	}
 
 	/**
 	 * Add repair step
 	 *
-	 * @param RepairStep|string $repairStep repair step
+	 * @param IRepairStep|string $repairStep repair step
 	 * @throws \Exception
 	 */
 	public function addStep($repairStep) {
 		if (is_string($repairStep)) {
 			if (class_exists($repairStep)) {
 				$s = new $repairStep();
-				if ($s instanceof RepairStep) {
+				if ($s instanceof IRepairStep) {
 					$this->repairSteps[] = $s;
 				} else {
-					throw new \Exception("Repair step '$repairStep' is not of type \\OC\\RepairStep");
+					throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
 				}
 			} else {
 				throw new \Exception("Repair step '$repairStep' is unknown");
@@ -119,7 +121,7 @@ class Repair extends BasicEmitter {
 	 * Returns the default repair steps to be run on the
 	 * command line or after an upgrade.
 	 *
-	 * @return array of RepairStep instances
+	 * @return IRepairStep[]
 	 */
 	public static function getRepairSteps() {
 		return [
@@ -141,7 +143,7 @@ class Repair extends BasicEmitter {
 	 * Returns expensive repair steps to be run on the
 	 * command line with a special option.
 	 *
-	 * @return array of RepairStep instances
+	 * @return IRepairStep[]
 	 */
 	public static function getExpensiveRepairSteps() {
 		return [
@@ -153,7 +155,7 @@ class Repair extends BasicEmitter {
 	 * Returns the repair steps to be run before an
 	 * upgrade.
 	 *
-	 * @return array of RepairStep instances
+	 * @return IRepairStep[]
 	 */
 	public static function getBeforeUpgradeRepairSteps() {
 		$connection = \OC::$server->getDatabaseConnection();
@@ -185,4 +187,41 @@ class Repair extends BasicEmitter {
 				new GenericEvent("$scope::$method", $arguments));
 		}
 	}
+
+	public function info($string) {
+		// for now just emit as we did in the past
+		$this->emit('\OC\Repair', 'info', array($string));
+	}
+
+	/**
+	 * @param string $message
+	 */
+	public function warning($message) {
+		// for now just emit as we did in the past
+		$this->emit('\OC\Repair', 'warning', [$message]);
+	}
+
+	/**
+	 * @param int $max
+	 */
+	public function startProgress($max = 0) {
+		// for now just emit as we did in the past
+		$this->emit('\OC\Repair', 'startProgress', [$max]);
+	}
+
+	/**
+	 * @param int $step
+	 */
+	public function advance($step = 1) {
+		// for now just emit as we did in the past
+		$this->emit('\OC\Repair', 'advance', [$step]);
+	}
+
+	/**
+	 * @param int $max
+	 */
+	public function finishProgress() {
+		// for now just emit as we did in the past
+		$this->emit('\OC\Repair', 'finishProgress', []);
+	}
 }
diff --git a/lib/public/migration/ioutput.php b/lib/public/migration/ioutput.php
new file mode 100644
index 0000000000000000000000000000000000000000..c52f13b31dc8ee40fa580ac617309147bf3192e4
--- /dev/null
+++ b/lib/public/migration/ioutput.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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/>
+ *
+ */
+namespace OCP\Migration;
+
+/**
+ * Interface IOutput
+ *
+ * @package OCP\Migration
+ * @since 9.1.0
+ */
+interface IOutput {
+
+	/**
+	 * @param string $message
+	 * @since 9.1.0
+	 */
+	public function info($message);
+
+	/**
+	 * @param string $message
+	 * @since 9.1.0
+	 */
+	public function warning($message);
+
+	/**
+	 * @param int $max
+	 * @since 9.1.0
+	 */
+	public function startProgress($max = 0);
+
+	/**
+	 * @param int $step
+	 * @since 9.1.0
+	 */
+	public function advance($step = 1);
+
+	/**
+	 * @param int $max
+	 * @since 9.1.0
+	 */
+	public function finishProgress();
+
+}
diff --git a/lib/private/repairstep.php b/lib/public/migration/irepairstep.php
similarity index 87%
rename from lib/private/repairstep.php
rename to lib/public/migration/irepairstep.php
index e1b8442fb8a9e8ecf63940f5ee52373a0af3a819..07830a935f95c84fa7831e8c9254e7f43104aade 100644
--- a/lib/private/repairstep.php
+++ b/lib/public/migration/irepairstep.php
@@ -18,17 +18,19 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>
  *
  */
-namespace OC;
+namespace OCP\Migration;
 
 /**
  * Repair step
+ * @since 9.1.0
  */
-interface RepairStep {
+interface IRepairStep {
 
 	/**
 	 * Returns the step's name
 	 *
 	 * @return string
+	 * @since 9.1.0
 	 */
 	public function getName();
 
@@ -36,8 +38,9 @@ interface RepairStep {
 	 * Run repair step.
 	 * Must throw exception on error.
 	 *
+	 * @since 9.1.0
 	 * @throws \Exception in case of failure
 	 */
-	public function run();
+	public function run(IOutput $output);
 
 }
diff --git a/tests/lib/repair.php b/tests/lib/repair.php
index 248db382140cec371511b928f34bd39490546f93..a598d3c1a29a1d4d554a8f2876f4c8843300ec03 100644
--- a/tests/lib/repair.php
+++ b/tests/lib/repair.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-use OC\Hooks\BasicEmitter;
+use OCP\Migration\IRepairStep;
 
-class TestRepairStep extends BasicEmitter implements \OC\RepairStep{
+class TestRepairStep implements IRepairStep {
 	private $warning;
 
 	public function __construct($warning = false) {
@@ -19,12 +19,12 @@ class TestRepairStep extends BasicEmitter implements \OC\RepairStep{
 		return 'Test Name';
 	}
 
-	public function run() {
+	public function run(\OCP\Migration\IOutput $out) {
 		if ($this->warning) {
-			$this->emit('\OC\Repair', 'warning', array('Simulated warning'));
+			$out->warning('Simulated warning');
 		}
 		else {
-			$this->emit('\OC\Repair', 'info', array('Simulated info'));
+			$out->info('Simulated info');
 		}
 	}
 }
diff --git a/tests/lib/repair/cleantags.php b/tests/lib/repair/cleantags.php
index fa11a7f736e6225c08af3d33e686fbf96c6e635f..214e2a17c9419bf21e55be787e92a689e2185f29 100644
--- a/tests/lib/repair/cleantags.php
+++ b/tests/lib/repair/cleantags.php
@@ -8,6 +8,7 @@
 
 namespace Test\Repair;
 use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Migration\IOutput;
 
 /**
  * Tests for the cleaning the tags tables
@@ -18,7 +19,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
  */
 class CleanTags extends \Test\TestCase {
 
-	/** @var \OC\RepairStep */
+	/** @var \OC\Repair\CleanTags */
 	protected $repair;
 
 	/** @var \OCP\IDBConnection */
@@ -27,9 +28,16 @@ class CleanTags extends \Test\TestCase {
 	/** @var int */
 	protected $createdFile;
 
+	/** @var IOutput */
+	private $outputMock;
+
 	protected function setUp() {
 		parent::setUp();
 
+		$this->outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
 		$this->connection = \OC::$server->getDatabaseConnection();
 		$this->repair = new \OC\Repair\CleanTags($this->connection);
 		$this->cleanUpTables();
@@ -67,15 +75,15 @@ class CleanTags extends \Test\TestCase {
 		$this->assertEntryCount('vcategory_to_object', 4, 'Assert tag entries count before repair step');
 		$this->assertEntryCount('vcategory', 4, 'Assert tag categories count before repair step');
 
-		self::invokePrivate($this->repair, 'deleteOrphanFileEntries');
+		self::invokePrivate($this->repair, 'deleteOrphanFileEntries', [$this->outputMock]);
 		$this->assertEntryCount('vcategory_to_object', 3, 'Assert tag entries count after cleaning file entries');
 		$this->assertEntryCount('vcategory', 4, 'Assert tag categories count after cleaning file entries');
 
-		self::invokePrivate($this->repair, 'deleteOrphanTagEntries');
+		self::invokePrivate($this->repair, 'deleteOrphanTagEntries', [$this->outputMock]);
 		$this->assertEntryCount('vcategory_to_object', 2, 'Assert tag entries count after cleaning tag entries');
 		$this->assertEntryCount('vcategory', 4, 'Assert tag categories count after cleaning tag entries');
 
-		self::invokePrivate($this->repair, 'deleteOrphanCategoryEntries');
+		self::invokePrivate($this->repair, 'deleteOrphanCategoryEntries', [$this->outputMock]);
 		$this->assertEntryCount('vcategory_to_object', 2, 'Assert tag entries count after cleaning category entries');
 		$this->assertEntryCount('vcategory', 2, 'Assert tag categories count after cleaning category entries');
 	}
diff --git a/tests/lib/repair/dropoldjobs.php b/tests/lib/repair/dropoldjobs.php
index a85c6506dbbc140835f3915ffb2b13ba789ed5e3..c8a4aa3f1c2565fcb31d1c25d95f805106ca410d 100644
--- a/tests/lib/repair/dropoldjobs.php
+++ b/tests/lib/repair/dropoldjobs.php
@@ -9,6 +9,7 @@
 namespace Test\Repair;
 
 use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
 
 /**
  * Tests for the dropping old tables
@@ -33,8 +34,13 @@ class DropOldJobs extends \Test\TestCase {
 		$this->assertTrue($this->jobList->has('OC\Cache\FileGlobalGC', null), 'Asserting that the job OC\Cache\FileGlobalGC exists before repairing');
 		$this->assertTrue($this->jobList->has('OC_Cache_FileGlobalGC', null), 'Asserting that the job OC_Cache_FileGlobalGC exists before repairing');
 
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
 		$repair = new \OC\Repair\DropOldJobs($this->jobList);
-		$repair->run();
+		$repair->run($outputMock);
 
 		$this->assertFalse($this->jobList->has('OC\Cache\FileGlobalGC', null), 'Asserting that the job OC\Cache\FileGlobalGC does not exist after repairing');
 		$this->assertFalse($this->jobList->has('OC_Cache_FileGlobalGC', null), 'Asserting that the job OC_Cache_FileGlobalGC does not exist after repairing');
diff --git a/tests/lib/repair/dropoldtables.php b/tests/lib/repair/dropoldtables.php
index 6ece8cf04d58753f30742182b7a0a0a8aacd3336..d2e1d7c3449fe1d0247cabf22a04f8243a9ad5b5 100644
--- a/tests/lib/repair/dropoldtables.php
+++ b/tests/lib/repair/dropoldtables.php
@@ -7,6 +7,7 @@
  */
 
 namespace Test\Repair;
+use OCP\Migration\IOutput;
 
 /**
  * Tests for the dropping old tables
@@ -31,8 +32,13 @@ class DropOldTables extends \Test\TestCase {
 		$this->assertFalse($this->connection->tableExists('sharing'), 'Asserting that the table oc_sharing does not exist before repairing');
 		$this->assertTrue($this->connection->tableExists('permissions'), 'Asserting that the table oc_permissions does exist before repairing');
 
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
 		$repair = new \OC\Repair\DropOldTables($this->connection);
-		$repair->run();
+		$repair->run($outputMock);
 
 		$this->assertFalse($this->connection->tableExists('sharing'), 'Asserting that the table oc_sharing does not exist after repairing');
 		$this->assertFalse($this->connection->tableExists('permissions'), 'Asserting that the table oc_permissions does not exist after repairing');
diff --git a/tests/lib/repair/oldgroupmembershipsharestest.php b/tests/lib/repair/oldgroupmembershipsharestest.php
index f02babab21d75806f49fc89ad8a658627874f75a..cc04a80eef9e103d1cfb20f2d2e070b820f74e44 100644
--- a/tests/lib/repair/oldgroupmembershipsharestest.php
+++ b/tests/lib/repair/oldgroupmembershipsharestest.php
@@ -10,6 +10,7 @@ namespace Test\Repair;
 
 use OC\Repair\OldGroupMembershipShares;
 use OC\Share\Constants;
+use OCP\Migration\IOutput;
 
 /**
  * Class OldGroupMembershipSharesTest
@@ -82,7 +83,12 @@ class OldGroupMembershipSharesTest extends \Test\TestCase {
 		$this->assertEquals([['id' => $parent], ['id' => $group2], ['id' => $user1], ['id' => $member], ['id' => $notAMember]], $rows);
 		$result->closeCursor();
 
-		$repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$repair->run($outputMock);
 
 		$query = $this->connection->getQueryBuilder();
 		$result = $query->select('id')
diff --git a/tests/lib/repair/removegetetagentriestest.php b/tests/lib/repair/removegetetagentriestest.php
index 12f0ae8a8d643085249a598d294721b7acb29d2b..c00923228d0ca225df2b2c759f3c03048d69e921 100644
--- a/tests/lib/repair/removegetetagentriestest.php
+++ b/tests/lib/repair/removegetetagentriestest.php
@@ -22,6 +22,7 @@
 namespace Test\Repair;
 
 use OC\Repair\RemoveGetETagEntries;
+use OCP\Migration\IOutput;
 use Test\TestCase;
 
 /**
@@ -65,9 +66,14 @@ class RemoveGetETagEntriesTest extends TestCase {
 			$this->assertTrue(in_array($entry, $data), 'Asserts that the entries are the ones from the test data set');
 		}
 
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
 		// run repair step
 		$repair = new RemoveGetETagEntries($this->connection);
-		$repair->run();
+		$repair->run($outputMock);
 
 		// check if test data is correctly modified in DB
 		$stmt = $this->connection->executeQuery($sqlToFetchProperties, [$userName]);
diff --git a/tests/lib/repair/repaircollation.php b/tests/lib/repair/repaircollation.php
index 8d609aeed386adca0a9eaf43ceeb219e4fd1f3ca..4efa8ccc55295d42dfb3ed9ef712ee44a2b2c181 100644
--- a/tests/lib/repair/repaircollation.php
+++ b/tests/lib/repair/repaircollation.php
@@ -1,4 +1,6 @@
 <?php
+use OCP\Migration\IOutput;
+
 /**
  * Copyright (c) 2014 Thomas Müller <deepdiver@owncloud.com>
  * This file is licensed under the Affero General Public License version 3 or
@@ -70,7 +72,12 @@ class TestRepairCollation extends \Test\TestCase {
 		$tables = $this->repair->getAllNonUTF8BinTables($this->connection);
 		$this->assertGreaterThanOrEqual(1, count($tables));
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		$tables = $this->repair->getAllNonUTF8BinTables($this->connection);
 		$this->assertCount(0, $tables);
diff --git a/tests/lib/repair/repairinnodb.php b/tests/lib/repair/repairinnodb.php
index 5c73b9313676c037c7de7c701bcfaba34e5cae00..9b02bc46e29173385cac26e81fdf1989b1e06cad 100644
--- a/tests/lib/repair/repairinnodb.php
+++ b/tests/lib/repair/repairinnodb.php
@@ -6,6 +6,8 @@
  * See the COPYING-README file.
  */
 namespace Test\Repair;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 
 /**
  * Tests for the converting of MySQL tables to InnoDB engine
@@ -16,7 +18,7 @@ namespace Test\Repair;
  */
 class RepairInnoDB extends \Test\TestCase {
 
-	/** @var \OC\RepairStep */
+	/** @var IRepairStep */
 	private $repair;
 
 	/** @var \Doctrine\DBAL\Connection */
@@ -49,7 +51,12 @@ class RepairInnoDB extends \Test\TestCase {
 		$result = $this->countMyIsamTables();
 		$this->assertEquals(1, $result);
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		$result = $this->countMyIsamTables();
 		$this->assertEquals(0, $result);
diff --git a/tests/lib/repair/repairinvalidsharestest.php b/tests/lib/repair/repairinvalidsharestest.php
index 9655e0eacbc5b14e835171ea1d4366f5777c010b..a1e871bcc80c00312a02e8e19e01d72e2e1a2bd8 100644
--- a/tests/lib/repair/repairinvalidsharestest.php
+++ b/tests/lib/repair/repairinvalidsharestest.php
@@ -11,6 +11,8 @@ namespace Test\Repair;
 
 use OC\Repair\RepairInvalidShares;
 use OC\Share\Constants;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
 use Test\TestCase;
 
 /**
@@ -22,7 +24,7 @@ use Test\TestCase;
  */
 class RepairInvalidSharesTest extends TestCase {
 
-	/** @var \OC\RepairStep */
+	/** @var IRepairStep */
 	private $repair;
 
 	/** @var \OCP\IDBConnection */
@@ -98,7 +100,12 @@ class RepairInvalidSharesTest extends TestCase {
 				'token' => $qb->expr()->literal('abcdefg')
 			])->execute();
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		$results = $this->connection->getQueryBuilder()
 			->select('*')
@@ -167,7 +174,12 @@ class RepairInvalidSharesTest extends TestCase {
 		$this->assertEquals([['id' => $parent], ['id' => $validChild], ['id' => $invalidChild]], $rows);
 		$result->closeCursor();
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		$query = $this->connection->getQueryBuilder();
 		$result = $query->select('id')
diff --git a/tests/lib/repair/repairlegacystorage.php b/tests/lib/repair/repairlegacystorage.php
index 3ae6578f7ec343fecf28407b565667b92e1bafb4..5b560458e769d80e9e4c0a15b320fb7e20210c9b 100644
--- a/tests/lib/repair/repairlegacystorage.php
+++ b/tests/lib/repair/repairlegacystorage.php
@@ -10,6 +10,8 @@ namespace Test\Repair;
 
 use OC\Files\Cache\Cache;
 use OC\Files\Cache\Storage;
+use OCP\Migration\IOutput;
+use PHPUnit_Framework_MockObject_MockObject;
 use Test\TestCase;
 
 /**
@@ -34,7 +36,8 @@ class RepairLegacyStorages extends TestCase {
 	private $legacyStorageId;
 	private $newStorageId;
 
-	private $warnings;
+	/** @var IOutput | PHPUnit_Framework_MockObject_MockObject */
+	private $outputMock;
 
 	protected function setUp() {
 		parent::setUp();
@@ -45,11 +48,9 @@ class RepairLegacyStorages extends TestCase {
 
 		$this->repair = new \OC\Repair\RepairLegacyStorages($this->config, $this->connection);
 
-		$this->warnings = [];
-
-		$this->repair->listen('\OC\Repair', 'warning', function ($description){
-			$this->warnings[] = $description;
-		});
+		$this->outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
 	}
 
 	protected function tearDown() {
@@ -141,7 +142,7 @@ class RepairLegacyStorages extends TestCase {
 		$this->prepareSettings($dataDir, $userId);
 		$newStorageNumId = $this->createStorage($this->newStorageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertNull($this->getStorageId($this->legacyStorageId));
 		$this->assertEquals($newStorageNumId, $this->getStorageId($this->newStorageId));
@@ -160,7 +161,7 @@ class RepairLegacyStorages extends TestCase {
 		$this->prepareSettings($dataDir, $userId);
 		$legacyStorageNumId = $this->createStorage($this->legacyStorageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertNull($this->getStorageId($this->legacyStorageId));
 		$this->assertEquals($legacyStorageNumId, $this->getStorageId($this->newStorageId));
@@ -182,7 +183,7 @@ class RepairLegacyStorages extends TestCase {
 
 		$this->createData($this->legacyStorageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertNull($this->getStorageId($this->legacyStorageId));
 		$this->assertEquals($legacyStorageNumId, $this->getStorageId($this->newStorageId));
@@ -205,7 +206,7 @@ class RepairLegacyStorages extends TestCase {
 
 		$this->createData($this->newStorageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertNull($this->getStorageId($this->legacyStorageId));
 		$this->assertEquals($newStorageNumId, $this->getStorageId($this->newStorageId));
@@ -228,10 +229,8 @@ class RepairLegacyStorages extends TestCase {
 		$this->createData($this->legacyStorageId);
 		$this->createData($this->newStorageId);
 
-		$this->repair->run();
-
-		$this->assertEquals(2, count($this->warnings));
-		$this->assertEquals('Could not repair legacy storage ', substr(current($this->warnings), 0, 32));
+		$this->outputMock->expects($this->exactly(2))->method('warning');
+		$this->repair->run($this->outputMock);
 
 		// storages left alone
 		$this->assertEquals($legacyStorageNumId, $this->getStorageId($this->legacyStorageId));
@@ -254,7 +253,7 @@ class RepairLegacyStorages extends TestCase {
 		$storageId = 'local::' . $this->dataDir;
 		$numId = $this->createStorage($storageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertEquals($numId, $this->getStorageId($storageId));
 	}
@@ -272,7 +271,7 @@ class RepairLegacyStorages extends TestCase {
 		$storageId = 'local::/tmp/somedir/' . $this->user;
 		$numId = $this->createStorage($storageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertEquals($numId, $this->getStorageId($storageId));
 	}
@@ -290,7 +289,7 @@ class RepairLegacyStorages extends TestCase {
 		$storageId = 'smb::user@password/tmp/somedir/' . $this->user;
 		$numId = $this->createStorage($storageId);
 
-		$this->repair->run();
+		$this->repair->run($this->outputMock);
 
 		$this->assertEquals($numId, $this->getStorageId($storageId));
 	}
@@ -322,21 +321,15 @@ class RepairLegacyStorages extends TestCase {
 	 * Only run the repair once
 	 */
 	public function testOnlyRunOnce() {
-		$output = array();
-		$this->repair->listen('\OC\Repair', 'info', function ($description) use (&$output) {
-			$output[] = 'info: ' . $description;
-		});
+		$this->outputMock->expects($this->exactly(1))->method('info');
 
 		$this->prepareSettings('/tmp/oc-autotest/datadir', $this->getUniqueID('user_'));
 		$this->assertNotEquals('yes', $this->config->getAppValue('core', 'repairlegacystoragesdone'));
-		$this->repair->run();
-		$this->assertEquals(1, count($output));
+		$this->repair->run($this->outputMock);
 		$this->assertEquals('yes', $this->config->getAppValue('core', 'repairlegacystoragesdone'));
 
-		$output = array();
-		$this->repair->run();
-		// no output which means it did not run
-		$this->assertEquals(0, count($output));
+		$this->outputMock->expects($this->never())->method('info');
+		$this->repair->run($this->outputMock);
 		$this->assertEquals('yes', $this->config->getAppValue('core', 'repairlegacystoragesdone'));
 	}
 }
diff --git a/tests/lib/repair/repairmimetypes.php b/tests/lib/repair/repairmimetypes.php
index a9ebb7bc88ac442693f3c638226e7a9908bde54d..d8ef95e954692adc9fe5196283d0c21d9c520eda 100644
--- a/tests/lib/repair/repairmimetypes.php
+++ b/tests/lib/repair/repairmimetypes.php
@@ -8,6 +8,12 @@
  */
 namespace Test\Repair;
 
+use OC\Files\Storage\Temporary;
+use OCP\Files\IMimeTypeLoader;
+use OCP\IConfig;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
 /**
  * Tests for the converting of legacy storages to home storages.
  *
@@ -17,17 +23,22 @@ namespace Test\Repair;
  */
 class RepairMimeTypes extends \Test\TestCase {
 
-	/** @var \OC\RepairStep */
+	/** @var IRepairStep */
 	private $repair;
 
+	/** @var Temporary */
 	private $storage;
 
+	/** @var IMimeTypeLoader */
+	private $mimetypeLoader;
+
 	protected function setUp() {
 		parent::setUp();
 
 		$this->savedMimetypeLoader = \OC::$server->getMimeTypeLoader();
 		$this->mimetypeLoader = \OC::$server->getMimeTypeLoader();
 
+		/** @var IConfig | \PHPUnit_Framework_MockObject_MockObject $config */
 		$config = $this->getMockBuilder('OCP\IConfig')
 			->disableOriginalConstructor()
 			->getMock();
@@ -96,7 +107,12 @@ class RepairMimeTypes extends \Test\TestCase {
 	private function renameMimeTypes($currentMimeTypes, $fixedMimeTypes) {
 		$this->addEntries($currentMimeTypes);
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		// force mimetype reload
 		$this->mimetypeLoader->reset();
diff --git a/tests/lib/repair/repairsharepropagation.php b/tests/lib/repair/repairsharepropagation.php
index 6ec8b98ec56db22be78e767982af4ed8b2b5e73a..34b47397a53ef07979e676ad40a2d8a39dbbefae 100644
--- a/tests/lib/repair/repairsharepropagation.php
+++ b/tests/lib/repair/repairsharepropagation.php
@@ -9,6 +9,7 @@
 namespace Test\Repair;
 
 use OC\Repair\SharePropagation;
+use OCP\Migration\IOutput;
 
 class RepairSharePropagation extends \Test\TestCase {
 	public function keyProvider() {
@@ -40,8 +41,13 @@ class RepairSharePropagation extends \Test\TestCase {
 				$removedKeys[] = $key;
 			}));
 
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
 		$step = new SharePropagation($config);
-		$step->run();
+		$step->run($outputMock);
 
 		sort($expectedRemovedKeys);
 		sort($removedKeys);
diff --git a/tests/lib/repair/repairsqliteautoincrement.php b/tests/lib/repair/repairsqliteautoincrement.php
index 6f0c2cb8d28508e1b41aa30b298d05b84025ea61..581857ebfc99b9014a4222bf9c84e03525f159cc 100644
--- a/tests/lib/repair/repairsqliteautoincrement.php
+++ b/tests/lib/repair/repairsqliteautoincrement.php
@@ -7,6 +7,7 @@
  */
 
 namespace Test\Repair;
+use OCP\Migration\IOutput;
 
 /**
  * Tests for fixing the SQLite id recycling
@@ -76,7 +77,12 @@ class RepairSqliteAutoincrement extends \Test\TestCase {
 	public function testConvertIdColumn() {
 		$this->assertFalse($this->checkAutoincrement());
 
-		$this->repair->run();
+		/** @var IOutput | \PHPUnit_Framework_MockObject_MockObject $outputMock */
+		$outputMock = $this->getMockBuilder('\OCP\Migration\IOutput')
+			->disableOriginalConstructor()
+			->getMock();
+
+		$this->repair->run($outputMock);
 
 		$this->assertTrue($this->checkAutoincrement());
 	}
diff --git a/tests/lib/repair/updateoutdatedocsids.php b/tests/lib/repair/updateoutdatedocsids.php
index 3669a64371f76952c2b28fa1bc59ef94a4c6e22b..06e2cb1d610bf5a3a38fde6d0f68c55eb5cda737 100644
--- a/tests/lib/repair/updateoutdatedocsids.php
+++ b/tests/lib/repair/updateoutdatedocsids.php
@@ -30,7 +30,7 @@ use Test\TestCase;
  * @package Test\Repair
  */
 class UpdateOutdatedOcsIds extends TestCase {
-	/** @var IConfig */
+	/** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
 	private $config;
 	/** @var \OC\Repair\UpdateOutdatedOcsIds */
 	private $updateOutdatedOcsIds;