Skip to content

Commit

Permalink
[FIXED JENKINS-3070]
Browse files Browse the repository at this point in the history
Added uninstaller that removes *.jpi.
  • Loading branch information
kohsuke committed Oct 9, 2012
1 parent 85eacfe commit 29f6a5d
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 5 deletions.
4 changes: 3 additions & 1 deletion changelog.html
Expand Up @@ -55,7 +55,9 @@
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
<li class=rfe>
Plugin manager now supports uninstallation.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-3070">issue 3070</a>)
</ul>
</div><!--=TRUNK-END=-->

Expand Down
35 changes: 34 additions & 1 deletion core/src/main/java/hudson/PluginWrapper.java
Expand Up @@ -26,6 +26,7 @@

import hudson.PluginManager.PluginInstanceStore;
import hudson.model.Api;
import hudson.model.ModelObject;
import jenkins.YesNoMaybe;
import jenkins.model.Jenkins;
import hudson.model.UpdateCenter;
Expand All @@ -49,6 +50,7 @@
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;
Expand Down Expand Up @@ -76,7 +78,7 @@
* @author Kohsuke Kawaguchi
*/
@ExportedBean
public class PluginWrapper implements Comparable<PluginWrapper> {
public class PluginWrapper implements Comparable<PluginWrapper>, ModelObject {
/**
* {@link PluginManager} to which this belongs to.
*/
Expand Down Expand Up @@ -116,6 +118,11 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
*/
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
Expand Down Expand Up @@ -200,6 +207,11 @@ public PluginWrapper(PluginManager parent, File archive, Manifest manifest, URL
this.active = !disableFile.exists();
this.dependencies = dependencies;
this.optionalDependencies = optionalDependencies;
this.archive = archive;
}

public String getDisplayName() {
return getLongName();
}

public Api getApi() {
Expand Down Expand Up @@ -513,6 +525,16 @@ public boolean isPinned() {
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.
*/
Expand Down Expand Up @@ -559,30 +581,41 @@ public String getBackupVersion() {
// 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());

Expand Down
21 changes: 18 additions & 3 deletions core/src/main/resources/hudson/PluginManager/installed.jelly
Expand Up @@ -42,9 +42,10 @@ THE SOFTWARE.
<tr style="border-top: 0px;">
<th width="32" tooltip="${%Uncheck to disable the plugin}">${%Enabled}</th>
<th initialSortDir="down">${%Name}</th>
<th width="32">${%Version}</th>
<th width="32">${%Previously installed version}</th>
<th width="32">${%Pinned}</th>
<th width="1">${%Version}</th>
<th width="1">${%Previously installed version}</th>
<th width="1">${%Pinned}</th>
<th width="1">${%Uninstall}</th>
</tr>
<j:forEach var="p" items="${app.pluginManager.plugins}">
<tr>
Expand Down Expand Up @@ -85,6 +86,18 @@ THE SOFTWARE.
<a href="${%wiki.url}"><img style="vertical-align:top" src="${imagesURL}/16x16/help.png"/></a>
</j:if>
</td>
<td class="center pane">
<j:choose>
<j:when test="${p.isDeleted()}">
<p>${%Uninstalltion pending}</p>

This comment has been minimized.

Copy link
@agray

agray Oct 10, 2012

Member

Shouldn't this be Uninstallation pending ? i.e. its a missspelling

</j:when>
<j:when test="${!p.isBundled()}">
<form method="post" action="plugin/${p.shortName}/uninstall">
<input type="submit" value="${%Uninstall}"/>
</form>
</j:when>
</j:choose>
</td>
</tr>
</j:forEach>
<!-- failed ones -->
Expand Down Expand Up @@ -121,6 +134,7 @@ THE SOFTWARE.

<!-- trigger -->
new Ajax.Request(btn.getAttribute('url')+"/make"+(btn.checked?"Enable":"Disable")+"d", {
method: "POST",
onFailure : function(req,o) {
$('needRestart').innerHTML = req.responseText;
}
Expand All @@ -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);
},
Expand Down
20 changes: 20 additions & 0 deletions 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"))
}
}
}
@@ -0,0 +1,2 @@
msg=You are about to uninstall the <b>{0}</b> plugin. This will remove the plugin binary from your $JENKINS_HOME, \
but it'll the configuration files of the plugin.

0 comments on commit 29f6a5d

Please sign in to comment.