Index: main/java/hudson/plugins/synergy/impl/CheckSessionCommand.java =================================================================== --- main/java/hudson/plugins/synergy/impl/CheckSessionCommand.java (revision 0) +++ main/java/hudson/plugins/synergy/impl/CheckSessionCommand.java (revision 0) @@ -0,0 +1,66 @@ +package hudson.plugins.synergy.impl; + +import hudson.FilePath; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class CheckSessionCommand extends Command { + + public static final String SESSION_NOT_FOUND = "SESSION_NOT_FOUND"; + + private String allSessions; + + /** + * Checks if a session allready exists. return's the CCM addr if the session + * allready exists + * + * @param filePath + */ + public CheckSessionCommand() { + } + + @Override + public String[] buildCommand(String ccmAddr) { + String[] commands = new String[] { ccmAddr, "status" }; + + return commands; + } + + @Override + public void parseResult(String result) { + allSessions = result; + } + + public String getCcmAddr(FilePath ccmSessionMapFile) throws IOException, InterruptedException { + if (!ccmSessionMapFile.exists()) + return SESSION_NOT_FOUND; + + InputStream is = null; + String ccmAddr = null; + try { + is = ccmSessionMapFile.read(); + Properties properties = new Properties(); + properties.load(is); + + ccmAddr = properties.getProperty("ccmSession"); + } finally { + if (is != null) + is.close(); + } + + if (allSessions.indexOf(ccmAddr) < 0) + return SESSION_NOT_FOUND; + + if (ccmAddr == null) + return SESSION_NOT_FOUND; + + return ccmAddr; + } + + @Override + public boolean isStatusOK(int status) { + return status == 0; + } +} Index: main/java/hudson/plugins/synergy/impl/CopyFolderCommand.java =================================================================== --- main/java/hudson/plugins/synergy/impl/CopyFolderCommand.java (revision 0) +++ main/java/hudson/plugins/synergy/impl/CopyFolderCommand.java (revision 0) @@ -0,0 +1,21 @@ +package hudson.plugins.synergy.impl; + +public class CopyFolderCommand extends Command { + + private String fromFolder; + private String toFolder; + + public CopyFolderCommand(String fromFolder, String toFolder) { + this.fromFolder = fromFolder; + this.toFolder = toFolder; + } + @Override + public String[] buildCommand(String ccmExe) { + String[] commands = new String[]{ccmExe, "folder", "-copy", fromFolder, "-existing", toFolder}; + return commands; + } + @Override + public void parseResult(String result) { + // do nothing. + } +} Index: main/java/hudson/plugins/synergy/impl/ProjectConflicts.java =================================================================== --- main/java/hudson/plugins/synergy/impl/ProjectConflicts.java (revision 16864) +++ main/java/hudson/plugins/synergy/impl/ProjectConflicts.java (working copy) @@ -32,12 +32,18 @@ while (line!=null) { line = line.trim(); if (line.length()!=0 && !line.startsWith("Project:") && line.indexOf("No conflicts detected")==-1) { + StringTokenizer tokenizer = new StringTokenizer(line, "\t"); String objectname = tokenizer.nextToken(); - String task = tokenizer.nextToken(); - String message = tokenizer.nextToken(); - int index = message.lastIndexOf("-"); - String type = message.substring(index+1).trim(); + String task = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : "No Task"; + String message = ""; + String type = ""; + if(tokenizer.hasMoreTokens()){ + message = tokenizer.nextToken(); + int index = message.lastIndexOf("-"); + type = message.substring(index+1).trim(); + } + Conflict conflict = new Conflict(objectname, task, type, message); conflicts.add(conflict); } Index: main/java/hudson/plugins/synergy/impl/StartCommand.java =================================================================== --- main/java/hudson/plugins/synergy/impl/StartCommand.java (revision 16864) +++ main/java/hudson/plugins/synergy/impl/StartCommand.java (working copy) @@ -1,29 +1,41 @@ package hudson.plugins.synergy.impl; +import hudson.FilePath; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.List; +import java.util.Properties; /** - * A start session command. - * A start session command returns the CCM_ADDR to use for the following commands. + * A start session command. A start session command returns the CCM_ADDR to use + * for the following commands. */ public class StartCommand extends Command { + private String ccmAddr; private String login; private String database; private String engine; private String password; private boolean remoteClient; - + /** - * Builds a start session command. - * A start session command returns the CCM_ADDR to use for the following commands. + * Builds a start session command. A start session command returns the + * CCM_ADDR to use for the following commands. * - * @param database The database path - * @param login The user login - * @param password The user password - * @param remoteClient Use remote client flag - * @return The start command. The last part of the command is the logon password. + * @param database + * The database path + * @param login + * The user login + * @param password + * The user password + * @param remoteClient + * Use remote client flag + * @return The start command. The last part of the command is the logon + * password. */ public StartCommand(String database, String engine, String login, String password, boolean remoteClient) { this.database = database; @@ -33,11 +45,10 @@ this.remoteClient = remoteClient; } - @Override public String[] buildCommand(String ccmAddr) { - String[] commands = new String[]{ccmAddr, "start", "-d", database, "-h", engine, "-n", login, "-nogui", "-m", "-q", "-pw", password}; - + String[] commands = new String[] { ccmAddr, "start", "-d", database, "-h", engine, "-n", login, "-nogui", "-m", "-q", "-pw", password }; + // Add "-rc" parameter if required at the end of the array. if (remoteClient) { List list = new ArrayList(commands.length); @@ -49,7 +60,7 @@ } return commands; } - + @Override public boolean[] buildMask() { boolean[] result = super.buildMask(); @@ -57,19 +68,41 @@ result[pwdIndex] = true; return result; } - + @Override public void parseResult(String result) { ccmAddr = result; } - + public String getCcmAddr() { return ccmAddr; } - + @Override public boolean isStatusOK(int status) { - return status==0; + return status == 0; } - + + public void addCcmAddrToSessionMapFile(FilePath ccmSessionMapFile) throws IOException, InterruptedException { + InputStream is = null; + OutputStream os = null; + try { + Properties properties = new Properties(); + if (ccmSessionMapFile.exists()) { + is = ccmSessionMapFile.read(); + properties.load(is); + } + + properties.put("ccmSession", ccmAddr); + + os = ccmSessionMapFile.write(); + properties.store(os, null); + } finally { + if (is != null) + is.close(); + if (os != null) + os.close(); + } + + } } Index: main/java/hudson/plugins/synergy/impl/UpdateCommand.java =================================================================== --- main/java/hudson/plugins/synergy/impl/UpdateCommand.java (revision 16864) +++ main/java/hudson/plugins/synergy/impl/UpdateCommand.java (working copy) @@ -1,12 +1,14 @@ package hudson.plugins.synergy.impl; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Builds an update workarea command. + * * @author jrbe */ public class UpdateCommand extends Command { @@ -14,26 +16,34 @@ * The spec of the project to update. */ private String project; - + /** * The list of members that have been added to the workarea. */ private List names; - - public UpdateCommand(String project) { + + /** + * Should the subprojects be replaced? + */ + private boolean replaceSubprojects; + + private List conflicts = new ArrayList(); + + public UpdateCommand(String project, boolean replaceSubprojects) { this.project = project; + this.replaceSubprojects = replaceSubprojects; } @Override public void parseResult(String result) { // List of elements found. names = new ArrayList(); - + // Creates regexps for what we are looking for in the log. - Pattern pReplaces = Pattern.compile("'[^']+'\\sreplaces\\s'[^']+'\\sunder\\s'[^']+'"); + Pattern pReplaces = Pattern.compile("'[^']+'\\sreplaces\\s'[^']+'\\sunder\\s'c"); Pattern pBoundUnder = Pattern.compile("'[^']+'\\sis\\snow\\sbound\\sunder\\s'[^']+'"); Pattern pObjectName = Pattern.compile("'[^']+'"); - + // Look for updates. Matcher mReplaces = pReplaces.matcher(result); while (mReplaces.find()) { @@ -42,31 +52,56 @@ String newElement = mObjectNames.find() ? mObjectNames.group() : null; String oldElement = mObjectNames.find() ? mObjectNames.group() : null; String elementParent = mObjectNames.find() ? mObjectNames.group() : null; - names.add(newElement.substring(1, newElement.length()-1)); + names.add(newElement.substring(1, newElement.length() - 1)); } - + // Look for new elements. Matcher mBound = pBoundUnder.matcher(result); while (mBound.find()) { String group = mBound.group(); Matcher mObjectNames = pObjectName.matcher(group); String newElement = mObjectNames.find() ? mObjectNames.group() : null; - String elementParent = mObjectNames.find() ? mObjectNames.group() :null; - names.add(newElement.substring(1, newElement.length()-1)); - } + String elementParent = mObjectNames.find() ? mObjectNames.group() : null; + names.add(newElement.substring(1, newElement.length() - 1)); + } + + Pattern updateWarningPattern = Pattern.compile("Warning:\\s.*"); + Matcher mUpdateWarningPattern = updateWarningPattern.matcher(result); + boolean foundWarning = mUpdateWarningPattern.find(); + if (foundWarning) { + String objectname = "Update Warning found!"; + String task = "No Task"; + String type = ""; + String message = mUpdateWarningPattern.group(); + + Conflict conflict = new Conflict(objectname, task, type, message); + conflicts.add(conflict); + } } - + @Override public String[] buildCommand(String ccmExe) { - String[] commands = new String[] {ccmExe, "update", "-r", "-rs", "-p", project}; + String subprojectUpdateRule = "-keep_subprojects"; + if (replaceSubprojects) + subprojectUpdateRule = "-replace_subprojects"; + + String[] commands = new String[] { ccmExe, "update", "-r", subprojectUpdateRule, "-p", project }; return commands; } public List getUpdates() { return names; } - + public boolean isStatusOK(int status) { - return status==0; + return status == 0; } + + public Collection getConflicts() { + return conflicts; + } + + public boolean isUpdateWarningsExists() { + return !getConflicts().isEmpty(); + } } Index: main/java/hudson/plugins/synergy/SynergyFolderPublisher.java =================================================================== --- main/java/hudson/plugins/synergy/SynergyFolderPublisher.java (revision 0) +++ main/java/hudson/plugins/synergy/SynergyFolderPublisher.java (revision 0) @@ -0,0 +1,164 @@ +package hudson.plugins.synergy; + +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.AbstractBuild; +import hudson.model.BuildListener; +import hudson.model.Descriptor; +import hudson.model.Result; +import hudson.plugins.synergy.impl.CheckSessionCommand; +import hudson.plugins.synergy.impl.Commands; +import hudson.plugins.synergy.impl.CopyFolderCommand; +import hudson.plugins.synergy.impl.StartCommand; +import hudson.plugins.synergy.impl.SynergyException; +import hudson.scm.SCM; +import hudson.tasks.Publisher; + +import java.io.IOException; + +import net.sf.json.JSONObject; + +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.StaplerRequest; + +public class SynergyFolderPublisher extends Publisher { + public static class DescriptorImpl extends Descriptor { + public static DescriptorImpl DESCRIPTOR = new DescriptorImpl(); + + private DescriptorImpl() { + super(SynergyFolderPublisher.class); + } + + @Override + public String getDisplayName() { + return "Synergy Copy Folder"; + } + + @Override + public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException { + return new SynergyFolderPublisher(Boolean.parseBoolean(req.getParameter("synergyPublisher.publish")), req + .getParameter("synergy.intFolder"), req.getParameter("synergy.devFolder")); + } + } + + /** + * Should the baseline be published + */ + private boolean onlyOnSuccess; + + /** + * the integration folder + */ + private String intFolder; + + /** + * the development folder + */ + private String devFolder; + + @DataBoundConstructor + public SynergyFolderPublisher(Boolean onlyOnSuccess, String intFolder, String devFolder) { + this.onlyOnSuccess = onlyOnSuccess; + this.intFolder = intFolder; + this.devFolder = devFolder; + } + + public Descriptor getDescriptor() { + return DescriptorImpl.DESCRIPTOR; + } + + @Override + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + // Check SCM used. + SCM scm = build.getProject().getScm(); + if (!(scm instanceof SynergySCM)) { + listener.getLogger().println("No Folder copy for non Synergy project"); + return false; + } + + // Check what needs to be done. + boolean buildSucess = Result.SUCCESS.equals(build.getResult()); + boolean copyFolders = true; + + if (onlyOnSuccess && !buildSucess) { + // Copy folders if build is sucessful. + copyFolders = false; + } + + // Check if we need to go on. + if (copyFolders) { + // Get Synergy parameters. + SynergySCM synergySCM = (SynergySCM) scm; + String database = synergySCM.getDatabase(); + String username = synergySCM.getUsername(); + String password = synergySCM.getPassword(); + boolean remoteClient = synergySCM.isRemoteClient(); + boolean replaceSubprojects = synergySCM.isReplaceSubprojects(); + String engine = synergySCM.getEngine(); + + FilePath path = build.getProject().getWorkspace(); + + Commands commands = new Commands(); + commands.setCcmExe(synergySCM.getDescriptor().getCcmExe()); + commands.setCcmUiLog(synergySCM.getDescriptor().getCcmUiLog()); + commands.setCcmEngLog(synergySCM.getDescriptor().getCcmEngLog()); + + commands.setTaskListener(listener); + commands.setLauncher(launcher); + + try { + FilePath ccmSessionMapFile = new FilePath(path, SynergySCM.CCM_SESSION_MAP_FILE_NAME); + + CheckSessionCommand checkSessionCommand = new CheckSessionCommand(); + commands.executeSynergyCommand(path, checkSessionCommand); + String ccmAddr = checkSessionCommand.getCcmAddr(ccmSessionMapFile); + if (CheckSessionCommand.SESSION_NOT_FOUND.equals(ccmAddr)) { + // Start Synergy. + StartCommand startCommand = new StartCommand(database, engine, username, password, remoteClient); + commands.executeSynergyCommand(path, startCommand); + ccmAddr = startCommand.getCcmAddr(); + startCommand.addCcmAddrToSessionMapFile(ccmSessionMapFile); + } + commands.setCcmAddr(ccmAddr); + + CopyFolderCommand copyFolderCommand = new CopyFolderCommand(getIntFolder(), getDevFolder()); + commands.executeSynergyCommand(path, copyFolderCommand); + } catch (SynergyException e) { + return false; + } finally { + // Stop Synergy. + // StopCommand stopCommand = new StopCommand(); + // try { + // commands.executeSynergyCommand(path, stopCommand); + // } catch (SynergyException e) { + // return false; + // } + } + } + return true; + } + + public void setPublish(boolean publish) { + this.onlyOnSuccess = publish; + } + + public boolean isPublish() { + return onlyOnSuccess; + } + + public void setIntFolder(String intFolder){ + this.intFolder = intFolder; + } + + public String getIntFolder(){ + return intFolder; + } + + public void setDevFolder(String devFolder){ + this.devFolder = devFolder; + } + + public String getDevFolder(){ + return devFolder; + } +} Index: main/java/hudson/plugins/synergy/SynergyPluginImpl.java =================================================================== --- main/java/hudson/plugins/synergy/SynergyPluginImpl.java (revision 16864) +++ main/java/hudson/plugins/synergy/SynergyPluginImpl.java (working copy) @@ -23,5 +23,6 @@ public void start() throws Exception { SCMS.SCMS.add(SynergySCM.DescriptorImpl.DESCRIPTOR); BuildStep.PUBLISHERS.add(SynergyPublisher.DescriptorImpl.DESCRIPTOR); + BuildStep.PUBLISHERS.add(SynergyFolderPublisher.DescriptorImpl.DESCRIPTOR); } } Index: main/java/hudson/plugins/synergy/SynergyPublisher.java =================================================================== --- main/java/hudson/plugins/synergy/SynergyPublisher.java (revision 16864) +++ main/java/hudson/plugins/synergy/SynergyPublisher.java (working copy) @@ -16,6 +16,7 @@ import hudson.model.BuildListener; import hudson.model.Descriptor; import hudson.model.Result; +import hudson.plugins.synergy.impl.CheckSessionCommand; import hudson.plugins.synergy.impl.Commands; import hudson.plugins.synergy.impl.CreateProjectBaselineCommand; import hudson.plugins.synergy.impl.PublishBaselineCommand; @@ -28,38 +29,35 @@ public class SynergyPublisher extends Publisher { public static class DescriptorImpl extends Descriptor { public static DescriptorImpl DESCRIPTOR = new DescriptorImpl(); - + private DescriptorImpl() { - super(SynergyPublisher.class); + super(SynergyPublisher.class); } - + @Override public String getDisplayName() { return "Create a Synergy Baseline"; } - + @Override public Publisher newInstance(StaplerRequest req, JSONObject formData) throws FormException { - return new SynergyPublisher( - req.getParameter("synergyPublisher.time"), - Boolean.parseBoolean(req.getParameter("synergyPublisher.publish")) - ); + return new SynergyPublisher(req.getParameter("synergyPublisher.time"), Boolean.parseBoolean(req.getParameter("synergyPublisher.publish"))); } - + } - + /** * The moment the baseline should be created (after/before/sucess) */ private String time; - + /** * Should the baseline be published */ private boolean publish; @DataBoundConstructor - public SynergyPublisher(String time,boolean publish) { + public SynergyPublisher(String time, boolean publish) { this.time = time; this.publish = publish; } @@ -67,7 +65,7 @@ public Descriptor getDescriptor() { return DescriptorImpl.DESCRIPTOR; } - + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { // Check SCM used. @@ -76,14 +74,14 @@ listener.getLogger().println("No baseline publishing for non Synergy project"); return false; } - + // Check what needs to be done. boolean createBaseline = false; boolean publishBaseline = false; boolean buildSucess = Result.SUCCESS.equals(build.getResult()); - + String createBaselineAtPoint = getTime(); - + if ("after".equals(createBaselineAtPoint)) { // Always create baseline after build. createBaseline = true; @@ -95,9 +93,9 @@ // Publish baseline if build is sucessful. publishBaseline = true; } - + // Check if we need to go on. - if (createBaseline || publishBaseline) { + if (createBaseline || publishBaseline) { // Get Synergy parameters. SynergySCM synergySCM = (SynergySCM) scm; String database = synergySCM.getDatabase(); @@ -108,59 +106,67 @@ String project = synergySCM.getProject(); String purpose = synergySCM.getPurpose(); String release = synergySCM.getRelease(); - + FilePath path = build.getProject().getWorkspace(); - + Commands commands = new Commands(); commands.setCcmExe(synergySCM.getDescriptor().getCcmExe()); commands.setCcmUiLog(synergySCM.getDescriptor().getCcmUiLog()); commands.setCcmEngLog(synergySCM.getDescriptor().getCcmEngLog()); - + commands.setTaskListener(listener); commands.setLauncher(launcher); - + try { - // Start Synergy. - StartCommand startCommand = new StartCommand(database, engine, username, password, remoteClient); - commands.executeSynergyCommand(path, startCommand); - String ccmAddr = startCommand.getCcmAddr(); + FilePath ccmSessionMapFile = new FilePath(path, SynergySCM.CCM_SESSION_MAP_FILE_NAME); + + CheckSessionCommand checkSessionCommand = new CheckSessionCommand(); + commands.executeSynergyCommand(path, checkSessionCommand); + String ccmAddr = checkSessionCommand.getCcmAddr(ccmSessionMapFile); + if (CheckSessionCommand.SESSION_NOT_FOUND.equals(ccmAddr)) { + // Start Synergy. + StartCommand startCommand = new StartCommand(database, engine, username, password, remoteClient); + commands.executeSynergyCommand(path, startCommand); + ccmAddr = startCommand.getCcmAddr(); + startCommand.addCcmAddrToSessionMapFile(ccmSessionMapFile); + } commands.setCcmAddr(ccmAddr); Date date = build.getTimestamp().getTime(); DateFormat format = new SimpleDateFormat("yyyyMMdd-hhmm"); String name = build.getProject().getName() + "-" + format.format(date); - + // Create baseline. if (createBaseline) { CreateProjectBaselineCommand createCommand = new CreateProjectBaselineCommand(name, project, release, purpose); - commands.executeSynergyCommand(path, createCommand); + commands.executeSynergyCommand(path, createCommand); } - + // Publish baseline. if (publishBaseline) { PublishBaselineCommand publishCommand = new PublishBaselineCommand(name); commands.executeSynergyCommand(path, publishCommand); } - + } catch (SynergyException e) { return false; } finally { // Stop Synergy. - StopCommand stopCommand = new StopCommand(); - try { - commands.executeSynergyCommand(path, stopCommand); - } catch (SynergyException e) { - return false; - } +// StopCommand stopCommand = new StopCommand(); +// try { +// commands.executeSynergyCommand(path, stopCommand); +// } catch (SynergyException e) { +// return false; +// } } } return true; } - + public void setPublish(boolean publish) { this.publish = publish; } - + public boolean isPublish() { return publish; } Index: main/java/hudson/plugins/synergy/SynergySCM.java =================================================================== --- main/java/hudson/plugins/synergy/SynergySCM.java (revision 16864) +++ main/java/hudson/plugins/synergy/SynergySCM.java (working copy) @@ -8,6 +8,7 @@ import hudson.model.TaskListener; import hudson.plugins.synergy.SynergyChangeLogSet.LogEntry; import hudson.plugins.synergy.SynergyChangeLogSet.Path; +import hudson.plugins.synergy.impl.CheckSessionCommand; import hudson.plugins.synergy.impl.CheckoutResult; import hudson.plugins.synergy.impl.Commands; import hudson.plugins.synergy.impl.CompareProjectCommand; @@ -53,6 +54,7 @@ import java.util.Map; import java.util.Set; +import javax.naming.ldap.HasControls; import javax.servlet.ServletException; import org.kohsuke.stapler.DataBoundConstructor; @@ -67,17 +69,17 @@ public class SynergySCM extends SCM implements Serializable { public static final class DescriptorImpl extends SCMDescriptor { public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); - + /** * Path to ccm executable. */ - private String ccmExe; - + private String ccmExe; + /** * Path to ccm_ui log. */ private String ccmUiLog; - + /** * Path to ccm_eng log. */ @@ -92,10 +94,10 @@ } private DescriptorImpl() { - super(SynergySCM.class, null); + super(SynergySCM.class, null); load(); - } - + } + @Override public boolean configure(StaplerRequest request) throws FormException { ccmExe = request.getParameter("synergy.ccmExe"); @@ -104,84 +106,74 @@ save(); return true; } - + @Override - public SCM newInstance(StaplerRequest req) throws FormException { - return new SynergySCM( - req.getParameter("synergy.project"), - req.getParameter("synergy.database"), - req.getParameter("synergy.release"), - req.getParameter("synergy.purpose"), - req.getParameter("synergy.username"), - req.getParameter("synergy.password"), - req.getParameter("synergy.engine"), - req.getParameter("synergy.oldProject"), - req.getParameter("synergy.baseline"), - req.getParameter("synergy.oldBaseline"), - "true".equals(req.getParameter("synergy.remoteClient")), - "true".equals(req.getParameter("synergy.detectConflict")) - ); - } - + public SCM newInstance(StaplerRequest req) throws FormException { + return new SynergySCM(req.getParameter("synergy.project"), req.getParameter("synergy.database"), req.getParameter("synergy.release"), req + .getParameter("synergy.purpose"), req.getParameter("synergy.username"), req.getParameter("synergy.password"), req + .getParameter("synergy.engine"), req.getParameter("synergy.oldProject"), req.getParameter("synergy.baseline"), req + .getParameter("synergy.oldBaseline"), "true".equals(req.getParameter("synergy.remoteClient")), "true".equals(req + .getParameter("synergy.detectConflict")), "true".equals(req.getParameter("synergy.replaceSubprojects")), "true".equals(req.getParameter("synergy.checkForUpdateWarnings")) ); + } + /** - * Checks if ccm executable exists. - */ - public void doCcmExeCheck(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - new FormFieldValidator.Executable(req,rsp).process(); - } - - + * Checks if ccm executable exists. + */ + public void doCcmExeCheck(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + new FormFieldValidator.Executable(req, rsp).process(); + } + @Override - public String getDisplayName() { + public String getDisplayName() { return "Synergy"; } - + public String getCcmExe() { - if (ccmExe==null) { + if (ccmExe == null) { return "ccm"; } else { return ccmExe; } } } - + + public static final String CCM_SESSION_MAP_FILE_NAME = "ccmSessionMap.properties"; + /** * The Synergy project name. */ private String project; - + /** * The Synergy database containing the project. */ private String database; - + /** - * The Synergy projet release. - * This is used to create baseline. + * The Synergy projet release. This is used to create baseline. */ private String release; - - /** - * The Synergy project purpose. - * This is used to create baseline. + + /** + * The Synergy project purpose. This is used to create baseline. */ private String purpose; - + /** * The Synergy engine host name. */ private String engine; - + /** * The user login */ private String username; - + /** * The user password. */ private String password; - + /** * The old project for differential delivery. */ @@ -191,83 +183,103 @@ * The baseline */ private String baseline; - + /** * The old baseline */ private String oldBaseline; - + /** * Remote client connection flag. */ private boolean remoteClient; - + /** * Detect conflict flag. */ private boolean detectConflict; - + private transient Commands commands; - + + /** + * Should subprojects be replaced? + */ + private boolean replaceSubprojects; + + /** + * Abort the build if there are updateWarnings. + */ + private boolean checkForUpdateWarnings; + @DataBoundConstructor - public SynergySCM(String project, String database, String release, String purpose, String username, String password, String engine, String oldProject, String baseline, String oldBaseline, boolean remoteClient, boolean detectConflict) { + public SynergySCM(String project, String database, String release, String purpose, String username, String password, String engine, + String oldProject, String baseline, String oldBaseline, boolean remoteClient, boolean detectConflict, boolean replaceSubprojects, boolean checkForUpdateWarnings) { this.project = project; - this.database = database; + this.database = database; this.release = release; this.purpose = purpose; this.username = username; this.password = password; this.engine = engine; this.oldProject = oldProject; - this.baseline = baseline; + this.baseline = baseline; this.oldBaseline = oldBaseline; this.remoteClient = remoteClient; this.detectConflict = detectConflict; + this.replaceSubprojects = replaceSubprojects; + this.checkForUpdateWarnings = checkForUpdateWarnings; } - - - + @Override - public boolean checkout(AbstractBuild build, Launcher launcher, FilePath path, BuildListener listener, File changeLogFile) throws IOException, InterruptedException { + public boolean checkout(AbstractBuild build, Launcher launcher, FilePath path, BuildListener listener, File changeLogFile) throws IOException, + InterruptedException { // Configure commands. commands = new Commands(); commands.setCcmExe(getDescriptor().getCcmExe()); commands.setCcmUiLog(getDescriptor().getCcmUiLog()); commands.setCcmEngLog(getDescriptor().getCcmEngLog()); - + commands.setTaskListener(listener); commands.setLauncher(launcher); - + try { - // Start Synergy. - StartCommand command = new StartCommand(database, engine, username, password, remoteClient); - commands.executeSynergyCommand(path, command); - String ccmAddr = command.getCcmAddr(); + FilePath ccmSessionMapFile = new FilePath(path, CCM_SESSION_MAP_FILE_NAME); + + CheckSessionCommand checkSessionCommand = new CheckSessionCommand(); + commands.executeSynergyCommand(path, checkSessionCommand); + String ccmAddr = checkSessionCommand.getCcmAddr(ccmSessionMapFile); + if (CheckSessionCommand.SESSION_NOT_FOUND.equals(ccmAddr)) { + // Start Synergy. + StartCommand command = new StartCommand(database, engine, username, password, remoteClient); + commands.executeSynergyCommand(path, command); + ccmAddr = command.getCcmAddr(); + command.addCcmAddrToSessionMapFile(ccmSessionMapFile); + } commands.setCcmAddr(ccmAddr); - + // Compute dynamic name. - String projectName = computeDynamicValue(build, project); + String projectName = computeDynamicValue(build, project); String oldProjectName = computeDynamicValue(build, oldProject); String baselineName = computeDynamicValue(build, baseline); String oldBaselineName = computeDynamicValue(build, oldBaseline); - + // Set role to build manager. SetRoleCommand setRoleCommand = new SetRoleCommand(SetRoleCommand.BUILD_MANAGER); commands.executeSynergyCommand(path, setRoleCommand); - + // Check projet state. - if (project!=null && project.length()!=0) { + if (project != null && project.length() != 0) { // Work on a Synergy project. CheckoutResult result = checkoutProject(path, changeLogFile, projectName, oldProjectName); - if (result!=null) { + if (result != null) { writeChangeLog(changeLogFile, result.getLogs()); - if (result.getConflicts()!=null && !result.getConflicts().isEmpty()) { + if (result.getConflicts() != null && !result.getConflicts().isEmpty()) { listener.getLogger().println("Error : conflicts detected for project " + projectName); return false; } } - } else if (baseline!=null && baseline.length()!=0) { + } else if (baseline != null && baseline.length() != 0) { // Work on a Synergy baseline. checkoutBaseline(path, changeLogFile, baselineName, oldBaselineName); } else { @@ -275,93 +287,99 @@ return false; } } catch (SynergyException e) { - return false; + return false; } finally { // Stop Synergy. - StopCommand stopCommand = new StopCommand(); - try { - commands.executeSynergyCommand(path, stopCommand); - } catch (SynergyException e) { - return false; - } + // StopCommand stopCommand = new StopCommand(); + // try { + // commands.executeSynergyCommand(path, stopCommand); + // } catch (SynergyException e) { + // return false; + // } } return true; } - + /** * "Checkout" a baseline * - * @param path Hudson workarea path - * @param changeLogFile Hudson changelog file - * @param baselineName The name of the baseline to checkout - * @param oldBaselineName The name of the old baseline (for differential delivery) + * @param path + * Hudson workarea path + * @param changeLogFile + * Hudson changelog file + * @param baselineName + * The name of the baseline to checkout + * @param oldBaselineName + * The name of the old baseline (for differential delivery) * * @throws IOException * @throws InterruptedException * @throws SynergyException */ - private void checkoutBaseline(FilePath path, File changeLogFile, String baselineName, String oldBaselineName) throws IOException, InterruptedException, SynergyException { + private void checkoutBaseline(FilePath path, File changeLogFile, String baselineName, String oldBaselineName) throws IOException, + InterruptedException, SynergyException { // Get delimiter. GetDelimiterCommand getDelim = new GetDelimiterCommand(); commands.executeSynergyCommand(path, getDelim); String delim = getDelim.getDelimiter(); - + // Get projects. String baselineObjectName = baselineName; - if (baselineObjectName.indexOf(":baseline:")==-1) { + if (baselineObjectName.indexOf(":baseline:") == -1) { baselineObjectName = baselineName + delim + "1:baseline:1"; } GetProjectInBaselineCommand projectsCommand = new GetProjectInBaselineCommand(baselineObjectName); commands.executeSynergyCommand(path, projectsCommand); List projects = projectsCommand.getProjects(); - + // Mapping of old/new projects. Map projectsMapping = new HashMap(); - + // Extract the project names. for (String newProject : projects) { String newProjectName = newProject.substring(0, newProject.indexOf(':')); projectsMapping.put(newProjectName, null); } - - // Get old projects. - if (oldBaselineName!=null && oldBaselineName.length()!=0) { + + // Get old projects. + if (oldBaselineName != null && oldBaselineName.length() != 0) { String oldBaselineObjectName = oldBaselineName; - if (oldBaselineObjectName.indexOf(":baseline:")==-1) { + if (oldBaselineObjectName.indexOf(":baseline:") == -1) { oldBaselineObjectName = oldBaselineName + delim + "1:baseline:1"; } projectsCommand = new GetProjectInBaselineCommand(oldBaselineObjectName); commands.executeSynergyCommand(path, projectsCommand); - List oldProjects = projectsCommand.getProjects(); - + List oldProjects = projectsCommand.getProjects(); + // Map each old project to a new project. - // TODO this won't work if multiple project with the same name is authorized. + // TODO this won't work if multiple project with the same name is + // authorized. Map projectNames = new HashMap(); - + // Extract project information. for (String oldProject : oldProjects) { // From "project~version:project:instance" to "project" String projectNameWithoutVersion = oldProject.substring(0, oldProject.indexOf(delim)); - + // From ""project~version:project:instance" to "project~version" String oldProjectNameWithVersion = oldProject.substring(0, oldProject.indexOf(':')); - + // Update project list. projectNames.put(projectNameWithoutVersion, oldProjectNameWithVersion); } - + for (String newProject : projects) { String newProjectNameWithoutVersion = newProject.substring(0, newProject.indexOf(delim)); String newProjectNameWithVersion = newProject.substring(0, newProject.indexOf(':')); String oldProjectNameWithVersion = projectNames.get(newProjectNameWithoutVersion); projectsMapping.put(newProjectNameWithVersion, oldProjectNameWithVersion); } - - } - + + } + // Clear workarea path.deleteContents(); - + // Checkout projects. // TODO This could be done in a one big request. Collection allEntries = new ArrayList(); @@ -370,112 +388,127 @@ Collection entries = result.getLogs(); allEntries.addAll(entries); } - + // Write change log. // TODO Task spawning on several project will be reported multiple times writeChangeLog(changeLogFile, allEntries); } - + /** * Checkout a project * - * @param path Hudson workarea path - * @param changeLogFile Hudson changelog file - * @param projectName The name of the project to checkout - * @param oldProjectName The name of the old project (for differential delivery) + * @param path + * Hudson workarea path + * @param changeLogFile + * Hudson changelog file + * @param projectName + * The name of the project to checkout + * @param oldProjectName + * The name of the old project (for differential delivery) * * @throws IOException * @throws InterruptedException * @throws SynergyException */ - private CheckoutResult checkoutStaticProject(FilePath path, File changeLogFile, String projectName, String oldProjectName) throws IOException, InterruptedException, SynergyException { + private CheckoutResult checkoutStaticProject(FilePath path, File changeLogFile, String projectName, String oldProjectName) throws IOException, + InterruptedException, SynergyException { // Compute workare path String desiredWorkArea = getCleanWorkareaPath(path); - - if (oldProjectName!=null && oldProjectName.length()!=0) { + + if (oldProjectName != null && oldProjectName.length() != 0) { // Compute difference. CompareProjectCommand compareCommand = new CompareProjectCommand(projectName, oldProjectName); commands.executeSynergyCommand(path, compareCommand); List result = compareCommand.getDifferences(); - + Collection entries = generateChangeLog(result, projectName, changeLogFile, path); copyEntries(path, entries); return new CheckoutResult(null, entries); - } else { + } else { // Create snapshot. WorkareaSnapshotCommand workareaSnapshotCommand = new WorkareaSnapshotCommand(projectName, desiredWorkArea); commands.executeSynergyCommand(path, workareaSnapshotCommand); - + // TODO compute and write changelog return null; - } + } } /** * Checkout a project * - * @param path Hudson workarea path - * @param changeLogFile Hudson changelog file - * @param projectName The name of the project to checkout - * @param oldProjectName The name of the old project (for differential delivery) + * @param path + * Hudson workarea path + * @param changeLogFile + * Hudson changelog file + * @param projectName + * The name of the project to checkout + * @param oldProjectName + * The name of the old project (for differential delivery) * * @throws IOException * @throws InterruptedException * @throws SynergyException */ - private CheckoutResult checkoutProject(FilePath path, File changeLogFile, String projectName, String oldProjectName) throws IOException, InterruptedException, SynergyException { + private CheckoutResult checkoutProject(FilePath path, File changeLogFile, String projectName, String oldProjectName) throws IOException, + InterruptedException, SynergyException { if (isStaticProject(projectName, path)) { // Clear workarea. path.deleteContents(); - + return checkoutStaticProject(path, changeLogFile, projectName, oldProjectName); } else { return checkoutDynamicProject(path, changeLogFile, projectName); } } - private CheckoutResult checkoutDynamicProject(FilePath path, File changeLogFile, String projectName) throws IOException, InterruptedException, SynergyException { + private CheckoutResult checkoutDynamicProject(FilePath path, File changeLogFile, String projectName) throws IOException, InterruptedException, + SynergyException { // Configure workarea. setAbsoluteWorkarea(path); - + // Update members. - UpdateCommand updateCommand = new UpdateCommand(projectName); + UpdateCommand updateCommand = new UpdateCommand(projectName, isReplaceSubprojects()); commands.executeSynergyCommand(path, updateCommand); - List updates = updateCommand.getUpdates(); - + List updates = updateCommand.getUpdates(); + // Generate changelog Collection logs = generateChangeLog(updates, projectName, changeLogFile, path); + if(isCheckForUpdateWarnings() && updateCommand.isUpdateWarningsExists()){ + return new CheckoutResult(updateCommand.getConflicts(), logs); + } + // Check conflicts. - List conflicts = null; - if (detectConflict) { + if (isDetectConflict()) { ProjectConflicts conflictsCommand = new ProjectConflicts(projectName); commands.executeSynergyCommand(path, conflictsCommand); - conflicts = conflictsCommand.getConflicts(); + return new CheckoutResult(conflictsCommand.getConflicts(), logs); } - return new CheckoutResult(conflicts, logs); + return new CheckoutResult(new ArrayList(), logs); } - + /** * Copy the specified entries in the workarea. - * @param ccmAddr - * @throws InterruptedException - * @throws IOException - * @throws SynergyException + * + * @param ccmAddr + * @throws InterruptedException + * @throws IOException + * @throws SynergyException */ - private void copyEntries(FilePath path, Collection entries) throws IOException, InterruptedException, SynergyException { + private void copyEntries(FilePath path, Collection entries) throws IOException, InterruptedException, SynergyException { // Iterate over the tasks. for (LogEntry entry : entries) { for (Path object : entry.getPaths()) { String id = object.getId(); - if (id.indexOf(":dir:")==-1) { + if (id.indexOf(":dir:") == -1) { String pathInProject = object.getValue(); FilePath pathInWorkarea = path.child(pathInProject); WriteObjectCommand command = new WriteObjectCommand(id, pathInWorkarea); commands.executeSynergyCommand(path, command); } - } + } } } @@ -487,36 +520,38 @@ desiredWorkArea = desiredWorkArea.replace("\\.\\", "\\"); return desiredWorkArea; } - + /** - * Replace an expression in the form ${name} in the given String - * by the value of the matching environment variable. + * Replace an expression in the form ${name} in the given String by the + * value of the matching environment variable. */ private String computeDynamicValue(AbstractBuild build, String parameterizedValue) throws IllegalStateException { - if (parameterizedValue!=null && parameterizedValue.indexOf("${")!=-1) { + if (parameterizedValue != null && parameterizedValue.indexOf("${") != -1) { int start = parameterizedValue.indexOf("${"); int end = parameterizedValue.indexOf("}", start); - String parameter = parameterizedValue.substring(start+2, end); + String parameter = parameterizedValue.substring(start + 2, end); String value = (String) build.getEnvVars().get(parameter); - if (value==null) { + if (value == null) { throw new IllegalStateException(parameter); } - return parameterizedValue.substring(0, start) + value + (parameterizedValue.length()>end+1 ? parameterizedValue.substring(end+1) : ""); + return parameterizedValue.substring(0, start) + value + + (parameterizedValue.length() > end + 1 ? parameterizedValue.substring(end + 1) : ""); } else { return parameterizedValue; } } - + /** * Check the project state. - * @return true if the project is a static project + * + * @return true if the project is a static project */ private boolean isStaticProject(String project, FilePath workspace) throws IOException, InterruptedException, SynergyException { // Get project state. GetProjectStateCommand command = new GetProjectStateCommand(project); commands.executeSynergyCommand(workspace, command); String state = command.getState(); - + // Compute result. if ("prep".equals(state) || "working".equals(state)) { // Integration testing or Development project. @@ -526,114 +561,123 @@ return true; } } - + /** * Configure the Synergy workarea for a top or subproject. - * @param project The Synergy project name - * @param relative Should the workarea be relative or asbolute - * @param launcher The Hudson launcher to use to launch commands - * @param workspace The Hudon project workspace path - * @param workarea The desired Synergy project workarea path - * @param ccmAddr The current Synergy sesison address - * @param listener The Hudson build listener - * @return True if the workarea was configured sucessfully + * + * @param project + * The Synergy project name + * @param relative + * Should the workarea be relative or asbolute + * @param launcher + * The Hudson launcher to use to launch commands + * @param workspace + * The Hudon project workspace path + * @param ccmAddr + * The current Synergy sesison address + * @param listener + * The Hudson build listener + * @return True if the workarea was configured sucessfully * @throws IOException * @throws InterruptedException - * @throws SynergyException + * @throws SynergyException */ - private void configureWorkarea(String project, boolean relative, FilePath workspace, FilePath workarea) throws IOException, InterruptedException, SynergyException { + private void configureWorkarea(String project, boolean relative, FilePath workspace) throws IOException, InterruptedException, SynergyException { // Check maintain workarea. GetProjectAttributeCommand getProjectAttributeCommand = new GetProjectAttributeCommand(project, GetProjectAttributeCommand.MAINTAIN_WORKAREA); commands.executeSynergyCommand(workspace, getProjectAttributeCommand); String maintainWorkArea = getProjectAttributeCommand.getValue(); boolean changeMaintain = false; - + if (!"TRUE".equals(maintainWorkArea)) { // If workarea is not maintain, maintain it. - SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, GetProjectAttributeCommand.MAINTAIN_WORKAREA, "TRUE"); + SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, + GetProjectAttributeCommand.MAINTAIN_WORKAREA, "TRUE"); commands.executeSynergyCommand(workspace, setProjectAttributeCommand); changeMaintain = true; } - + // Check relative/absolute wo. if (relative) { getProjectAttributeCommand = new GetProjectAttributeCommand(project, GetProjectAttributeCommand.RELATIVE); commands.executeSynergyCommand(workspace, getProjectAttributeCommand); String relativeWorkArea = getProjectAttributeCommand.getValue(); - + if (relative && !"TRUE".equals(relativeWorkArea)) { - // If asked for relative workarea, and workarea is not relative, set relative workarea. - SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, GetProjectAttributeCommand.RELATIVE, relative ? "TRUE" : "FALSE"); - commands.executeSynergyCommand(workspace, setProjectAttributeCommand); + // If asked for relative workarea, and workarea is not relative, + // set relative workarea. + SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, GetProjectAttributeCommand.RELATIVE, + relative ? "TRUE" : "FALSE"); + commands.executeSynergyCommand(workspace, setProjectAttributeCommand); } } - + // Check workarea path. getProjectAttributeCommand = new GetProjectAttributeCommand(project, GetProjectAttributeCommand.WORKAREA_PATH); commands.executeSynergyCommand(workspace, getProjectAttributeCommand); String currentWorkArea = getProjectAttributeCommand.getValue(); - String desiredWorkArea = getCleanWorkareaPath(workarea); + String desiredWorkArea = relative ? currentWorkArea : getCleanWorkareaPath(workspace); if (!currentWorkArea.equals(desiredWorkArea) || changeMaintain) { // If current workarea location is not the desired one, change it. - SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, GetProjectAttributeCommand.WORKAREA_PATH, desiredWorkArea); - commands.executeSynergyCommand(workspace, setProjectAttributeCommand); + SetProjectAttributeCommand setProjectAttributeCommand = new SetProjectAttributeCommand(project, GetProjectAttributeCommand.WORKAREA_PATH, + desiredWorkArea); + commands.executeSynergyCommand(workspace, setProjectAttributeCommand); } } - + /** * Configure the Synergy workarea for the main project and the subprojects. * - * @param launcher Launcher to use to launch command - * @param path The Hudson projet workspace path - * @param ccmAddr The current Synergy session address - * @param listener The Hudson build listener - * @return true if the Synergy workarea was configured propertly + * @param launcher + * Launcher to use to launch command + * @param path + * The Hudson projet workspace path + * @param ccmAddr + * The current Synergy session address + * @param listener + * The Hudson build listener + * @return true if the Synergy workarea was configured propertly * @throws IOException * @throws InterruptedException - * @throws SynergyException + * @throws SynergyException */ private void setAbsoluteWorkarea(FilePath path) throws IOException, InterruptedException, SynergyException { // Check main project. - configureWorkarea(project, false, path, path); - + configureWorkarea(project, false, path); + // Get subproject. SubProjectQueryCommand command = new SubProjectQueryCommand(project); try { commands.executeSynergyCommand(path, command); } catch (SynergyException e) { // 1 is ok (means the query returns nothing). - if (e.getStatus()!=1) { + if (e.getStatus() != 1) { throw e; } } List subProjects = command.getSubProjects(); - - if (subProjects!=null && subProjects.size()>0) { - GetDelimiterCommand getDelim = new GetDelimiterCommand(); - commands.executeSynergyCommand(path, getDelim); - String delimiter = getDelim.getDelimiter(); - String projetPrincipal = project.split(delimiter)[0]; + + if (subProjects != null && subProjects.size() > 0) { for (String subProject : subProjects) { - configureWorkarea(subProject, true, path, new FilePath(path, projetPrincipal)); + configureWorkarea(subProject, true, path); } - } + } } - + /** * Gets the file that stores the revision. */ public static File getRevisionFile(AbstractBuild build) { return new File(build.getRootDir(), "revision.txt"); } - + /** * Reads the revision file of the specified build. * * @return map from {@link SvnInfo#url Subversion URL} to its revision. */ - /* package */static Map parseRevisionFile(AbstractBuild build) - throws IOException { + /* package */static Map parseRevisionFile(AbstractBuild build) throws IOException { Map revisions = new HashMap(); // module -> // revision {// read the revision file of the last build @@ -651,8 +695,7 @@ continue; // invalid line? } try { - revisions.put(line.substring(0, index), Long - .parseLong(line.substring(index + 1))); + revisions.put(line.substring(0, index), Long.parseLong(line.substring(index + 1))); } catch (NumberFormatException e) { // perhaps a corrupted line. ignore } @@ -664,40 +707,46 @@ return revisions; } - + /** * Generate the changelog. - * @param names Names of the elements that have changed - * @param projects Name of the Synergy project being build and that may contain changes - * @param changeLogFile File to write the changelog into - * @param workarea The Workarea path + * + * @param names + * Names of the elements that have changed + * @param projects + * Name of the Synergy project being build and that may contain + * changes + * @param changeLogFile + * File to write the changelog into + * @param workarea + * The Workarea path * @return * @throws IOException * @throws InterruptedException * @throws SynergyException */ - private Collection generateChangeLog(List names, String projectName, File changeLogFile, FilePath workarea) throws IOException, InterruptedException, SynergyException { + private Collection generateChangeLog(List names, String projectName, File changeLogFile, FilePath workarea) throws IOException, + InterruptedException, SynergyException { // Find information about the element. Map logs = new HashMap(); DateFormat dateFormat = DateFormat.getDateTimeInstance(); - - if (names!=null) { + + if (names != null) { // Compute the subproject list for the finduse project // in case the given project is a top level project. SubProjectQueryCommand subProjectQuery = new SubProjectQueryCommand(projectName); commands.executeSynergyCommand(workarea, subProjectQuery); Set projects = new HashSet(subProjectQuery.getSubProjects()); projects.add(projectName); - + // Find the delimiter. GetDelimiterCommand getDelim = new GetDelimiterCommand(); commands.executeSynergyCommand(workarea, getDelim); String delimiter = getDelim.getDelimiter(); - // Compute the use of the subprojects in the project. Map subProjectsUse = new HashMap(); - if (projects.size()>1) { + if (projects.size() > 1) { Set set = new HashSet(); set.add(projectName); for (String project : projects) { @@ -705,27 +754,27 @@ FindUseCommand findUse = new FindUseCommand(project, set, delimiter); commands.executeSynergyCommand(workarea, findUse); String use = findUse.getPath(); - if (use!=null) { + if (use != null) { subProjectsUse.put(project, use); } } } } - - for (String name : names) { + + for (String name : names) { // Entry to use. SynergyChangeLogSet.LogEntry entry = null; - + // Find associate task. FindAssociatedTaskCommand taskCommand = new FindAssociatedTaskCommand(name); commands.executeSynergyCommand(workarea, taskCommand); List taskIds = taskCommand.getTasks(); - if (taskIds!=null && !taskIds.isEmpty()) { + if (taskIds != null && !taskIds.isEmpty()) { String taskId = taskIds.get(0); entry = logs.get(taskId); - if (entry==null) { + if (entry == null) { entry = new LogEntry(); - + // Find task info. List t = new ArrayList(1); t.add(taskId); @@ -736,27 +785,27 @@ entry.setMsg(infos.get(0).getSynopsis()); entry.setUser(infos.get(0).getResolver()); entry.setTaskId(infos.get(0).getId()); - entry.setDate(infos.get(0).getDateCompleted()==null ? null : dateFormat.format(infos.get(0).getDateCompleted())); + entry.setDate(infos.get(0).getDateCompleted() == null ? null : dateFormat.format(infos.get(0).getDateCompleted())); } logs.put(taskId, entry); } } - + // Deal with no task case (should not happen) - if (entry==null) { + if (entry == null) { entry = logs.get(null); - if (entry==null) { + if (entry == null) { entry = new LogEntry(); entry.setMsg("Unknown task"); logs.put(null, entry); } } - + // Find use of the element in the project. FindUseCommand command = new FindUseCommand(name, projects, delimiter); commands.executeSynergyCommand(workarea, command); String pathInProject = command.getPath(); - if (pathInProject!=null) { + if (pathInProject != null) { if (!pathInProject.startsWith(projectName)) { // The element is in a subproject. // TODO add the subprojet path @@ -765,47 +814,50 @@ path.setId(name); path.setValue(pathInProject); entry.addPath(path); - } + } } - } - + } + return logs.values(); } /** * Write the changelog file. - * @param changeLogFile The changelog file - * @param logs The logs + * + * @param changeLogFile + * The changelog file + * @param logs + * The logs */ private void writeChangeLog(File changeLogFile, Collection logs) { - if (logs!=null) { + if (logs != null) { PrintWriter writer = null; try { writer = new PrintWriter(changeLogFile, "UTF-8"); writer.println(""); writer.println(""); - + for (LogEntry log : logs) { writer.println(String.format("\t", log.getTaskId())); writer.println(String.format("\t\t%s", log.getTaskId())); writer.println(String.format("\t\t%s", log.getUser())); writer.println(String.format("\t\t%s", log.getDate())); writer.println(String.format("\t\t", log.getMsg())); - + writer.println("\t\t"); for (SynergyChangeLogSet.Path path : log.getPaths()) { writer.println(String.format("\t\t\t%s", path.getEditType(), path.getValue())); } writer.println("\t\t"); - + writer.println("\t"); } - + writer.println(""); } catch (IOException e) { // TODO } finally { - if (writer!=null) { + if (writer != null) { writer.close(); } } @@ -823,60 +875,67 @@ } @Override - public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath path, TaskListener listener) throws IOException, InterruptedException { + public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath path, TaskListener listener) throws IOException, + InterruptedException { // Get last build. AbstractBuild lastBuild = (AbstractBuild) project.getLastBuild(); - + // Check release. - if (release==null) { - listener.getLogger().println("The release attribute is not set. It is required for change pooling."); - return false; - } - + if (release == null) { + listener.getLogger().println("The release attribute is not set. It is required for change pooling."); + return false; + } + // No last build, build one now. - if(lastBuild==null) { - listener.getLogger().println("No existing build. Starting a new one"); - return true; - } - - // Get last build date. - Calendar date = lastBuild.getTimestamp(); - - // Configure commands. + if (lastBuild == null) { + listener.getLogger().println("No existing build. Starting a new one"); + return true; + } + + // Get last build date. + Calendar date = lastBuild.getTimestamp(); + + // Configure commands. commands = new Commands(); commands.setCcmExe(getDescriptor().getCcmExe()); commands.setCcmUiLog(getDescriptor().getCcmUiLog()); commands.setCcmEngLog(getDescriptor().getCcmEngLog()); - + commands.setTaskListener(listener); commands.setLauncher(launcher); - + try { - // Start Synergy. - StartCommand command = new StartCommand(database, engine, username, password, remoteClient); - commands.executeSynergyCommand(path, command); - String ccmAddr = command.getCcmAddr(); + FilePath ccmSessionMapFile = new FilePath(project.getWorkspace(), CCM_SESSION_MAP_FILE_NAME); + + CheckSessionCommand checkSessionCommand = new CheckSessionCommand(); + commands.executeSynergyCommand(path, checkSessionCommand); + String ccmAddr = checkSessionCommand.getCcmAddr(ccmSessionMapFile); + if (CheckSessionCommand.SESSION_NOT_FOUND.equals(ccmAddr)) { + // Start Synergy. + StartCommand startCommand = new StartCommand(database, engine, username, password, remoteClient); + commands.executeSynergyCommand(path, startCommand); + ccmAddr = startCommand.getCcmAddr(); + startCommand.addCcmAddrToSessionMapFile(ccmSessionMapFile); + } commands.setCcmAddr(ccmAddr); - + // Find completed tasks. FindCompletedSinceDateCommand findCommand = new FindCompletedSinceDateCommand(date, release); commands.executeSynergyCommand(path, findCommand); List result = findCommand.getTasks(); - return result!=null && !result.isEmpty(); + return result != null && !result.isEmpty(); } catch (SynergyException e) { return false; } finally { // Stop Synergy - StopCommand stopCommand = new StopCommand(); - try { - commands.executeSynergyCommand(path, stopCommand); - } catch (SynergyException e) { - return false; - } + // StopCommand stopCommand = new StopCommand(); + // try { + // commands.executeSynergyCommand(path, stopCommand); + // } catch (SynergyException e) { + // return false; + // } } } - - public String getProject() { return project; @@ -909,19 +968,19 @@ public void setEngine(String engine) { this.engine = engine; } - + public String getOldProject() { return oldProject; } - + public String getBaseline() { return baseline; } - + public String getOldBaseline() { return oldBaseline; } - + public boolean isRemoteClient() { return remoteClient; } @@ -929,12 +988,29 @@ public void setRemoteClient(boolean remoteClient) { this.remoteClient = remoteClient; } - + public boolean isDetectConflict() { return detectConflict; } - + public void setDetectConflict(boolean detectConflict) { this.detectConflict = detectConflict; } + + public boolean isReplaceSubprojects() { + return replaceSubprojects; + } + + public void setReplaceSubprojects(boolean replaceSubprojects) { + this.replaceSubprojects = replaceSubprojects; + } + + public boolean isCheckForUpdateWarnings(){ + return checkForUpdateWarnings; + } + + public void setCheckForUpdateWarnings(boolean checkForUpdateWarnings){ + this.checkForUpdateWarnings = checkForUpdateWarnings; + } + } Index: main/resources/hudson/plugins/synergy/SynergyFolderPublisher/config.jelly =================================================================== --- main/resources/hudson/plugins/synergy/SynergyFolderPublisher/config.jelly (revision 0) +++ main/resources/hudson/plugins/synergy/SynergyFolderPublisher/config.jelly (revision 0) @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file Index: main/resources/hudson/plugins/synergy/SynergyFolderPublisher/global.jelly =================================================================== --- main/resources/hudson/plugins/synergy/SynergyFolderPublisher/global.jelly (revision 0) +++ main/resources/hudson/plugins/synergy/SynergyFolderPublisher/global.jelly (revision 0) @@ -0,0 +1,3 @@ + + + \ No newline at end of file Index: main/resources/hudson/plugins/synergy/SynergySCM/config.jelly =================================================================== --- main/resources/hudson/plugins/synergy/SynergySCM/config.jelly (revision 16864) +++ main/resources/hudson/plugins/synergy/SynergySCM/config.jelly (working copy) @@ -20,6 +20,12 @@ + + + + + + Index: main/webapp/checkForUpdateWarnings.html =================================================================== --- main/webapp/checkForUpdateWarnings.html (revision 0) +++ main/webapp/checkForUpdateWarnings.html (revision 0) @@ -0,0 +1,14 @@ +
+Abort the build if there are some update warnings like: + +
+ --- Begin Error Reporting ---
+Update succeeded, but left some directory entries empty.
+Warning: No candidates found for directory entry META-INF:dir:33. It will be left empty!
+Warning! No selection available for directory entry 'META-INF,?:dir:33' under 'java=1' in project 'am=ebbi_sop_0_1_0'.
+
+Recommendation: Ensure that the projects to be updated are configured to update using templates.
+--- End Error Reporting ---
+
+ +
Index: main/webapp/devFolder.html =================================================================== --- main/webapp/devFolder.html (revision 0) +++ main/webapp/devFolder.html (revision 0) @@ -0,0 +1,8 @@ +
+the dev folder +
+
+
+the folder which the developers use. +
+
Index: main/webapp/intFolder.html =================================================================== --- main/webapp/intFolder.html (revision 0) +++ main/webapp/intFolder.html (revision 0) @@ -0,0 +1,8 @@ +
+the integration folder +
+
+
+all tasks from this folder will be copied to the dev folder +
+
Index: main/webapp/replaceSubprojects.html =================================================================== --- main/webapp/replaceSubprojects.html (revision 0) +++ main/webapp/replaceSubprojects.html (revision 0) @@ -0,0 +1,3 @@ +
+Specifies that subprojects can be replaced with new subprojects. Subprojects are replaced only if the other versions of those subprojects are selected by the selection rules. +
Index: main/webapp/tmp0000.html =================================================================== --- main/webapp/tmp0000.html (revision 0) +++ main/webapp/tmp0000.html (revision 0) @@ -0,0 +1,3 @@ +
+Start the session as a remote client (UNIX only) +