From ba3fda07efca889e03207ddf8312079a97b1cbe7 Mon Sep 17 00:00:00 2001 From: Pierre Beitz Date: Tue, 6 Apr 2021 17:44:09 +0200 Subject: [PATCH 1/3] Fixes #316: When resolving dependencies using manifest, do not fail if an optional plugin cannot be retrieved --- .../tools/pluginmanager/impl/PluginManager.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java index 59fb61a3..0375c333 100644 --- a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java +++ b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java @@ -906,12 +906,19 @@ public List resolveDependenciesFromManifest(Plugin plugin) { String pluginName = pluginInfo[0]; String pluginVersion = pluginInfo[1]; Plugin dependentPlugin = new Plugin(pluginName, pluginVersion, null, null); + dependentPlugin.setOptional(dependency.contains("resolution:=optional")); + if (useLatestSpecified && plugin.isLatest() || useLatestAll) { - VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, pluginName); - dependentPlugin.setVersion(latestPluginVersion); - dependentPlugin.setLatest(true); + try { + VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, pluginName); + dependentPlugin.setVersion(latestPluginVersion); + dependentPlugin.setLatest(true); + } catch(PluginNotFoundException e) { + if (! dependentPlugin.getOptional()) { + throw e; + } + } } - dependentPlugin.setOptional(dependency.contains("resolution:=optional")); dependentPlugins.add(dependentPlugin); dependentPlugin.setParent(plugin); From 8926b6e0449c0e6c146e86e8c314aa2d8fa261f0 Mon Sep 17 00:00:00 2001 From: Pierre Beitz Date: Tue, 6 Apr 2021 17:48:59 +0200 Subject: [PATCH 2/3] Apply suggestions from code review --- .../java/io/jenkins/tools/pluginmanager/impl/PluginManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java index 0375c333..0d88aa80 100644 --- a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java +++ b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java @@ -914,7 +914,7 @@ public List resolveDependenciesFromManifest(Plugin plugin) { dependentPlugin.setVersion(latestPluginVersion); dependentPlugin.setLatest(true); } catch(PluginNotFoundException e) { - if (! dependentPlugin.getOptional()) { + if (!dependentPlugin.getOptional()) { throw e; } } From 6407cf301b71e8fe04aa2749f24bffe936b7e18f Mon Sep 17 00:00:00 2001 From: Pierre Beitz Date: Wed, 7 Apr 2021 16:29:33 +0200 Subject: [PATCH 3/3] Fixes #316: When resolving dependencies using manifest, do not fail if an optional plugin cannot be retrieved --- .../pluginmanager/impl/PluginManager.java | 45 +++++++++++-------- .../pluginmanager/impl/PluginManagerTest.java | 22 ++++++--- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java index 0d88aa80..21c24e5a 100644 --- a/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java +++ b/plugin-management-library/src/main/java/io/jenkins/tools/pluginmanager/impl/PluginManager.java @@ -76,7 +76,7 @@ import static java.util.Comparator.comparing; public class PluginManager implements Closeable { - private static final VersionNumber LATEST = new VersionNumber("latest"); + static final VersionNumber LATEST = new VersionNumber("latest"); private List failedPlugins; /** * Directory where the plugins will be downloaded @@ -835,26 +835,43 @@ public JSONArray getPluginDependencyJsonArray(Plugin plugin, JSONObject ucJson) * Retrieves the latest available version of a specified plugin. * * @param dependendantPlugin the plugin depending on the given plugin - * @param pluginName the name of the plugin + * @param plugin the plugin to resolve the latest version for * @return latest version of the specified plugin * @throws IllegalStateException Update Center JSON has not been retrieved yet */ - public VersionNumber getLatestPluginVersion(Plugin dependendantPlugin, String pluginName) { + public VersionNumber getLatestPluginVersion(Plugin dependendantPlugin, Plugin plugin) { if (latestPlugins == null) { throw new IllegalStateException("List of plugins is not available. Likely Update Center data has not been downloaded yet"); } - if (!latestPlugins.has(pluginName)) { - throw new PluginNotFoundException(dependendantPlugin, String.format("unable to find dependant plugin %s in update center %s", pluginName, + if (!latestPlugins.has(plugin.getName())) { + if (plugin.getOptional()) { + // case where a plugin depends on an optional plugin that is not available in the same Update Center + // we don't care about the version as we won't be able to download the plugin anyway + return LATEST; + } + throw new PluginNotFoundException(dependendantPlugin, String.format("unable to find dependant plugin %s in update center %s", plugin.getName(), jenkinsUcLatest)); } - JSONObject pluginInfo = (JSONObject) latestPlugins.get(pluginName); + JSONObject pluginInfo = (JSONObject) latestPlugins.get(plugin.getName()); String latestPluginVersion = pluginInfo.getString("version"); return new VersionNumber(latestPluginVersion); } + /** + * @deprecated use {@link #getLatestPluginVersion(Plugin, Plugin)} instead + * @param dependendantPlugin the plugin depending on the given plugin + * @param pluginName the name of the plugin + * @return latest version of the specified plugin + * @throws IllegalStateException Update Center JSON has not been retrieved yet + */ + @Deprecated + public VersionNumber getLatestPluginVersion(Plugin dependendantPlugin, String pluginName) { + return getLatestPluginVersion(dependendantPlugin, new Plugin(pluginName,null, null, null)); + } + /** * Resolves direct dependencies from downloaded plugin manifest. Done for plugins in which dependencies can't be * determined via easily via json, such as when a user downloads a plugin directly from url or incremental plugins, @@ -907,19 +924,11 @@ public List resolveDependenciesFromManifest(Plugin plugin) { String pluginVersion = pluginInfo[1]; Plugin dependentPlugin = new Plugin(pluginName, pluginVersion, null, null); dependentPlugin.setOptional(dependency.contains("resolution:=optional")); - if (useLatestSpecified && plugin.isLatest() || useLatestAll) { - try { - VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, pluginName); - dependentPlugin.setVersion(latestPluginVersion); - dependentPlugin.setLatest(true); - } catch(PluginNotFoundException e) { - if (!dependentPlugin.getOptional()) { - throw e; - } - } + VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, dependentPlugin); + dependentPlugin.setVersion(latestPluginVersion); + dependentPlugin.setLatest(true); } - dependentPlugins.add(dependentPlugin); dependentPlugin.setParent(plugin); } @@ -966,7 +975,7 @@ public List resolveDependenciesFromJson(Plugin plugin, JSONObject plugin try { if (useLatestSpecified && plugin.isLatest() || useLatestAll) { - VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, pluginName); + VersionNumber latestPluginVersion = getLatestPluginVersion(plugin, dependentPlugin); dependentPlugin.setVersion(latestPluginVersion); dependentPlugin.setLatest(true); } diff --git a/plugin-management-library/src/test/java/io/jenkins/tools/pluginmanager/impl/PluginManagerTest.java b/plugin-management-library/src/test/java/io/jenkins/tools/pluginmanager/impl/PluginManagerTest.java index 1feceb1a..def15062 100644 --- a/plugin-management-library/src/test/java/io/jenkins/tools/pluginmanager/impl/PluginManagerTest.java +++ b/plugin-management-library/src/test/java/io/jenkins/tools/pluginmanager/impl/PluginManagerTest.java @@ -711,20 +711,30 @@ public void getPluginVersionTest() { public void getLatestPluginVersionExceptionTest() { setTestUcJson(); - assertThatThrownBy(() -> pm.getLatestPluginVersion(null, "git")) + assertThatThrownBy(() -> pm.getLatestPluginVersion(null, new Plugin("git", null, null, null))) .isInstanceOf(PluginNotFoundException.class); } @Test public void getLatestPluginTest() { setTestUcJson(); - VersionNumber antLatestVersion = pm.getLatestPluginVersion(null, "ant"); + VersionNumber antLatestVersion = pm.getLatestPluginVersion(null, new Plugin("ant", null, null, null)); assertThat(antLatestVersion).hasToString("1.9"); - VersionNumber amazonEcsLatestVersion = pm.getLatestPluginVersion(null, "amazon-ecs"); + VersionNumber amazonEcsLatestVersion = pm.getLatestPluginVersion(null, new Plugin("amazon-ecs", null, null, null)); assertThat(amazonEcsLatestVersion).hasToString("1.20"); } + @Test + public void getLatestOptionalAbsentPluginTest() { + setTestUcJson(); + + Plugin absentPlugin = new Plugin("git", null, null, null); + absentPlugin.setOptional(true); + VersionNumber absentPluginVersion = pm.getLatestPluginVersion(null, absentPlugin); + assertThat(absentPluginVersion).isEqualByComparingTo(PluginManager.LATEST); + } + @Test public void resolveDependenciesFromManifestLatestSpecified() { Config config = Config.builder() @@ -748,7 +758,7 @@ public void resolveDependenciesFromManifestLatestSpecified() { .when(pluginManagerSpy).getAttributeFromManifest(any(File.class), any(String.class)); doReturn(new VersionNumber("2.4")).doReturn(new VersionNumber("2.20")).when(pluginManagerSpy). - getLatestPluginVersion(any(Plugin.class), any(String.class)); + getLatestPluginVersion(any(Plugin.class), any(Plugin.class)); List actualPlugins = pluginManagerSpy.resolveDependenciesFromManifest(testPlugin); @@ -777,7 +787,7 @@ public void resolveDependenciesFromManifestLatestAll() { .when(pluginManagerSpy).getAttributeFromManifest(any(File.class), any(String.class)); doReturn(new VersionNumber("2.4")).doReturn(new VersionNumber("2.20")).when(pluginManagerSpy). - getLatestPluginVersion(any(Plugin.class), any(String.class)); + getLatestPluginVersion(any(Plugin.class), any(Plugin.class)); List actualPlugins = pluginManagerSpy.resolveDependenciesFromManifest(testPlugin); @@ -985,7 +995,7 @@ public void resolveDependenciesFromJsonLatestAll() { doReturn(mavenInvokerDependencies).when(pluginManagerSpy).getPluginDependencyJsonArray(any(Plugin.class), any(JSONObject.class)); doReturn(new VersionNumber("2.44")).doReturn(new VersionNumber("2.30")).doReturn(new VersionNumber("1.18")) .doReturn(new VersionNumber("2.0")).doReturn(new VersionNumber("1.8")) - .when(pluginManagerSpy).getLatestPluginVersion(any(Plugin.class), any(String.class)); + .when(pluginManagerSpy).getLatestPluginVersion(any(Plugin.class), any(Plugin.class)); List actualPlugins = pluginManagerSpy.resolveDependenciesFromJson(mvnInvokerPlugin, pluginJson);