package hudson.plugins.cvs_tag; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Array; import java.text.SimpleDateFormat; import java.util.Map; import groovy.lang.Binding; import groovy.lang.GroovyShell; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Hudson; import hudson.model.Result; import hudson.scm.CVSSCM; import hudson.util.ArgumentListBuilder; import org.codehaus.groovy.control.CompilerConfiguration; /** * @author Brendt Lucas */ public class CvsTagPlugin { static final String DESCRIPTION = "Perform CVS tagging on succesful build"; static final String CONFIG_PREFIX = "cvstag."; private CvsTagPlugin() { } private static AbstractProject getRootProject(AbstractProject abstractProject) { if (abstractProject.getParent() instanceof Hudson) { return abstractProject; } else { return getRootProject((AbstractProject) abstractProject.getParent()); } } public static boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener, String tagName) throws IOException, InterruptedException { PrintStream logger = listener.getLogger(); if (!Result.SUCCESS.equals(build.getResult())) { logger.println("Skipping CVS Tagging as build result was not successful."); return true; } AbstractProject rootProject = getRootProject(build.getProject()); if (!(rootProject.getScm() instanceof CVSSCM)) { logger.println("CVS Tag plugin does not support tagging for SCM " + rootProject.getScm() + "."); return true; } CVSSCM scm = CVSSCM.class.cast(rootProject.getScm()); // Evaluate the groovy tag name Map<String, String> env = build.getEnvironment(listener); tagName = evalGroovyExpression(env, tagName); // -D option for rtag command. // Tag the most recent revision no later than <date> ... String date = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(build.getTimestamp().getTime()); ArgumentListBuilder cmd = new ArgumentListBuilder(); cmd.add(scm.getDescriptor().getCvsExeOrDefault(), "-d", scm.getCvsRoot(), "rtag"); if (scm.getBranch() != null) { // cvs -d cvsRoot rtag -r branchName tagName modules cmd.add("-r", scm.getBranch(), tagName); } else { // cvs -d cvsRoot rtag -D toDate tagName modules cmd.add("-D", date, tagName); } cmd.add(scm.getAllModulesNormalized()); logger.println("Executing tag command: " + cmd.toStringWithQuote()); File tempDir = null; try { tempDir = Util.createTempDir(); int exitCode = launcher.launch().cmds(cmd).envs(env).stdout(logger).pwd(tempDir).join(); if (exitCode != 0) { listener.fatalError(CvsTagPublisher.DESCRIPTOR.getDisplayName() + " failed. exit code=" + exitCode); } } catch (IOException e) { e.printStackTrace(listener.error(e.getMessage())); logger.println("IOException occurred: " + e); return false; } catch (InterruptedException e) { e.printStackTrace(listener.error(e.getMessage())); logger.println("InterruptedException occurred: " + e); return false; } finally { try { if (tempDir != null) { logger.println("cleaning up " + tempDir); Util.deleteRecursive(tempDir); } } catch (IOException e) { e.printStackTrace(listener.error(e.getMessage())); } } return true; } /** * Converts an array into a delimited String * * @param array the array to convert * @param delimiter The delimiter used in the String representation * @return a delimited String representation of the array */ private static String arrayToString(Object array, String delimiter) { int length = Array.getLength(array); if (length == 0) { return ""; } StringBuilder sb = new StringBuilder(2 * length - 1); for (int i = 0; i < length; i++) { if (i > 0) { sb.append(delimiter); } sb.append(Array.get(array, i)); } return sb.toString(); } static String evalGroovyExpression(Map<String, String> env, String expression) { Binding binding = new Binding(); binding.setVariable("env", env); binding.setVariable("sys", System.getProperties()); CompilerConfiguration config = new CompilerConfiguration(); //config.setDebug(true); GroovyShell shell = new GroovyShell(binding, config); Object result = shell.evaluate("return \"" + expression + "\""); if (result == null) { return ""; } else { return result.toString().trim(); } } }