msrb pushed to jenkins (master). "Migrate to plugins containing symlinks"

notifications at fedoraproject.org notifications at fedoraproject.org
Thu Apr 16 06:36:59 UTC 2015


>From 6136db2d08f638c0093bb77ea101001213ee9c98 Mon Sep 17 00:00:00 2001
From: Michal Srb <msrb at redhat.com>
Date: Thu, 16 Apr 2015 08:36:26 +0200
Subject: Migrate to plugins containing symlinks


diff --git a/add-support-for-plugins-from-RPMs.patch b/add-support-for-plugins-from-RPMs.patch
deleted file mode 100644
index cb9b263..0000000
--- a/add-support-for-plugins-from-RPMs.patch
+++ /dev/null
@@ -1,322 +0,0 @@
-diff --git a/core/src/main/java/hudson/LocalPluginManager.java b/core/src/main/java/hudson/LocalPluginManager.java
-index 4cfbf6a..ceaaf7f 100644
---- a/core/src/main/java/hudson/LocalPluginManager.java
-+++ b/core/src/main/java/hudson/LocalPluginManager.java
-@@ -27,9 +27,11 @@ package hudson;
- import jenkins.model.Jenkins;
- 
- import javax.servlet.ServletContext;
-+
- import java.io.File;
- import java.io.IOException;
- import java.net.URL;
-+import java.nio.file.Paths;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashSet;
-@@ -69,12 +71,13 @@ public class LocalPluginManager extends PluginManager {
-         ServletContext context = Jenkins.getInstance().servletContext;
- 
-         for( String path : Util.fixNull((Set<String>)context.getResourcePaths("/WEB-INF/plugins"))) {
--            String fileName = path.substring(path.lastIndexOf('/')+1);
--            if(fileName.length()==0) {
--                // see http://www.nabble.com/404-Not-Found-error-when-clicking-on-help-td24508544.html
--                // I suspect some containers are returning directory names.
--                continue;
--            }
-+//            String fileName = path.substring(path.lastIndexOf('/')+1);
-+//            if(fileName.length()==0) {
-+//                // see http://www.nabble.com/404-Not-Found-error-when-clicking-on-help-td24508544.html
-+//                // I suspect some containers are returning directory names.
-+//                continue;
-+//            }
-+            String fileName = Paths.get(path).getFileName().toString();
-             try {
-                 names.add(fileName);
- 
-diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java
-index 41605ee..8fc9ccd 100644
---- a/core/src/main/java/hudson/PluginManager.java
-+++ b/core/src/main/java/hudson/PluginManager.java
-@@ -53,6 +53,7 @@ import jenkins.model.Jenkins;
- import jenkins.util.io.OnMaster;
- import net.sf.json.JSONArray;
- import net.sf.json.JSONObject;
-+
- import org.apache.commons.fileupload.FileItem;
- import org.apache.commons.fileupload.disk.DiskFileItemFactory;
- import org.apache.commons.fileupload.servlet.ServletFileUpload;
-@@ -81,13 +82,18 @@ import javax.servlet.ServletException;
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.parsers.SAXParserFactory;
- import java.io.Closeable;
-+
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.WeakReference;
- import java.lang.reflect.Method;
-+import java.net.URISyntaxException;
- import java.net.URL;
- import java.net.URLClassLoader;
-+import java.nio.file.Files;
-+import java.nio.file.Path;
-+import java.nio.file.Paths;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
-@@ -108,6 +114,7 @@ import java.util.jar.JarFile;
- import java.util.jar.Manifest;
- import java.util.logging.Level;
- import java.util.logging.Logger;
-+
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
-@@ -116,6 +123,7 @@ import static hudson.init.InitMilestone.*;
- import hudson.model.DownloadService;
- import hudson.util.FormValidation;
- import static java.util.logging.Level.WARNING;
-+
- import org.kohsuke.accmod.Restricted;
- import org.kohsuke.accmod.restrictions.NoExternalUse;
- 
-@@ -143,6 +151,9 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
-      */
-     public final File rootDir;
- 
-+    // FIXME: pass this location to Jenkins via system property
-+    private final File rpmRootDir = new File("/usr/share/jenkins/plugins/");
-+
-     /**
-      * @deprecated as of 1.355
-      *      {@link PluginManager} can now live longer than {@link jenkins.model.Jenkins} instance, so
-@@ -211,6 +222,47 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
-         return new Api(this);
-     }
- 
-+    private void symlinkRpmPlugins() {
-+        if (!rpmRootDir.exists()) {
-+            return;
-+        }
-+
-+        File[] rpmPluginDirs = rpmRootDir.listFiles();
-+        File[] currentPlugins = rootDir.listFiles();
-+        boolean isAlreadyInstalled = false;
-+
-+        for (File rpmPlugin : rpmPluginDirs) {
-+            if (rpmPlugin.isDirectory()) {
-+                for (File plugin : currentPlugins) {
-+                    // remove broken symlinks from $JENKINS_HOME/plugins/
-+                    if (Files.isSymbolicLink(plugin.toPath())) {
-+                        if (Files.notExists(plugin.toPath())) {
-+                            LOGGER.info("Removing broken symbolic link from plugins directory: " + plugin);
-+                            plugin.delete();
-+                        }
-+                    }
-+                    if (rpmPlugin.getName().equals(plugin.getName()) || plugin.getName().equals(rpmPlugin.getName() + ".jpi")) {
-+                        LOGGER.info(rpmPlugin.getName() + " already exists in plugin directory, skipping");
-+                        isAlreadyInstalled = true;
-+                        break;
-+                    }
-+                }
-+                if (!isAlreadyInstalled) {
-+                    Path link = Paths.get(rootDir.getPath(), rpmPlugin.getName() + ".jpi");
-+                    Path target = Paths.get(rpmPlugin.getPath());
-+                    try {
-+                        Files.createSymbolicLink(link, target);
-+                    } catch (IOException e) {
-+                        LOGGER.info(e.toString());
-+                    }
-+                }
-+                isAlreadyInstalled = false;
-+            } else {
-+                LOGGER.info(rpmRootDir + rpmPlugin.getName() + " is not a directory, ignoring");
-+            }
-+        }
-+    }
-+
-     /**
-      * Called immediately after the construction.
-      * This is a separate method so that code executed from here will see a valid value in
-@@ -218,6 +270,9 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
-      */
-     public TaskBuilder initTasks(final InitStrategy initStrategy) {
-         TaskBuilder builder;
-+
-+        symlinkRpmPlugins();
-+
-         if (!pluginListed) {
-             builder = new TaskGraphBuilder() {
-                 List<File> archives;
-@@ -537,8 +592,24 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas
-         //  - no file exists today
-         //  - bundled version and current version differs (by timestamp), and the file isn't pinned.
-         if (!file.exists() || (file.lastModified() != lastModified && !pinFile.exists())) {
--            FileUtils.copyURLToFile(src, file);
--            file.setLastModified(src.openConnection().getLastModified());
-+            Path sourcePath = null;
-+            try {
-+                sourcePath = Paths.get(src.toURI());
-+            } catch (URISyntaxException e) {
-+                throw new IOException(e);
-+            }
-+            Path linkPath = Paths.get(rootDir.getAbsolutePath(), fileName);
-+            if (Files.isDirectory(sourcePath)) {
-+                if (Files.isDirectory(linkPath)) {
-+                    FileUtils.deleteDirectory(linkPath.toFile());
-+                } else if (Files.exists(linkPath)) {
-+                    Files.delete(linkPath);
-+                }
-+                Files.createSymbolicLink(linkPath, sourcePath);
-+            } else {
-+                FileUtils.copyURLToFile(src, file);
-+                file.setLastModified(src.openConnection().getLastModified());
-+            }
-             // lastModified is set for two reasons:
-             // - to avoid unpacking as much as possible, but still do it on both upgrade and downgrade
-             // - to make sure the value is not changed after each restart, so we can avoid
-diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java
-index aa683e6..2de708a 100644
---- a/core/src/main/java/hudson/PluginWrapper.java
-+++ b/core/src/main/java/hudson/PluginWrapper.java
-@@ -34,15 +34,22 @@ import hudson.model.UpdateSite;
- import hudson.util.VersionNumber;
- 
- import java.io.File;
-+import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
-+import java.io.InputStream;
- import java.io.OutputStream;
- import java.io.Closeable;
- import java.net.URL;
-+import java.nio.file.Files;
-+import java.nio.file.Path;
-+import java.nio.file.Paths;
- import java.util.ArrayList;
- import java.util.List;
-+import java.util.jar.Attributes;
- import java.util.jar.Manifest;
- import java.util.logging.Logger;
-+
- import static java.util.logging.Level.WARNING;
- import static org.apache.commons.io.FilenameUtils.getBaseName;
- import org.apache.commons.lang.StringUtils;
-@@ -56,6 +63,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
- import java.util.Enumeration;
- import java.util.jar.JarFile;
- import java.util.logging.Level;
-+
- import javax.annotation.CheckForNull;
- 
- /**
-@@ -431,6 +439,13 @@ public class PluginWrapper implements Comparable<PluginWrapper>, ModelObject {
-         return isBundled;
-     }
- 
-+    public boolean isFromRPM() {
-+        if (Files.isSymbolicLink(archive.toPath())) {
-+            return true;
-+        }
-+        return false;
-+    }
-+
-     /**
-      * If true, the plugin is going to be activated next time
-      * Jenkins runs.
-@@ -565,13 +580,27 @@ public class PluginWrapper implements Comparable<PluginWrapper>, ModelObject {
-     @Exported
-     public String getBackupVersion() {
-         File backup = getBackupFile();
-+        Path backupPath = Paths.get(backup.toURI());
-         if (backup.exists()) {
-             try {
--                JarFile backupPlugin = new JarFile(backup);
--                try {
--                    return backupPlugin.getManifest().getMainAttributes().getValue("Plugin-Version");
--                } finally {
--                    backupPlugin.close();
-+                if (!Files.isDirectory(backupPath)) {
-+
-+                    JarFile backupPlugin = new JarFile(backup);
-+                    try {
-+                        return backupPlugin.getManifest().getMainAttributes().getValue("Plugin-Version");
-+                    } finally {
-+                        backupPlugin.close();
-+                    }
-+
-+                } else {
-+                    InputStream is = new FileInputStream(new File(backup, "META-INF/MANIFEST.MF"));
-+                    Manifest manifest = new Manifest(is);
-+                    Attributes attributes = manifest.getMainAttributes();
-+                    try {
-+                        return attributes.getValue("Plugin-Version");
-+                    } finally {
-+                        is.close();
-+                    }
-                 }
-             } catch (IOException e) {
-                 LOGGER.log(WARNING, "Failed to get backup version from " + backup, e);
-diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java
-index f5aecb5..12a2bb1 100644
---- a/core/src/main/java/hudson/model/UpdateCenter.java
-+++ b/core/src/main/java/hudson/model/UpdateCenter.java
-@@ -52,8 +52,10 @@ import hudson.util.XStream2;
- import jenkins.RestartRequiredException;
- import jenkins.model.Jenkins;
- import jenkins.util.io.OnMaster;
-+
- import org.acegisecurity.Authentication;
- import org.acegisecurity.context.SecurityContext;
-+import org.apache.commons.io.FileUtils;
- import org.apache.commons.io.input.CountingInputStream;
- import org.apache.commons.io.output.NullOutputStream;
- import org.jvnet.localizer.Localizable;
-@@ -63,6 +65,7 @@ import org.kohsuke.stapler.StaplerResponse;
- 
- import javax.net.ssl.SSLHandshakeException;
- import javax.servlet.ServletException;
-+
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
-@@ -89,7 +92,9 @@ import java.util.jar.Attributes;
- import java.util.jar.JarFile;
- import java.util.logging.Level;
- import java.util.logging.Logger;
-+
- import javax.annotation.CheckForNull;
-+
- import org.acegisecurity.context.SecurityContextHolder;
- import org.kohsuke.accmod.Restricted;
- import org.kohsuke.accmod.restrictions.NoExternalUse;
-@@ -1427,6 +1432,9 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
-             if(!backup.renameTo(dst)) {
-                 throw new IOException("Failed to rename "+backup+" to "+dst);
-             }
-+            // remove old unpacked version
-+            File baseDir = pm.rootDir;
-+            FileUtils.deleteQuietly(new File(baseDir, plugin.name));
-         }
- 
-         protected void onSuccess() {
-diff --git a/core/src/main/resources/hudson/PluginManager/installed.jelly b/core/src/main/resources/hudson/PluginManager/installed.jelly
-index 2d439b3..ef14603 100644
---- a/core/src/main/resources/hudson/PluginManager/installed.jelly
-+++ b/core/src/main/resources/hudson/PluginManager/installed.jelly
-@@ -112,9 +112,11 @@ THE SOFTWARE.
-                         <p>${%Uninstallation pending}</p>
-                       </j:when>
-                       <j:when test="${!p.isBundled()}">
--                        <form method="post" action="plugin/${p.shortName}/uninstall">
--                          <input type="submit" value="${%Uninstall}"/>
--                        </form>
-+                        <j:when test="${!p.isFromRPM()}">
-+                          <form method="post" action="plugin/${p.shortName}/uninstall">
-+                            <input type="submit" value="${%Uninstall}"/>
-+                          </form>
-+                        </j:when>
-                       </j:when>
-                     </j:choose>
-                   </td>
diff --git a/hpi-unpack-temp-hack.patch b/hpi-unpack-temp-hack.patch
new file mode 100644
index 0000000..3dd009e
--- /dev/null
+++ b/hpi-unpack-temp-hack.patch
@@ -0,0 +1,26 @@
+diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java
+index 727bdd7..98b74d9 100644
+--- a/core/src/main/java/hudson/ClassicPluginStrategy.java
++++ b/core/src/main/java/hudson/ClassicPluginStrategy.java
+@@ -590,15 +590,12 @@ public class ClassicPluginStrategy implements PluginStrategy {
+     }
+ 
+     private static void unzipExceptClasses(File archive, File destDir, Project prj) {
+-        Expand e = new Expand();
+-        e.setProject(prj);
+-        e.setTaskType("unzip");
+-        e.setSrc(archive);
+-        e.setDest(destDir);
+-        PatternSet p = new PatternSet();
+-        p.setExcludes("WEB-INF/classes/");
+-        e.addPatternset(p);
+-        e.execute();
++        // TODO: quick hack, this needs to be solved properly
++        try {
++            Runtime.getRuntime().exec("/usr/bin/unzip -d " + destDir.getAbsolutePath() + " " + archive.getAbsolutePath() + " -x 'WEB-INF/classes/*'");
++        } catch (IOException e) {
++            LOGGER.log(Level.SEVERE, "Failed to unzip plugin " + archive, e);
++        }
+     }
+ 
+     /**
diff --git a/jenkins.spec b/jenkins.spec
index 8467a20..7801450 100644
--- a/jenkins.spec
+++ b/jenkins.spec
@@ -11,7 +11,7 @@
 
 Name:           jenkins
 Version:        1.606
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        An extendable open source continuous integration server
 
 # The project's primary license is MIT
@@ -44,8 +44,8 @@ Patch7:         use-guava-13.0.patch
 Patch9:         remove-windows-support-from-processtree.patch
 Patch10:        remove-dotnet-support.patch
 Patch11:        remove-windows-installer-support.patch
-Patch13:        add-support-for-plugins-from-RPMs.patch
 Patch14:        do-not-check-for-core-updates.patch
+Patch15:        hpi-unpack-temp-hack.patch
 
 BuildArch:      noarch
 
@@ -352,8 +352,8 @@ This package contains API documentation for %{name}.
 %patch9 -p1
 %patch10 -p1
 %patch11 -p1
-%patch13 -p1 -F2
 %patch14 -p1
+%patch15 -p1
 
 # Remove bundled JARs and classes
 find . -name "*.jar" -delete
@@ -709,6 +709,9 @@ exit 0
 %doc LICENSE.txt
 
 %changelog
+* Mon Apr 13 2015 Michal Srb <msrb at redhat.com> - 1.606-2
+- Migrate to plugins containing symlinks
+
 * Thu Mar 26 2015 Michal Srb <msrb at redhat.com> - 1.606-1
 - Update to upstream release 1.606
 - Resolves: CVE-2015-1806
-- 
cgit v0.10.2


	http://pkgs.fedoraproject.org/cgit/jenkins.git/commit/?h=master&id=6136db2d08f638c0093bb77ea101001213ee9c98


More information about the scm-commits mailing list