diff --git a/changelog.html b/changelog.html index de603e226e..22594442e8 100644 --- a/changelog.html +++ b/changelog.html @@ -55,7 +55,9 @@ Upcoming changes diff --git a/core/src/main/java/hudson/PluginWrapper.java b/core/src/main/java/hudson/PluginWrapper.java index 27d1b174a8..3e61e16660 100644 --- a/core/src/main/java/hudson/PluginWrapper.java +++ b/core/src/main/java/hudson/PluginWrapper.java @@ -26,6 +26,7 @@ package hudson; import hudson.PluginManager.PluginInstanceStore; import hudson.model.Api; +import hudson.model.ModelObject; import jenkins.YesNoMaybe; import jenkins.model.Jenkins; import hudson.model.UpdateCenter; @@ -49,6 +50,7 @@ import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; +import org.kohsuke.stapler.interceptor.RequirePOST; import java.util.Enumeration; import java.util.jar.JarFile; @@ -76,7 +78,7 @@ import java.util.jar.JarFile; * @author Kohsuke Kawaguchi */ @ExportedBean -public class PluginWrapper implements Comparable { +public class PluginWrapper implements Comparable, ModelObject { /** * {@link PluginManager} to which this belongs to. */ @@ -116,6 +118,11 @@ public class PluginWrapper implements Comparable { */ private final File pinFile; + /** + * A .jpi file, an exploded plugin directory, or a .jpl file. + */ + private final File archive; + /** * Short name of the plugin. The artifact Id of the plugin. * This is also used in the URL within Jenkins, so it needs @@ -200,6 +207,11 @@ public class PluginWrapper implements Comparable { this.active = !disableFile.exists(); this.dependencies = dependencies; this.optionalDependencies = optionalDependencies; + this.archive = archive; + } + + public String getDisplayName() { + return getLongName(); } public Api getApi() { @@ -513,6 +525,16 @@ public class PluginWrapper implements Comparable { return pinFile.exists(); } + /** + * Returns true if this plugin is deleted. + * + * The plugin continues to function in this session, but in the next session it'll disappear. + */ + @Exported + public boolean isDeleted() { + return !archive.exists(); + } + /** * Sort by short name. */ @@ -559,30 +581,41 @@ public class PluginWrapper implements Comparable { // Action methods // // + @RequirePOST public HttpResponse doMakeEnabled() throws IOException { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); enable(); return HttpResponses.ok(); } + @RequirePOST public HttpResponse doMakeDisabled() throws IOException { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); disable(); return HttpResponses.ok(); } + @RequirePOST public HttpResponse doPin() throws IOException { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); new FileOutputStream(pinFile).close(); return HttpResponses.ok(); } + @RequirePOST public HttpResponse doUnpin() throws IOException { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); pinFile.delete(); return HttpResponses.ok(); } + @RequirePOST + public HttpResponse doDoUninstall() throws IOException { + Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); + archive.delete(); + return HttpResponses.redirectViaContextPath("/pluginManager/installed"); // send back to plugin manager + } + private static final Logger LOGGER = Logger.getLogger(PluginWrapper.class.getName()); diff --git a/core/src/main/resources/hudson/PluginManager/installed.jelly b/core/src/main/resources/hudson/PluginManager/installed.jelly index b8934ad904..0e6e53b5d6 100644 --- a/core/src/main/resources/hudson/PluginManager/installed.jelly +++ b/core/src/main/resources/hudson/PluginManager/installed.jelly @@ -42,9 +42,10 @@ THE SOFTWARE. ${%Enabled} ${%Name} - ${%Version} - ${%Previously installed version} - ${%Pinned} + ${%Version} + ${%Previously installed version} + ${%Pinned} + ${%Uninstall} @@ -85,6 +86,18 @@ THE SOFTWARE. + + + +

${%Uninstalltion pending}

+
+ +
+ +
+
+
+
@@ -121,6 +134,7 @@ THE SOFTWARE. new Ajax.Request(btn.getAttribute('url')+"/make"+(btn.checked?"Enable":"Disable")+"d", { + method: "POST", onFailure : function(req,o) { $('needRestart').innerHTML = req.responseText; } @@ -145,6 +159,7 @@ THE SOFTWARE. function unpin(button,shortName) { new Ajax.Request("./plugin/"+shortName+"/unpin", { + method: "POST", onFailure : function(t) { alert('Failed to unpin:'+t.responseText); }, diff --git a/core/src/main/resources/hudson/PluginWrapper/uninstall.groovy b/core/src/main/resources/hudson/PluginWrapper/uninstall.groovy new file mode 100644 index 0000000000..182283a71f --- /dev/null +++ b/core/src/main/resources/hudson/PluginWrapper/uninstall.groovy @@ -0,0 +1,20 @@ +package hudson.PluginWrapper + +def l = namespace(lib.LayoutTagLib) +def f = namespace(lib.FormTagLib) + +l.layout { + def title = "Uninstalling ${my.shortName} plugin" + l.header(title:title) + l.main_panel { + h1 { + img(src:"${imagesURL}/48x48/error.png",alt:"[!]",height:48,width:48) + text(" ") + text(title) + } + p { raw _("msg",my.shortName) } + f.form(method:"post",action:"doUninstall") { + f.submit(value:_("Yes")) + } + } +} \ No newline at end of file diff --git a/core/src/main/resources/hudson/PluginWrapper/uninstall.properties b/core/src/main/resources/hudson/PluginWrapper/uninstall.properties new file mode 100644 index 0000000000..fa00f953d6 --- /dev/null +++ b/core/src/main/resources/hudson/PluginWrapper/uninstall.properties @@ -0,0 +1,2 @@ +msg=You are about to uninstall the {0} plugin. This will remove the plugin binary from your $JENKINS_HOME, \ + but it'll the configuration files of the plugin. \ No newline at end of file