Fix uninstallable flag after discarding changes

After uninstalling a plugin (without restart) and then discarding the
changes, plugins which are required for the plugin can be uninstalled
even if the uninstallation was reverted. This was caused by not updating
the dependency relations between the plugins when an uninstallation has
been canceled. Therefore, the updating step is added.
This commit is contained in:
Laura Gorzitze
2024-02-13 18:02:54 +01:00
parent ec14d4cbd5
commit 46c52cdb99
4 changed files with 34 additions and 1 deletions

View File

@@ -0,0 +1,2 @@
- type: fixed
description: Required plugins can be uninstalled even when dependent plugins are still installed

View File

@@ -390,6 +390,7 @@ public class DefaultPluginManager implements PluginManager {
PluginPermissions.write().check();
pendingUninstallQueue.forEach(PendingPluginUninstallation::cancel);
pendingInstallQueue.forEach(PendingPluginInstallation::cancel);
pendingUninstallQueue.forEach(pendingPluginUninstallation -> dependencyTracker.addInstalled(pendingPluginUninstallation.getPlugin().getDescriptor()));
pendingUninstallQueue.clear();
pendingInstallQueue.clear();
updateMayUninstallFlag();

View File

@@ -53,4 +53,8 @@ class PendingPluginUninstallation {
throw new PluginFailedToCancelInstallationException("failed to cancel uninstallation", name, ex);
}
}
InstalledPlugin getPlugin() {
return plugin;
}
}

View File

@@ -57,8 +57,10 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.anyOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -99,6 +101,9 @@ class DefaultPluginManagerTest {
@Captor
private ArgumentCaptor<PluginInstallationContext> contextCaptor;
@Captor
private ArgumentCaptor<Boolean> booleanCaptor;
private DefaultPluginManager manager;
@Mock
@@ -458,7 +463,7 @@ class DefaultPluginManagerTest {
}
@Test
void shouldUseDependencyTrackerForUninstall() {
void shouldPreventUninstallationOfRequiredPlugin() {
InstalledPlugin mailPlugin = createInstalled("scm-mail-plugin");
InstalledPlugin reviewPlugin = createInstalled("scm-review-plugin");
when(reviewPlugin.getDescriptor().getDependencies()).thenReturn(singleton("scm-mail-plugin"));
@@ -553,6 +558,27 @@ class DefaultPluginManagerTest {
verify(mailPlugin).setUninstallable(true);
}
@Test
void shouldUpdateMayUninstallFlagAfterCancelingUninstallationOfDependentPlugin() {
InstalledPlugin mailPlugin = createInstalled("scm-mail-plugin");
InstalledPlugin reviewPlugin = createInstalled("scm-review-plugin");
when(reviewPlugin.getDescriptor().getDependencies()).thenReturn(singleton("scm-mail-plugin"));
when(loader.getInstalledPlugins()).thenReturn(asList(mailPlugin, reviewPlugin));
doNothing().when(mailPlugin).setUninstallable(booleanCaptor.capture());
manager.computeInstallationDependencies();
manager.uninstall("scm-review-plugin", false);
manager.cancelPending();
List<Boolean> values = booleanCaptor.getAllValues();
assertThat(values).containsExactly(false, true, false);
}
@Test
void shouldUpdateMayUninstallFlagAfterDependencyIsInstalled() {
InstalledPlugin mailPlugin = createInstalled("scm-mail-plugin");