mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 09:25:43 +01:00
Introduce PluginDependencyTracker
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static sonia.scm.ScmConstraintViolationException.Builder.doThrow;
|
||||||
|
|
||||||
|
class PluginDependencyTracker {
|
||||||
|
|
||||||
|
private final Map<String, Collection<String>> plugins = new HashMap<>();
|
||||||
|
|
||||||
|
void addInstalled(PluginDescriptor plugin) {
|
||||||
|
plugin.getDependencies().forEach(dependency -> addDependency(plugin.getInformation().getName(), dependency));
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeInstalled(PluginDescriptor plugin) {
|
||||||
|
doThrow()
|
||||||
|
.violation("Plugin is needed as a dependency for other plugins", "plugin")
|
||||||
|
.when(!mayUninstall(plugin.getInformation().getName()));
|
||||||
|
plugin.getDependencies().forEach(dependency -> removeDependency(plugin.getInformation().getName(), dependency));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean mayUninstall(String name) {
|
||||||
|
return plugins.computeIfAbsent(name, x -> new HashSet<>()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDependency(String from, String to) {
|
||||||
|
plugins.computeIfAbsent(to, name -> createInitialDependencyCollection(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeDependency(String from, String to) {
|
||||||
|
plugins.get(to).remove(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<String> createInitialDependencyCollection(String from) {
|
||||||
|
Collection<String> dependencies = new HashSet<>();
|
||||||
|
dependencies.add(from);
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import sonia.scm.ScmConstraintViolationException;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptySet;
|
||||||
|
import static java.util.Collections.singleton;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static sonia.scm.plugin.PluginTestHelper.createInstalled;
|
||||||
|
|
||||||
|
class PluginDependencyTrackerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void simpleInstalledPluginWithoutDependingPluginsCanBeUninstalled() {
|
||||||
|
PluginDescriptor mail = createInstalled("scm-mail-plugin").getDescriptor();
|
||||||
|
when(mail.getDependencies()).thenReturn(emptySet());
|
||||||
|
|
||||||
|
PluginDependencyTracker pluginDependencyTracker = new PluginDependencyTracker();
|
||||||
|
pluginDependencyTracker.addInstalled(mail);
|
||||||
|
|
||||||
|
boolean mayUninstall = pluginDependencyTracker.mayUninstall("scm-mail-plugin");
|
||||||
|
assertThat(mayUninstall).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void installedPluginWithDependingPluginCannotBeUninstalled() {
|
||||||
|
PluginDescriptor review = createInstalled("scm-review-plugin").getDescriptor();
|
||||||
|
when(review.getDependencies()).thenReturn(singleton("scm-mail-plugin"));
|
||||||
|
|
||||||
|
PluginDependencyTracker pluginDependencyTracker = new PluginDependencyTracker();
|
||||||
|
pluginDependencyTracker.addInstalled(review);
|
||||||
|
|
||||||
|
boolean mayUninstall = pluginDependencyTracker.mayUninstall("scm-mail-plugin");
|
||||||
|
assertThat(mayUninstall).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void uninstallOfRequiredPluginShouldThrowException() {
|
||||||
|
PluginDescriptor review = createInstalled("scm-review-plugin").getDescriptor();
|
||||||
|
when(review.getDependencies()).thenReturn(singleton("scm-mail-plugin"));
|
||||||
|
|
||||||
|
PluginDependencyTracker pluginDependencyTracker = new PluginDependencyTracker();
|
||||||
|
pluginDependencyTracker.addInstalled(review);
|
||||||
|
|
||||||
|
Assertions.assertThrows(
|
||||||
|
ScmConstraintViolationException.class,
|
||||||
|
() -> pluginDependencyTracker.removeInstalled(createInstalled("scm-mail-plugin").getDescriptor())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void installedPluginWithDependingPluginCanBeUninstalledAfterDependingPluginIsUninstalled() {
|
||||||
|
PluginDescriptor review = createInstalled("scm-review-plugin").getDescriptor();
|
||||||
|
when(review.getDependencies()).thenReturn(singleton("scm-mail-plugin"));
|
||||||
|
|
||||||
|
PluginDependencyTracker pluginDependencyTracker = new PluginDependencyTracker();
|
||||||
|
pluginDependencyTracker.addInstalled(review);
|
||||||
|
pluginDependencyTracker.removeInstalled(review);
|
||||||
|
|
||||||
|
boolean mayUninstall = pluginDependencyTracker.mayUninstall("scm-mail-plugin");
|
||||||
|
assertThat(mayUninstall).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void installedPluginWithMultipleDependingPluginCannotBeUninstalledAfterOnlyOneDependingPluginIsUninstalled() {
|
||||||
|
PluginDescriptor review = createInstalled("scm-review-plugin").getDescriptor();
|
||||||
|
when(review.getDependencies()).thenReturn(singleton("scm-mail-plugin"));
|
||||||
|
PluginDescriptor jira = createInstalled("scm-jira-plugin").getDescriptor();
|
||||||
|
when(jira.getDependencies()).thenReturn(singleton("scm-mail-plugin"));
|
||||||
|
|
||||||
|
PluginDependencyTracker pluginDependencyTracker = new PluginDependencyTracker();
|
||||||
|
pluginDependencyTracker.addInstalled(review);
|
||||||
|
pluginDependencyTracker.addInstalled(jira);
|
||||||
|
pluginDependencyTracker.removeInstalled(jira);
|
||||||
|
|
||||||
|
boolean mayUninstall = pluginDependencyTracker.mayUninstall("scm-mail-plugin");
|
||||||
|
assertThat(mayUninstall).isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user