diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8fd79db9..5421312a13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased +### Fixed +- Fix plugin installation error if previously a plugin was installed with the same dependency which is still pending. ([#1300](https://github.com/scm-manager/scm-manager/pull/1300)) + ## [2.4.0] - 2020-08-14 ### Added - Introduced merge detection for receive hooks ([#1278](https://github.com/scm-manager/scm-manager/pull/1278)) diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java index 0e1e044e83..b53d715ef6 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/DefaultPluginManager.java @@ -86,7 +86,11 @@ public class DefaultPluginManager implements PluginManager { if (contextFactory != null) { this.contextFactory = contextFactory; } else { - this.contextFactory = (availablePlugins -> PluginInstallationContext.from(getInstalled(), availablePlugins)); + this.contextFactory = (plugins -> { + List pendingPlugins = new ArrayList<>(plugins); + pendingInstallQueue.stream().map(PendingPluginInstallation::getPlugin).forEach(pendingPlugins::add); + return PluginInstallationContext.from(getInstalled(), pendingPlugins); + }); } this.computeInstallationDependencies(); diff --git a/scm-webapp/src/test/java/sonia/scm/plugin/DefaultPluginManagerTest.java b/scm-webapp/src/test/java/sonia/scm/plugin/DefaultPluginManagerTest.java index 977451ca3a..d52bd6e51e 100644 --- a/scm-webapp/src/test/java/sonia/scm/plugin/DefaultPluginManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/plugin/DefaultPluginManagerTest.java @@ -37,7 +37,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.NotFoundException; @@ -90,6 +89,9 @@ class DefaultPluginManagerTest { @Captor private ArgumentCaptor eventCaptor; + @Captor + private ArgumentCaptor contextCaptor; + private DefaultPluginManager manager; @Mock @@ -624,8 +626,31 @@ class DefaultPluginManagerTest { assertThat(eventCaptor.getValue().getPlugin()).isEqualTo(review); } - } + @Test + void contextShouldContainAvailablePluginsAndPendingInstallationPlugins() { + DefaultPluginManager manager = new DefaultPluginManager( + loader, center, installer, restarter, eventBus, null + ); + AvailablePlugin jenkins = createAvailable("scm-jenkins-plugin"); + AvailablePlugin webhook = createAvailable("scm-webhook-plugin"); + when(jenkins.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-el-plugin")); + when(webhook.getDescriptor().getDependencies()).thenReturn(ImmutableSet.of("scm-el-plugin")); + AvailablePlugin el = createAvailable("scm-el-plugin"); + when(center.getAvailable()).thenReturn(ImmutableSet.of(jenkins, el, webhook)); + + manager.install("scm-jenkins-plugin", false); + manager.install("scm-webhook-plugin", false); + + verify(installer, times(3)).install(contextCaptor.capture(), any()); + + PluginInstallationContext pluginInstallationContext = contextCaptor.getAllValues().get(2); + + assertThat(pluginInstallationContext.find("scm-jenkins-plugin")).isPresent(); + assertThat(pluginInstallationContext.find("scm-webhook-plugin")).isPresent(); + assertThat(pluginInstallationContext.find("scm-el-plugin")).isPresent(); + } + } @Nested class WithoutReadPermissions {