package hudson.plugins.cvs_tag;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletException;
import hudson.tasks.Publisher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.Extension;
import hudson.Launcher;
import hudson.scm.Messages;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.util.FormValidation;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.codehaus.groovy.control.CompilationFailedException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.QueryParameter;
import static hudson.plugins.cvs_tag.CvsTagPlugin.CONFIG_PREFIX;
import static hudson.plugins.cvs_tag.CvsTagPlugin.DESCRIPTION;
/**
* @author Brendt Lucas
*/
public class CvsTagPublisher extends Notifier
{
/**
* The tag name
*/
private String tagName;
@Extension
public static final CvsTagDescriptorImpl DESCRIPTOR = new CvsTagDescriptorImpl();
/**
* @return the tag name
*/
public String getTagName()
{
if (tagName == null || tagName.length() == 0)
{
return DESCRIPTOR.getDefaultTagName();
}
return tagName;
}
/**
* Set the tag name
* @param tagName the tag name
*/
public void setTagName(String tagName)
{
this.tagName = tagName;
}
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException
{
return CvsTagPlugin.perform(build, launcher, listener, tagName);
}
@Override
public boolean needsToRunAfterFinalized()
{
return true;
}
public BuildStepMonitor getRequiredMonitorService()
{
return BuildStepMonitor.BUILD;
}
@Override
public BuildStepDescriptor<Publisher> getDescriptor()
{
return DESCRIPTOR;
}
public static final class CvsTagDescriptorImpl extends BuildStepDescriptor<Publisher>
{
private String defaultTagName;
private CvsTagDescriptorImpl()
{
super(CvsTagPublisher.class);
this.defaultTagName = "${env['JOB_NAME']}-${env['BUILD_NUMBER']}-${new java.text.SimpleDateFormat(\"yyyy_MM_dd\").format(new Date())}";
load();
}
@Override
public String getDisplayName()
{
return DESCRIPTION;
}
@Override
public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException
{
CvsTagPublisher cvsTagPublisher = new CvsTagPublisher();
cvsTagPublisher.setTagName(formData.getString("tagName"));
return cvsTagPublisher;
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException
{
this.defaultTagName = req.getParameter(CONFIG_PREFIX + "tagName");
save();
return super.configure(req, formData);
}
public boolean isApplicable(Class<? extends AbstractProject> jobType)
{
return true;
}
public String getDefaultTagName()
{
return defaultTagName;
}
public void setDefaultTagName(String defaultTagName)
{
this.defaultTagName = defaultTagName;
}
public FormValidation doTagNameCheck(@QueryParameter("value") final String tagName) throws IOException, ServletException
{
if (tagName == null || tagName.length() == 0)
{
return FormValidation.error("Please specify a name for this tag.");
}
else
{
// Test to make sure the tag name is valid
String s = null;
try
{
s = CvsTagPlugin.evalGroovyExpression(new HashMap<String, String>(), tagName);
}
catch (CompilationFailedException e)
{
return FormValidation.error("Check if quotes, braces, or brackets are balanced. " + e.getMessage());
}
if (s != null)
{
String errorMessage = isInvalidTag(s);
if (errorMessage != null)
{
return FormValidation.error(errorMessage);
}
}
}
return FormValidation.ok();
}
/**
* Checks if the given value is a valid CVS tag.
* <p/>
* If it's invalid, this method gives you the reason as string.
* @param tagName the tag name
* @return the error message, or null if tag is valid
*/
private String isInvalidTag(String tagName)
{
// source code from CVS rcs.c
//void
//RCS_check_tag (tag)
// const char *tag;
//{
// char *invalid = "$,.:;@"; /* invalid RCS tag characters */
// const char *cp;
//
// /*
// * The first character must be an alphabetic letter. The remaining
// * characters cannot be non-visible graphic characters, and must not be
// * in the set of "invalid" RCS identifier characters.
// */
// if (isalpha ((unsigned char) *tag))
// {
// for (cp = tag; *cp; cp++)
// {
// if (!isgraph ((unsigned char) *cp))
// error (1, 0, "tag `%s' has non-visible graphic characters",
// tag);
// if (strchr (invalid, *cp))
// error (1, 0, "tag `%s' must not contain the characters `%s'",
// tag, invalid);
// }
// }
// else
// error (1, 0, "tag `%s' must start with a letter", tag);
//}
if (tagName == null || tagName.length() == 0)
{
return Messages.CVSSCM_TagIsEmpty();
}
char ch = tagName.charAt(0);
if (!(('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z')))
{
return Messages.CVSSCM_TagNeedsToStartWithAlphabet();
}
for (char invalid : "$,.:;@".toCharArray())
{
if (tagName.indexOf(invalid) >= 0)
{
return Messages.CVSSCM_TagContainsIllegalChar(invalid);
}
}
return null;
}
}
}