package hudson.plugins.accurev.delegates; import hudson.model.AbstractBuild; import hudson.model.Job; import hudson.model.Run; import hudson.plugins.accurev.*; import hudson.plugins.accurev.cmd.Command; import hudson.plugins.accurev.cmd.Update; import hudson.plugins.accurev.delegates.Relocation.RelocationOption; import hudson.plugins.accurev.parsers.xml.ParseShowReftrees; import hudson.scm.PollingResult; import hudson.util.ArgumentListBuilder; import org.apache.commons.lang.StringUtils; import org.xmlpull.v1.XmlPullParserFactory; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Logger; /** * @author raymond */ public class ReftreeDelegate extends AbstractModeDelegate { private static final Logger logger = Logger.getLogger(ReftreeDelegate.class.getName()); protected boolean popRequired = false; private File updateLogFile; public ReftreeDelegate(AccurevSCM scm) { super(scm); } public String getRefTree() { return scm.getReftree(); } @Override protected PollingResult checkForChanges(Job<?, ?> project) throws IOException, InterruptedException { try { Relocation relocation = checkForRelocation(); if (relocation.isRelocationRequired()) { listener.getLogger().println("Relocation required triggering build"); return PollingResult.BUILD_NOW; } else { if (Update.hasChanges(scm, server, accurevEnv, accurevWorkingSpace, listener, launcher, getRefTree())) { return PollingResult.BUILD_NOW; } else { return PollingResult.NO_CHANGES; } } } catch (IllegalArgumentException ex) { listener.fatalError(ex.getMessage()); return PollingResult.NO_CHANGES; } } protected Relocation checkForRelocation() throws IOException, InterruptedException { final Map<String, AccurevReferenceTree> reftrees = getReftrees(); String reftree = scm.getReftree(); if (reftrees == null) { throw new IllegalArgumentException("Cannot determine reference tree configuration information"); } if (!reftrees.containsKey(reftree)) { throw new IllegalArgumentException("The specified reference tree does not appear to exist!"); } AccurevReferenceTree accurevReftree = reftrees.get(reftree); if (!scm.getDepot().equals(accurevReftree.getDepot())) { throw new IllegalArgumentException("The specified reference tree, " + reftree + ", is based in the depot " + accurevReftree.getDepot() + " not " + scm.getDepot()); } RemoteWorkspaceDetails remoteDetails = getRemoteWorkspaceDetails(); List<RelocationOption> relocationOptions = new ArrayList<>(); for (RefTreeRelocation refTreeRelocation : RefTreeRelocation.values()) { if (refTreeRelocation.isRequired(accurevReftree, remoteDetails)) { relocationOptions.add(refTreeRelocation); } } return new Relocation(relocationOptions, remoteDetails.getHostName(), accurevWorkingSpace.getRemote(), null); } protected RemoteWorkspaceDetails getRemoteWorkspaceDetails() throws InterruptedException { try { return jenkinsWorkspace.act(new DetermineRemoteHostname(accurevWorkingSpace.getRemote())); } catch (IOException e) { e.printStackTrace(listener.getLogger()); throw new IllegalArgumentException("Unable to validate reference tree host."); } } /** * Builds a command which gets executed and retrieves the following return data * * @return Map with Reference Tree name as key and Reference Tree Object as value. * @throws IOException Failed to execute command or Parse data. */ private Map<String, AccurevReferenceTree> getReftrees() throws IOException { listener.getLogger().println("Getting a list of reference trees..."); final ArgumentListBuilder cmd = new ArgumentListBuilder(); cmd.add("show"); Command.addServer(cmd, server); cmd.add("-fx"); cmd.add("refs"); XmlPullParserFactory parser = XmlParserFactory.getFactory(); if (parser == null) throw new IOException("No XML Parser"); return AccurevLauncher.runCommand("Show ref trees command", accurevTool, launcher, cmd, scm.getOptionalLock(), accurevEnv, jenkinsWorkspace, listener, logger, parser, new ParseShowReftrees(), null); } @Override protected boolean checkout(Run<?, ?> build, File changeLogFile) throws IOException, InterruptedException { if (!validateCheckout(build)) { return false; } Relocation relocation = checkForRelocation(); if (relocation.isRelocationRequired()) { if (!relocate(relocation)) { return false; } if (!populate(build, popRequired)) { return false; } } return doUpdate(changeLogFile); } private boolean doUpdate(File changeLogFile) throws IOException { updateLogFile = XmlConsolidateStreamChangeLog.getUpdateChangeLogFile(changeLogFile); return Update.performUpdate(scm, server, accurevEnv, accurevWorkingSpace, listener, launcher, getRefTree(), updateLogFile); } @Override protected String getUpdateFileName() { return updateLogFile.getName(); } protected String getPopulateFromMessage() { return "from reftree"; } @Override protected String getPopulateStream() { return null; } private boolean relocate(Relocation relocation) throws IOException, InterruptedException { ArgumentListBuilder relocateCommand = getRelocateCommand(); popRequired = relocation.isPopRequired(); if (popRequired) { listener.getLogger().println("Clearing path: " + accurevWorkingSpace.getRemote()); accurevWorkingSpace.deleteContents(); } relocation.appendCommands(relocateCommand); return AccurevLauncher.runCommand("relocation command", accurevTool, launcher, relocateCommand, scm.getOptionalLock(), accurevEnv, accurevWorkingSpace, listener, logger, true); } protected ArgumentListBuilder getRelocateCommand() { ArgumentListBuilder chrefcmd = new ArgumentListBuilder(); chrefcmd.add("chref"); Command.addServer(chrefcmd, server); chrefcmd.add("-r"); chrefcmd.add(getRefTree()); return chrefcmd; } protected boolean validateCheckout(Run<?, ?> build) { String reftree = getRefTree(); if (StringUtils.isEmpty(reftree)) { listener.fatalError("Must specify a reference tree"); return false; } return true; } @Override protected void buildEnvVarsCustom(AbstractBuild<?, ?> build, Map<String, String> env) { env.put("ACCUREV_REFTREE", scm.getReftree()); } private enum RefTreeRelocation implements RelocationOption { HOST { @Override protected boolean isRequired(AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails) { return !accurevReftree.getHost().equals(remoteDetails.getHostName()); } public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) { cmd.add("-m"); cmd.add(relocation.getNewHost()); } }, STORAGE { @Override protected boolean isRequired(AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails) { String oldStorage = accurevReftree.getStorage() .replace("/", remoteDetails.getFileSeparator()) .replace("\\", remoteDetails.getFileSeparator()); return !new File(oldStorage).equals(new File(remoteDetails.getPath())); } public void appendCommand(ArgumentListBuilder cmd, Relocation relocation) { cmd.add("-l"); cmd.add(relocation.getNewPath()); } }; public boolean isPopRequired() { return true; } protected abstract boolean isRequired(AccurevReferenceTree accurevReftree, RemoteWorkspaceDetails remoteDetails); } }