From 65da3cc710710f7d41152cb27ff6976da084e0de Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 11 Aug 2020 09:46:00 +0200 Subject: [PATCH] Fix duplicate plugins in the plugin tree after update --- .../java/sonia/scm/plugin/ExplodedSmp.java | 20 +++++++ .../sonia/scm/plugin/PluginProcessor.java | 10 +++- .../sonia/scm/plugin/PluginProcessorTest.java | 56 +++++++++++++------ .../scm/plugin/scm-mail-plugin-2-0-0.xml | 43 ++++++++++++++ .../scm/plugin/scm-mail-plugin-2-1-0.xml | 43 ++++++++++++++ .../scm/plugin/scm-review-plugin-2-0-0.xml | 47 ++++++++++++++++ .../scm/plugin/scm-review-plugin-2-1-0.xml | 47 ++++++++++++++++ 7 files changed, 247 insertions(+), 19 deletions(-) create mode 100644 scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-0-0.xml create mode 100644 scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-1-0.xml create mode 100644 scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-0-0.xml create mode 100644 scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-1-0.xml diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/ExplodedSmp.java b/scm-webapp/src/main/java/sonia/scm/plugin/ExplodedSmp.java index 2b2aebd00b..777c4a11d9 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/ExplodedSmp.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/ExplodedSmp.java @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.file.Path; +import java.util.Objects; //~--- JDK imports ------------------------------------------------------------ @@ -105,6 +106,25 @@ public final class ExplodedSmp return plugin; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ExplodedSmp that = (ExplodedSmp) o; + return path.equals(that.path); + } + + @Override + public int hashCode() { + return Objects.hash(path); + } + + @Override + public String toString() { + PluginInformation information = plugin.getInformation(); + return information.getName() + "@" + information.getVersion() + " (" + path + ")"; + } + //~--- inner classes -------------------------------------------------------- /** diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/PluginProcessor.java b/scm-webapp/src/main/java/sonia/scm/plugin/PluginProcessor.java index 1265a28977..15e12bd6eb 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/PluginProcessor.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/PluginProcessor.java @@ -190,8 +190,14 @@ public final class PluginProcessor return ImmutableSet.copyOf(wrappers); } - private ImmutableSet concat(Set installedPlugins, Set newlyInstalledPlugins) { - return ImmutableSet.builder().addAll(installedPlugins).addAll(newlyInstalledPlugins).build(); + private Set concat(Set installedPlugins, Set newlyInstalledPlugins) { + // We first add all newly installed plugins, + // after that we add the missing plugins, which are already installed. + // ExplodedSmp is equal by its path, so duplicates (updates) are not in the result. + return ImmutableSet.builder() + .addAll(newlyInstalledPlugins) + .addAll(installedPlugins) + .build(); } private Set installPending(Set installedPlugins) throws IOException { diff --git a/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java b/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java index e78fc1db77..5ee975a275 100644 --- a/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java +++ b/scm-webapp/src/test/java/sonia/scm/plugin/PluginProcessorTest.java @@ -30,7 +30,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.io.Resources; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -38,26 +37,22 @@ import org.junit.rules.TemporaryFolder; import sonia.scm.lifecycle.classloading.ClassLoaderLifeCycle; import javax.xml.bind.JAXB; - -import static org.hamcrest.Matchers.*; - -import static org.junit.Assert.*; - -//~--- JDK imports ------------------------------------------------------------ - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; - import java.lang.reflect.InvocationTargetException; - import java.net.URL; - import java.util.Set; +import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -100,7 +95,7 @@ public class PluginProcessorTest new PluginResource("sonia/scm/plugin/scm-f-plugin-1.0.1.smp", "scm-f-plugin.smp", "scm-f-plugin:1.0.1"); - private static final String PLUGIN_G = "sonia/scm/plugin/scm-g-plugin.xml"; + private static final String PLUGIN_G = "scm-g-plugin.xml"; private static final String PLUGIN_H = "sonia/scm/plugin/scm-h-plugin.xml"; private static final String PLUGIN_I = "sonia/scm/plugin/scm-i-plugin.xml"; @@ -108,21 +103,34 @@ public class PluginProcessorTest @Test(expected = PluginConditionFailedException.class) public void testFailedPluginCondition() throws IOException { - createPlugin(PLUGIN_G); + createPendingPluginInstallation(PLUGIN_G); collectPlugins(); } @Test(expected = DependencyVersionMismatchException.class) public void testWrongVersionOfDependency() throws IOException { - createPlugin(PLUGIN_H); - createPlugin(PLUGIN_I); + createPendingPluginInstallation(PLUGIN_H); + createPendingPluginInstallation(PLUGIN_I); collectPlugins(); } + @Test + public void shouldNotContainDuplicatesOnUpdate() throws IOException { + createInstalledPlugin("scm-mail-plugin-2-0-0.xml"); + createInstalledPlugin("scm-review-plugin-2-0-0.xml"); + createPendingPluginInstallation("scm-mail-plugin-2-1-0.xml"); + createPendingPluginInstallation("scm-review-plugin-2-1-0.xml"); + + Set plugins = collectPlugins().stream() + .map(p -> p.getDescriptor().getInformation().getName(true)) + .collect(Collectors.toSet()); + assertThat(plugins, containsInAnyOrder("scm-mail-plugin:2.1.0", "scm-review-plugin:2.1.0")); + } + @SuppressWarnings("UnstableApiUsage") - private void createPlugin(String descriptorResource) throws IOException { - URL resource = Resources.getResource(descriptorResource); + private void createPendingPluginInstallation(String descriptorResource) throws IOException { + URL resource = Resources.getResource("sonia/scm/plugin/" +descriptorResource); InstalledPluginDescriptor descriptor = JAXB.unmarshal(resource, InstalledPluginDescriptor.class); File file = new File(pluginDirectory, descriptor.getInformation().getName() + ".smp"); @@ -133,6 +141,20 @@ public class PluginProcessorTest } } + @SuppressWarnings("UnstableApiUsage") + private void createInstalledPlugin(String descriptorResource) throws IOException { + URL resource = Resources.getResource("sonia/scm/plugin/" + descriptorResource); + InstalledPluginDescriptor descriptor = JAXB.unmarshal(resource, InstalledPluginDescriptor.class); + + File directory = new File(pluginDirectory, descriptor.getInformation().getName()); + File scmDirectory = new File(directory, "META-INF" + File.separator + "scm"); + assertTrue(scmDirectory.mkdirs()); + + try (OutputStream output = new FileOutputStream(new File(scmDirectory, "plugin.xml"))) { + Resources.copy(resource, output); + } + } + /** * Method description diff --git a/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-0-0.xml b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-0-0.xml new file mode 100644 index 0000000000..bf148adaac --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-0-0.xml @@ -0,0 +1,43 @@ + + + + + 2 + + + sonia.scm.plugins + scm-mail-plugin + 2.0.0 + scm-mail-plugin + The awesome mail plugin + + + + sonia.scm.plugins + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-1-0.xml b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-1-0.xml new file mode 100644 index 0000000000..f642b1e65d --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-mail-plugin-2-1-0.xml @@ -0,0 +1,43 @@ + + + + + 2 + + + sonia.scm.plugins + scm-mail-plugin + 2.1.0 + scm-mail-plugin + The awesome mail plugin + + + + sonia.scm.plugins + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-0-0.xml b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-0-0.xml new file mode 100644 index 0000000000..43517a4f47 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-0-0.xml @@ -0,0 +1,47 @@ + + + + + 2 + + + sonia.scm.plugins + scm-review-plugin + 2.0.0 + scm-review-plugin + The awesome review plugin + + + + sonia.scm.plugins + + + + scm-mail-plugin + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-1-0.xml b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-1-0.xml new file mode 100644 index 0000000000..4feab0b7c4 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/plugin/scm-review-plugin-2-1-0.xml @@ -0,0 +1,47 @@ + + + + + 2 + + + sonia.scm.plugins + scm-review-plugin + 2.1.0 + scm-review-plugin + The awesome review plugin + + + + sonia.scm.plugins + + + + scm-mail-plugin + + +