diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java index 3084ef796f..e46014f1a9 100644 --- a/core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/core/src/main/java/hudson/ClassicPluginStrategy.java @@ -186,6 +186,10 @@ public class ClassicPluginStrategy implements PluginStrategy { } catch (InvalidPathException e) { throw new IOException(e); } + String canonicalName = manifest.getMainAttributes().getValue("Short-Name") + ".jpi"; + if (!archive.getName().equals(canonicalName)) { + LOGGER.warning(() -> "encountered " + archive + " under a nonstandard name; expected " + canonicalName); + } } final Attributes atts = manifest.getMainAttributes(); diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 266f7b48fa..ec4bd4b503 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -601,7 +601,7 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas } void considerDetachedPlugin(String shortName) { - if (new File(rootDir, shortName + ".jpi").isFile()) { + if (new File(rootDir, shortName + ".jpi").isFile() || new File(rootDir, shortName + ".hpi").isFile()) { LOGGER.fine(() -> "not considering loading a detached dependency " + shortName + " as it is already on disk"); return; } diff --git a/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java b/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java index f81549e85b..c5c51ddcc0 100644 --- a/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java +++ b/test/src/test/java/jenkins/install/LoadDetachedPluginsTest.java @@ -184,6 +184,20 @@ public class LoadDetachedPluginsTest { assertEquals(expectedPlugin, pw.getShortName()); } + @Issue("JENKINS-55582") + @LocalData + @Test + public void nonstandardFilenames() { + logging.record(PluginManager.class, Level.FINE).record(ClassicPluginStrategy.class, Level.FINE); + rr.then(r -> { + assertTrue(r.jenkins.pluginManager.getPlugin("build-token-root").isActive()); + assertEquals("1.2", r.jenkins.pluginManager.getPlugin("jdk-tool").getVersion()); + /* TODO currently still loads the detached 1.0, since we only skip $shortName.[jh]pi not $shortName-$version.[jh]pi; during PLUGINS_LISTED there is a list of known filenames but not short names + assertEquals("1.3", r.jenkins.pluginManager.getPlugin("command-launcher").getVersion()); + */ + }); + } + private List getInstalledDetachedPlugins(JenkinsRule r, List detachedPlugins) { PluginManager pluginManager = r.jenkins.getPluginManager(); List installedPlugins = new ArrayList<>(); diff --git a/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/build-token-root.jpi b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/build-token-root.jpi new file mode 100644 index 0000000000..17e86dc61c Binary files /dev/null and b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/build-token-root.jpi differ diff --git a/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/command-launcher-1.3.hpi b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/command-launcher-1.3.hpi new file mode 100644 index 0000000000..9d36607ee6 Binary files /dev/null and b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/command-launcher-1.3.hpi differ diff --git a/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/jdk-tool.hpi b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/jdk-tool.hpi new file mode 100644 index 0000000000..3b32e40170 Binary files /dev/null and b/test/src/test/resources/jenkins/install/LoadDetachedPluginsTest/nonstandardFilenames/plugins/jdk-tool.hpi differ