mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
Add uninstall method to plugin manager
This commit is contained in:
@@ -81,6 +81,14 @@ public interface PluginManager {
|
|||||||
*/
|
*/
|
||||||
void install(String name, boolean restartAfterInstallation);
|
void install(String name, boolean restartAfterInstallation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the plugin with the given name for uninstall.
|
||||||
|
*
|
||||||
|
* @param name plugin name
|
||||||
|
* @param restartAfterInstallation restart context after plugin has been marked to really uninstall the plugin
|
||||||
|
*/
|
||||||
|
void uninstall(String name, boolean restartAfterInstallation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install all pending plugins and restart the scm context.
|
* Install all pending plugins and restart the scm context.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -33,8 +33,7 @@
|
|||||||
|
|
||||||
package sonia.scm.plugin;
|
package sonia.scm.plugin;
|
||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -43,9 +42,11 @@ import sonia.scm.NotFoundException;
|
|||||||
import sonia.scm.event.ScmEventBus;
|
import sonia.scm.event.ScmEventBus;
|
||||||
import sonia.scm.lifecycle.RestartEvent;
|
import sonia.scm.lifecycle.RestartEvent;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -54,6 +55,8 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||||
|
|
||||||
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -67,7 +70,8 @@ public class DefaultPluginManager implements PluginManager {
|
|||||||
private final PluginLoader loader;
|
private final PluginLoader loader;
|
||||||
private final PluginCenter center;
|
private final PluginCenter center;
|
||||||
private final PluginInstaller installer;
|
private final PluginInstaller installer;
|
||||||
private final List<PendingPluginInstallation> pendingQueue = new ArrayList<>();
|
private final Collection<PendingPluginInstallation> pendingQueue = new ArrayList<>();
|
||||||
|
private final PluginDependencyTracker dependencyTracker = new PluginDependencyTracker();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DefaultPluginManager(ScmEventBus eventBus, PluginLoader loader, PluginCenter center, PluginInstaller installer) {
|
public DefaultPluginManager(ScmEventBus eventBus, PluginLoader loader, PluginCenter center, PluginInstaller installer) {
|
||||||
@@ -75,6 +79,16 @@ public class DefaultPluginManager implements PluginManager {
|
|||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
this.center = center;
|
this.center = center;
|
||||||
this.installer = installer;
|
this.installer = installer;
|
||||||
|
|
||||||
|
this.computeRequiredPlugins();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
synchronized void computeRequiredPlugins() {
|
||||||
|
loader.getInstalledPlugins()
|
||||||
|
.stream()
|
||||||
|
.map(InstalledPlugin::getDescriptor)
|
||||||
|
.forEach(dependencyTracker::addInstalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -153,6 +167,21 @@ public class DefaultPluginManager implements PluginManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uninstall(String name, boolean restartAfterInstallation) {
|
||||||
|
PluginPermissions.manage().check();
|
||||||
|
InstalledPlugin installed = getInstalled(name)
|
||||||
|
.orElseThrow(() -> NotFoundException.notFound(entity(InstalledPlugin.class, name)));
|
||||||
|
|
||||||
|
dependencyTracker.removeInstalled(installed.getDescriptor());
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.createFile(installed.getDirectory().resolve("uninstall"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new PluginException("could not mark plugin " + name + " in path " + installed.getDirectory() + " for uninstall", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void installPendingAndRestart() {
|
public void installPendingAndRestart() {
|
||||||
PluginPermissions.manage().check();
|
PluginPermissions.manage().check();
|
||||||
|
|||||||
@@ -10,26 +10,37 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Answers;
|
import org.junitpioneer.jupiter.TempDirectory;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import sonia.scm.NotFoundException;
|
import sonia.scm.NotFoundException;
|
||||||
|
import sonia.scm.ScmConstraintViolationException;
|
||||||
import sonia.scm.event.ScmEventBus;
|
import sonia.scm.event.ScmEventBus;
|
||||||
import sonia.scm.lifecycle.RestartEvent;
|
import sonia.scm.lifecycle.RestartEvent;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static java.util.Collections.singleton;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.in;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.any;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.doThrow;
|
||||||
|
import static org.mockito.Mockito.lenient;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
import static sonia.scm.plugin.PluginTestHelper.createAvailable;
|
import static sonia.scm.plugin.PluginTestHelper.createAvailable;
|
||||||
import static sonia.scm.plugin.PluginTestHelper.createInstalled;
|
import static sonia.scm.plugin.PluginTestHelper.createInstalled;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@ExtendWith(TempDirectory.class)
|
||||||
class DefaultPluginManagerTest {
|
class DefaultPluginManagerTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@@ -305,6 +316,34 @@ class DefaultPluginManagerTest {
|
|||||||
assertThat(available.get(0).isPending()).isTrue();
|
assertThat(available.get(0).isPending()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowExceptionWhenUninstallingUnknownPlugin() {
|
||||||
|
assertThrows(NotFoundException.class, () -> manager.uninstall("no-such-plugin", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldUseDependencyTrackerForUninstall() {
|
||||||
|
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(ImmutableList.of(mailPlugin, reviewPlugin));
|
||||||
|
manager.computeRequiredPlugins();
|
||||||
|
|
||||||
|
assertThrows(ScmConstraintViolationException.class, () -> manager.uninstall("scm-mail-plugin", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldCreateUninstallFile(@TempDirectory.TempDir Path temp) {
|
||||||
|
InstalledPlugin mailPlugin = createInstalled("scm-mail-plugin");
|
||||||
|
when(mailPlugin.getDirectory()).thenReturn(temp);
|
||||||
|
|
||||||
|
when(loader.getInstalledPlugins()).thenReturn(singletonList(mailPlugin));
|
||||||
|
|
||||||
|
manager.uninstall("scm-mail-plugin", false);
|
||||||
|
|
||||||
|
assertThat(temp.resolve("uninstall")).exists();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@@ -350,6 +389,11 @@ class DefaultPluginManagerTest {
|
|||||||
assertThrows(AuthorizationException.class, () -> manager.install("test", false));
|
assertThrows(AuthorizationException.class, () -> manager.install("test", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowAuthorizationExceptionsForUninstallMethod() {
|
||||||
|
assertThrows(AuthorizationException.class, () -> manager.uninstall("test", false));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldThrowAuthorizationExceptionsForInstallPendingAndRestart() {
|
void shouldThrowAuthorizationExceptionsForInstallPendingAndRestart() {
|
||||||
assertThrows(AuthorizationException.class, () -> manager.installPendingAndRestart());
|
assertThrows(AuthorizationException.class, () -> manager.installPendingAndRestart());
|
||||||
|
|||||||
Reference in New Issue
Block a user