Merge pull request #59676 from nextcloud/fix/noid/reinstall-missing-apps-on-upgrade

Restore missing apps on upgrade
This commit is contained in:
Julien Veyssier 2026-04-17 13:17:32 +02:00 committed by GitHub
commit 89b06a4df6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 0 deletions

View file

@ -23,6 +23,7 @@ use OC\Repair\Events\RepairInfoEvent;
use OC\Repair\Events\RepairStartEvent;
use OC\Repair\Events\RepairStepEvent;
use OC\Repair\Events\RepairWarningEvent;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
@ -391,6 +392,8 @@ class Updater extends BasicEmitter {
$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
if (isset($previousEnableStates[$app])) {
$this->restoreMissingAppStoreApp($app);
if (!empty($previousEnableStates[$app]) && is_array($previousEnableStates[$app])) {
$this->appManager->enableAppForGroups($app, $previousEnableStates[$app]);
} elseif ($previousEnableStates[$app] === 'yes') {
@ -405,6 +408,17 @@ class Updater extends BasicEmitter {
}
}
private function restoreMissingAppStoreApp(string $appId): void {
try {
$this->appManager->getAppPath($appId, true);
} catch (AppPathNotFoundException) {
// the app was not found locally but we know it was previously enabled
// so we automatically download it from the appstore and run its missing migrations
$this->installer->downloadApp($appId);
$this->installer->installApp($appId);
}
}
private function logAllEvents(): void {
$log = $this->log;

View file

@ -11,6 +11,7 @@ namespace Test;
use OC\Installer;
use OC\IntegrityCheck\Checker;
use OC\Updater;
use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\IAppConfig;
use OCP\IConfig;
@ -107,4 +108,36 @@ class UpdaterTest extends TestCase {
$this->assertSame($result, $this->updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersions));
}
public function testUpgradeAppStoreAppsRestoresMissingAutoDisabledAppBeforeEnabling(): void {
$this->installer->expects($this->once())
->method('isUpdateAvailable')
->with('mailroundcube')
->willReturn(false);
$this->installer->expects($this->once())
->method('downloadApp')
->with('mailroundcube');
$this->installer->expects($this->once())
->method('installApp')
->with('mailroundcube');
$this->appManager->expects($this->once())
->method('getAppPath')
->with('mailroundcube', true)
->willThrowException(new AppPathNotFoundException('missing'));
$this->appManager->expects($this->once())
->method('enableApp')
->with('mailroundcube');
$this->appManager->expects($this->never())
->method('enableAppForGroups');
self::invokePrivate($this->updater, 'upgradeAppStoreApps', [
['mailroundcube'],
['mailroundcube' => 'yes'],
]);
}
}