package hudson.plugins.rake;
import static hudson.plugins.rake.Util.getCanonicalRubies;
import static hudson.plugins.rake.Util.getGemsDir;
import static hudson.plugins.rake.Util.hasGemsInstalled;
import static hudson.plugins.rake.Util.isRakeInstalled;
import hudson.CopyOnWrite;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.tasks.Builder;
import hudson.util.ArgumentListBuilder;
import hudson.util.FormValidation;
import java.io.File;
import java.io.IOException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
/**
* Rake plugin main class.
*
* @author David Calavera
*/
@SuppressWarnings({"unchecked", "serial"})
public class Rake extends Builder {
@Extension
public static final RakeDescriptor DESCRIPTOR = new RakeDescriptor();
private final String rakeInstallation;
private final String rakeFile;
private final String rakeLibDir;
private final String rakeWorkingDir;
private final String tasks;
private final boolean silent;
@DataBoundConstructor
public Rake(String rakeInstallation, String rakeFile, String tasks, String rakeLibDir, String rakeWorkingDir, boolean silent) {
this.rakeInstallation = rakeInstallation;
this.rakeFile = rakeFile;
this.tasks = tasks;
this.rakeLibDir = rakeLibDir;
this.rakeWorkingDir = rakeWorkingDir;
this.silent = silent;
}
private RubyInstallation getRake() {
for (RubyInstallation rake : getDescriptor().getInstallations()) {
if (rakeInstallation != null && rake.getName().equals(rakeInstallation)) {
return rake;
}
}
return null;
}
private Launcher getLastBuiltLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) {
AbstractProject project = build.getProject();
Node lastBuiltOn = project.getLastBuiltOn();
Launcher lastBuiltLauncher = launcher;
if (lastBuiltOn != null) {
lastBuiltLauncher = lastBuiltOn.createLauncher(listener);
}
return lastBuiltLauncher;
}
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException {
ArgumentListBuilder args = new ArgumentListBuilder();
String normalizedTasks = tasks.replaceAll("[\t\r\n]+"," ");
Launcher lastBuiltLauncher = getLastBuiltLauncher(build, launcher, listener);
RubyInstallation rake = getRake();
if (rake != null) {
File exec = rake.getExecutable();
if(!exec.exists()) {
listener.fatalError(exec + " doesn't exist");
return false;
}
args.add(exec.getPath());
} else {
args.add(lastBuiltLauncher.isUnix()?"rake":"rake.bat");
}
if (rakeFile != null && rakeFile.length() > 0) {
args.add("--rakefile", rakeFile);
}
if (rakeLibDir != null && rakeLibDir.length() > 0) {
args.add("--libdir", rakeLibDir);
}
if (silent) {
args.add("--silent");
}
FilePath workingDir = build.getModuleRoot();
if (rakeWorkingDir != null && rakeWorkingDir.length() > 0) {
workingDir = new FilePath(build.getModuleRoot(), rakeWorkingDir);
}
args.addTokenized(normalizedTasks);
try {
int r = lastBuiltLauncher.launch().cmds(args).envs(build.getEnvironment(listener)).stdout(listener).pwd(workingDir).join();
return r == 0;
} catch (IOException e) {
Util.displayIOException(e,listener);
e.printStackTrace(listener.fatalError("rake execution failed"));
return false;
}
}
@Override
public RakeDescriptor getDescriptor() {
return DESCRIPTOR;
}
public String getRakeInstallation() {
return rakeInstallation;
}
public String getRakeFile() {
return rakeFile;
}
public String getRakeLibDir() {
return rakeLibDir;
}
public String getTasks() {
return tasks;
}
public boolean isSilent() {
return silent;
}
public String getRakeWorkingDir() {
return rakeWorkingDir;
}
public static final class RakeDescriptor extends Descriptor<Builder> {
@CopyOnWrite
private volatile RubyInstallation[] installations = new RubyInstallation[0];
private RakeDescriptor() {
super(Rake.class);
load();
}
@Override
public synchronized void load() {
super.load();
installations = getCanonicalRubies(installations);
}
public String getDisplayName() {
return "Invoke Rake";
}
@Override
public Rake newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return (Rake)req.bindJSON(clazz,formData);
}
@Override
public String getHelpFile() {
return "/plugin/rake/help.html";
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
installations = req.bindParametersToList(RubyInstallation.class, "rake.")
.toArray(new RubyInstallation[0]);
save();
return true;
}
public RubyInstallation[] getInstallations() {
return installations;
}
public FormValidation doCheckRubyInstallation(@QueryParameter final String value) {
if (!Hudson.getInstance().hasPermission(Hudson.ADMINISTER)) return FormValidation.ok();
File f = new File(Util.fixNull(value));
if(!f.isDirectory()) {
return FormValidation.error(f + " is not a directory");
}
if (!hasGemsInstalled(f.getAbsolutePath())) {
return FormValidation.error("It seems that ruby gems is not installed");
}
if (!isRakeInstalled(getGemsDir(f.getAbsolutePath()))) {
return FormValidation.error("It seems that rake is not installed");
}
return FormValidation.ok();
}
}
}