mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 07:25:44 +01:00
cancel all pending installations, if a dependency failed to install
This commit is contained in:
@@ -43,6 +43,7 @@ import sonia.scm.NotFoundException;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -99,7 +100,7 @@ public class DefaultPluginManager implements PluginManager {
|
||||
}
|
||||
|
||||
private <T extends Plugin> Predicate<T> filterByName(String name) {
|
||||
return (plugin) -> name.equals(plugin.getDescriptor().getInformation().getName());
|
||||
return plugin -> name.equals(plugin.getDescriptor().getInformation().getName());
|
||||
}
|
||||
|
||||
private boolean isNotInstalled(AvailablePlugin availablePlugin) {
|
||||
@@ -108,18 +109,42 @@ public class DefaultPluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void install(String name) {
|
||||
if (getInstalled(name).isPresent()){
|
||||
LOG.info("plugin {} is already installed, skipping installation", name);
|
||||
return;
|
||||
}
|
||||
AvailablePlugin plugin = getAvailable(name).orElseThrow(() -> NotFoundException.notFound(entity(AvailablePlugin.class, name)));
|
||||
Set<String> dependencies = plugin.getDescriptor().getDependencies();
|
||||
if (dependencies != null) {
|
||||
for (String dependency: dependencies){
|
||||
install(dependency);
|
||||
List<AvailablePlugin> plugins = collectPluginsToInstall(name);
|
||||
List<PendingPluginInstallation> pendingInstallations = new ArrayList<>();
|
||||
for (AvailablePlugin plugin : plugins) {
|
||||
try {
|
||||
PendingPluginInstallation pending = installer.install(plugin);
|
||||
pendingInstallations.add(pending);
|
||||
} catch (PluginInstallException ex) {
|
||||
cancelPending(pendingInstallations);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
installer.install(plugin);
|
||||
private void cancelPending(List<PendingPluginInstallation> pendingInstallations) {
|
||||
pendingInstallations.forEach(PendingPluginInstallation::cancel);
|
||||
}
|
||||
|
||||
private List<AvailablePlugin> collectPluginsToInstall(String name) {
|
||||
List<AvailablePlugin> plugins = new ArrayList<>();
|
||||
collectPluginsToInstall(plugins, name);
|
||||
return plugins;
|
||||
}
|
||||
private void collectPluginsToInstall(List<AvailablePlugin> plugins, String name) {
|
||||
if (!getInstalled(name).isPresent()) {
|
||||
AvailablePlugin plugin = getAvailable(name).orElseThrow(() -> NotFoundException.notFound(entity(AvailablePlugin.class, name)));
|
||||
|
||||
Set<String> dependencies = plugin.getDescriptor().getDependencies();
|
||||
if (dependencies != null) {
|
||||
for (String dependency: dependencies){
|
||||
collectPluginsToInstall(plugins, dependency);
|
||||
}
|
||||
}
|
||||
|
||||
plugins.add(plugin);
|
||||
} else {
|
||||
LOG.info("plugin {} is already installed, skipping installation", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -153,6 +154,29 @@ class DefaultPluginManagerTest {
|
||||
verify(installer).install(review);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRollbackOnFailedInstallation() {
|
||||
AvailablePlugin review = createAvailable("scm-review-plugin");
|
||||
when(review.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-mail-plugin"));
|
||||
AvailablePlugin mail = createAvailable("scm-mail-plugin");
|
||||
when(mail.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-notification-plugin"));
|
||||
AvailablePlugin notification = createAvailable("scm-notification-plugin");
|
||||
when(center.getAvailable()).thenReturn(ImmutableSet.of(review, mail, notification));
|
||||
|
||||
PendingPluginInstallation pendingNotification = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingNotification).when(installer).install(notification);
|
||||
|
||||
PendingPluginInstallation pendingMail = mock(PendingPluginInstallation.class);
|
||||
doReturn(pendingMail).when(installer).install(mail);
|
||||
|
||||
doThrow(new PluginChecksumMismatchException("checksum does not match")).when(installer).install(review);
|
||||
|
||||
assertThrows(PluginInstallException.class, () -> manager.install("scm-review-plugin"));
|
||||
|
||||
verify(pendingNotification).cancel();
|
||||
verify(pendingMail).cancel();
|
||||
}
|
||||
|
||||
private AvailablePlugin createAvailable(String name) {
|
||||
PluginInformation information = new PluginInformation();
|
||||
information.setName(name);
|
||||
|
||||
Reference in New Issue
Block a user