| 1 package org.antmod.tasks; 2 3 import java.io.File ; 4 import java.io.IOException ; 5 6 import org.antmod.conf.AntmodProperties; 7 import org.antmod.descriptor.DescriptorStoreFactory; 8 import org.antmod.descriptor.ReleaseDescriptor; 9 import org.antmod.scm.ScmDifference; 10 import org.antmod.scm.ScmSystem; 11 import org.antmod.scm.ScmSystemFactory; 12 import org.antmod.scm.ScmVersion; 13 import org.antmod.util.AntUtil; 14 import org.apache.commons.io.FileUtils; 15 import org.apache.commons.io.HexDump; 16 import org.apache.commons.lang.StringUtils; 17 import org.apache.tools.ant.BuildException; 18 import org.apache.tools.ant.Project; 19 import org.apache.tools.ant.Task; 20 import org.apache.tools.ant.types.EnumeratedAttribute; 21 22 47 public class MergeToBranchTask extends Task { 48 private String descriptorName; 49 private String moduleName; 50 private TargetVersionInfo targetVersion; 51 52 53 56 public MergeToBranchTask() { 57 } 58 59 public void setDescriptor(String descriptorName) { 60 this.descriptorName = descriptorName; 61 } 62 63 public void setModuleName(String moduleName) { 64 if (moduleName != null) { 65 moduleName = moduleName.trim(); 66 } 67 this.moduleName = moduleName; 68 } 69 70 public void setTargetVersion(TargetVersionInfo targetVersion) { 71 this.targetVersion = targetVersion; 72 } 73 74 private boolean isMergeToTrunk() { 75 return this.targetVersion.getValue().equals(TargetVersionInfo.TRUNK); 76 } 77 78 83 protected String getIntroductionText() { 84 if (isMergeToTrunk()) { 85 return "Merge & commit branch changes to the trunk"; 86 } else { 87 return "Merge & commit trunk changes to latest branch"; 88 } 89 } 90 91 96 protected boolean askUserConfirmation(ScmVersion localVersion, ScmVersion targetVersion) { 97 String isOkay = AntUtil.ask(getProject(), "Merge & commit changes from '" + localVersion + "' to '" + targetVersion + "' now? ", "yes,no"); 98 return "yes".equalsIgnoreCase(isOkay); 99 } 100 101 105 protected void commitMergedChanges(ScmSystem scm, File checkoutDir, ScmVersion localVersion, ScmVersion targetVersion) { 106 logWarning("-- Committing merged changes..."); 107 scm.doCommit(checkoutDir, "Antmod " + getTaskName() + " commit from " + ((isMergeToTrunk()) ? "'" + localVersion + "'" : "trunk") + " to " + ((isMergeToTrunk()) ? "trunk" : "latest branch")); 108 } 109 110 114 public void execute() throws BuildException { 115 if (this.moduleName == null) { 116 throw new BuildException("FAIL: 'modulename' attribute of " + getTaskName() + "task has to be set."); 117 } 118 if (this.descriptorName == null) { 119 throw new BuildException("FAIL: 'descriptor' attribute of " + getTaskName() + "task has to be set."); 120 } 121 if (this.targetVersion == null) { 122 throw new BuildException("FAIL: 'targetVersion' attribute of " + getTaskName() + "task has to be set."); 123 } 124 logWarning("Intro: " + getIntroductionText()); 125 logWarning(""); 126 127 ReleaseDescriptor descriptor = DescriptorStoreFactory.getConfiguredDescriptorStore().getReleaseDescriptor(this.descriptorName); 129 ReleaseDescriptor.Module module = descriptor.getModuleByName(this.moduleName); 130 ScmSystem scm = ScmSystemFactory.getScmSystemByName(module.getRepos()); 131 132 ScmVersion localVersion = scm.getLocalVersion(getModuleDir()); 134 if (isMergeToTrunk()) { 135 if (localVersion.isTrunk()) { 136 throw new BuildException(getTaskName() + " FAILED: you do not have a branch of module '"+this.moduleName+"' checked out (trunk is currently checked out)."); 137 } 138 } else { 139 if (!localVersion.isTrunk()) { 140 throw new BuildException(getTaskName() + " FAILED: trunk of module '"+this.moduleName+"' is currently not checked out ("+localVersion+" is currently checked out)."); 141 } 142 } 143 144 if (!scm.isUpToDate(getModuleDir())) { 146 throw new BuildException(getTaskName() + " FAILED: local checkout of module '"+this.moduleName+"' is NOT up-to-date or has local changes."); 147 } 148 149 ScmVersion targetVersion = null; 151 if (isMergeToTrunk()) { 152 targetVersion = ScmVersion.getTrunkBranch(this.moduleName); 153 } else { 154 targetVersion = scm.getLatestVersion(getModuleDir()); 155 if (targetVersion == null) { 156 throw new BuildException("Could not find a latest branch for module " + this.moduleName); 157 } 158 } 159 160 logWarning("-- Checking for conflicts with " + ((isMergeToTrunk()) ? "'" : "latest branch '") + targetVersion + "'..."); 162 ScmDifference[] diffs = scm.getDifferences(targetVersion, localVersion); 163 if (diffs.length == 0) { 164 logWarning("-- Nothing to do - no changes between local '" + localVersion + "' and '"+targetVersion+"'"); 165 return; 166 } 167 for (int i = diffs.length; i -- > 0;) { 168 174 if (diffs[i].hasConflict()) { 175 logWarning("-- CONFLICT in file '" + diffs[i].getFilename() + "':" + HexDump.EOL + diffs[i].getLog()); 176 throw new BuildException(getTaskName() + " FAILED: local '" + localVersion + "' of module '"+this.moduleName+"' has conflict with '" + targetVersion + "' in file '"+diffs[i].getFilename()+"'."); 177 } 178 } 179 logWarning("-- No conflicts were found."); 180 181 logWarning(""); 183 if (!askUserConfirmation(localVersion, targetVersion)) { 184 return; 185 } 186 187 File localDir = new File (AntmodProperties.getProperty("antmod.local.dir")); 189 File mtbDir = new File (localDir, getTaskName()); 190 File checkoutDir = new File (mtbDir, this.descriptorName + "_" + this.moduleName + "_" + targetVersion + File.separator + this.moduleName); 191 if (checkoutDir.exists()) { 192 try { 193 FileUtils.deleteDirectory(checkoutDir); 194 } catch (IOException e) { 195 throw new BuildException(e); 196 } 197 } 198 if (!checkoutDir.mkdirs() && !checkoutDir.exists()) { 199 throw new BuildException(getTaskName() + " FAILED: could not create temp directory '"+checkoutDir+"'"); 200 } 201 logWarning("-- Temp checkout " + ((isMergeToTrunk()) ? "'" : "latest branch '") + targetVersion + "' to ${antmod.local.dir}..." ); 202 scm.doCheckout(this.moduleName, checkoutDir, targetVersion, true); 203 logWarning(""); 204 205 logWarning("-- Merging '" + localVersion + "' changes to temp checkout of " + ((isMergeToTrunk()) ? "trunk" : "latest branch") + "..."); 207 scm.doMerge(checkoutDir, localVersion); 208 if (!StringUtils.isBlank(scm.getErrorOutput())) { 209 logWarning("-- Merging FAILED: " + scm.getErrorOutput()); 210 throw new BuildException("Merging failed, checkout " + ((isMergeToTrunk()) ? "the trunk (using 'pickversion') of this module and use 'mergefrombranch'" : "the '" + targetVersion + "' branch (using 'pickversion') of this module and use 'mergefromtrunk'") + " to resolve. This usually happens when '" + getTaskName() + "' is executed twice with the same target branch of the same module."); 211 } 212 logWarning(""); 213 214 commitMergedChanges(scm, checkoutDir, localVersion, targetVersion); 216 logWarning(""); 217 218 try { 220 FileUtils.deleteDirectory(checkoutDir.getParentFile()); 221 } catch (IOException e) { 222 throw new BuildException(e); 223 } 224 225 logWarning("-- " + getTaskName() + " completed"); 226 } 227 228 231 private File getModuleDir() { 232 if (this.moduleName == null) { 233 throw new RuntimeException ("Cannot return valid moduledir because 'moduleName' attribute is not set."); 234 } 235 if (new File (getProject().getBaseDir(), AntmodProperties.getProperty("antmod.release.metadata.file")).exists()) { 236 return new File (getProject().getBaseDir(), this.moduleName); 237 } else { 238 return new File (getProject().getBaseDir().getParentFile(), this.moduleName); 239 } 240 } 241 242 245 protected void logWarning(String msg) { 246 log(msg, Project.MSG_WARN); 247 } 248 249 255 public static class TargetVersionInfo extends EnumeratedAttribute { 256 257 258 public static String LATESTBRANCH = "latestbranch"; 259 260 261 public static String TRUNK = "trunk"; 262 263 private static String [] values = 264 new String []{ 265 LATESTBRANCH, 266 TRUNK 267 }; 268 269 public String [] getValues() { 270 return TargetVersionInfo.values; 271 } 272 273 } 274 } 275 | Popular Tags |