package hudson.plugins.git;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Launcher;
import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.plugins.git.opt.PreBuildMergeOptions;
import hudson.remoting.VirtualChannel;
import hudson.scm.SCM;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.util.FormFieldValidator;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import javax.servlet.ServletException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.spearce.jgit.transport.RemoteConfig;
public class GitPublisher extends Publisher implements Serializable {
private static final long serialVersionUID = 1L;
@Override
public boolean needsToRunAfterFinalized() {
return true;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
@Override
public boolean perform(AbstractBuild<?, ?> build,
Launcher launcher, final BuildListener listener)
throws InterruptedException {
SCM scm = build.getProject().getScm();
if (!(scm instanceof GitSCM)) {
return false;
}
final GitSCM gitSCM = (GitSCM) scm;
final String projectName = build.getProject().getName();
final FilePath workspacePath = build.getWorkspace();
final int buildNumber = build.getNumber();
final Result buildResult = build.getResult();
final String gitExe = gitSCM.getDescriptor().getGitExe();
EnvVars tempEnvironment;
try {
tempEnvironment = build.getEnvironment(listener);
} catch (IOException e) {
listener.error("IOException publishing in git plugin");
tempEnvironment = new EnvVars();
}
final EnvVars environment = tempEnvironment;
boolean canPerform;
try {
canPerform = build.getWorkspace().act(
new FileCallable<Boolean>() {
private static final long serialVersionUID = 1L;
public Boolean invoke(File workspace,
VirtualChannel channel) throws IOException {
IGitAPI git = new GitAPI(
gitExe, workspacePath,
listener, environment);
// We delete the old tag generated by the SCM plugin
String buildnumber = "hudson-" + projectName + "-" + buildNumber;
git.deleteTag(buildnumber);
// And add the success / fail state into the tag.
buildnumber += "-" + buildResult.toString();
git.tag(buildnumber, "Hudson Build #" + buildNumber);
PreBuildMergeOptions mergeOptions = gitSCM.getMergeOptions();
if (mergeOptions.doMerge() && buildResult.isBetterOrEqualTo(
Result.SUCCESS)) {
RemoteConfig remote = mergeOptions.getMergeRemote();
listener.getLogger().println("Pushing result " + buildnumber + " to " + mergeOptions.getMergeTarget() + " branch of " + remote.getName() + " repository");
git.push(remote, "HEAD:" + mergeOptions.getMergeTarget());
} else {
//listener.getLogger().println("Pushing result " + buildnumber + " to origin repository");
//git.push(null);
}
return true;
}
});
} catch (Throwable e) {
listener.error("Failed to push tags to origin repository: " + e.getMessage());
build.setResult(Result.FAILURE);
return false;
}
return canPerform;
}
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
super(GitPublisher.class);
}
public String getDisplayName() {
return "Push Merges back to origin";
}
@Override
public String getHelpFile() {
return "/plugin/git/gitPublisher.html";
}
/**
* Performs on-the-fly validation on the file mask wildcard.
*
* @param req request
* @param rsp response
* @throws IOException
* @throws ServletException
*/
public void doCheck(StaplerRequest req, StaplerResponse rsp)
throws IOException, ServletException {
new FormFieldValidator.WorkspaceFileMask(req, rsp).process();
}
@Override
public GitPublisher newInstance(StaplerRequest req, JSONObject formData)
throws FormException {
return new GitPublisher();
}
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
}
}