1 package hudson.model; 2 3 import hudson.Launcher; 4 import hudson.Proc.LocalProc; 5 import hudson.Util; 6 import hudson.tasks.Fingerprinter.FingerprintAction; 7 import hudson.tasks.test.AbstractTestResultAction; 8 import hudson.maven.MavenBuild; 9 import static hudson.model.Hudson.isWindows; 10 import hudson.model.listeners.SCMListener; 11 import hudson.model.Fingerprint.RangeSet; 12 import hudson.model.Fingerprint.BuildPtr; 13 import hudson.scm.CVSChangeLogParser; 14 import hudson.scm.ChangeLogParser; 15 import hudson.scm.ChangeLogSet; 16 import hudson.scm.ChangeLogSet.Entry; 17 import hudson.scm.SCM; 18 import org.kohsuke.stapler.StaplerRequest; 19 import org.kohsuke.stapler.StaplerResponse; 20 import org.xml.sax.SAXException ; 21 22 import javax.servlet.ServletException ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.io.PrintStream ; 26 import java.util.Calendar ; 27 import java.util.Map ; 28 import java.util.HashMap ; 29 import java.util.Collections ; 30 31 39 public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends Run<P,R> implements Runnable { 40 41 45 private String builtOn; 46 47 51 private ChangeLogParser scm; 52 53 56 private volatile transient ChangeLogSet<? extends Entry> changeSet; 57 58 protected AbstractBuild(P job) throws IOException { 59 super(job); 60 } 61 62 protected AbstractBuild(P job, Calendar timestamp) { 63 super(job, timestamp); 64 } 65 66 protected AbstractBuild(P project, File buildDir) throws IOException { 67 super(project, buildDir); 68 } 69 70 public final P getProject() { 71 return getParent(); 72 } 73 74 77 public Node getBuiltOn() { 78 if(builtOn==null) 79 return Hudson.getInstance(); 80 else 81 return Hudson.getInstance().getSlave(builtOn); 82 } 83 84 87 public String getBuiltOnStr() { 88 return builtOn; 89 } 90 91 protected abstract class AbstractRunner implements Runner { 92 96 protected Launcher launcher; 97 98 101 protected final Node getCurrentNode() { 102 return Executor.currentExecutor().getOwner().getNode(); 103 } 104 105 public Result run(BuildListener listener) throws Exception { 106 Node node = Executor.currentExecutor().getOwner().getNode(); 107 assert builtOn==null; 108 builtOn = node.getNodeName(); 109 110 launcher = node.createLauncher(listener); 111 if(node instanceof Slave) 112 listener.getLogger().println("Building remotely on "+node.getNodeName()); 113 114 if(checkout(listener)) 115 return Result.FAILURE; 116 117 Result result = doRun(listener); 118 if(result!=null) 119 return result; 121 if(getResult()==null || getResult()==Result.SUCCESS) 122 createLastSuccessfulLink(listener); 123 124 return Result.SUCCESS; 125 } 126 127 private void createLastSuccessfulLink(BuildListener listener) { 128 if(!isWindows()) { 129 try { 130 new LocalProc(new String []{"rm","-f","../lastSuccessful"},new String [0],listener.getLogger(),getProject().getBuildDir()).join(); 132 133 int r = new LocalProc(new String []{ 134 "ln","-s","builds/"+getId(),"../lastSuccessful"}, 135 new String [0],listener.getLogger(),getProject().getBuildDir()).join(); 136 if(r!=0) 137 listener.getLogger().println("ln failed: "+r); 138 } catch (IOException e) { 139 PrintStream log = listener.getLogger(); 140 log.println("ln failed"); 141 Util.displayIOException(e,listener); 142 e.printStackTrace( log ); 143 } 144 } 145 } 146 147 private boolean checkout(BuildListener listener) throws Exception { 148 if(!project.checkout(AbstractBuild.this,launcher,listener,new File (getRootDir(),"changelog.xml"))) 149 return true; 150 151 SCM scm = project.getScm(); 152 153 AbstractBuild.this.scm = scm.createChangeLogParser(); 154 AbstractBuild.this.changeSet = AbstractBuild.this.calcChangeSet(); 155 156 for (SCMListener l : Hudson.getInstance().getSCMListeners()) 157 l.onChangeLogParsed(AbstractBuild.this,listener,changeSet); 158 return false; 159 } 160 161 170 protected abstract Result doRun(BuildListener listener) throws Exception ; 171 } 172 173 178 public ChangeLogSet<? extends Entry> getChangeSet() { 179 if(scm==null) 180 scm = new CVSChangeLogParser(); 181 182 if(changeSet==null) changeSet = calcChangeSet(); 184 return changeSet; 185 } 186 187 190 public boolean hasChangeSetComputed() { 191 File changelogFile = new File (getRootDir(), "changelog.xml"); 192 return changelogFile.exists(); 193 } 194 195 private ChangeLogSet<? extends Entry> calcChangeSet() { 196 File changelogFile = new File (getRootDir(), "changelog.xml"); 197 if(!changelogFile.exists()) 198 return ChangeLogSet.createEmpty(this); 199 200 try { 201 return scm.parse(this,changelogFile); 202 } catch (IOException e) { 203 e.printStackTrace(); 204 } catch (SAXException e) { 205 e.printStackTrace(); 206 } 207 return ChangeLogSet.createEmpty(this); 208 } 209 210 @Override 211 public Map <String ,String > getEnvVars() { 212 Map <String ,String > env = super.getEnvVars(); 213 214 JDK jdk = project.getJDK(); 215 if(jdk !=null) 216 jdk.buildEnvVars(env); 217 project.getScm().buildEnvVars(env); 218 219 return env; 220 } 221 222 public Calendar due() { 223 return timestamp; 224 } 225 226 230 public abstract AbstractTestResultAction getTestResultAction(); 231 232 235 public abstract void run(); 236 237 243 @Override 244 public String getWhyKeepLog() { 245 for (Map.Entry <AbstractProject, RangeSet> e : getDownstreamBuilds().entrySet()) { 248 AbstractProject<?,?> p = e.getKey(); 249 if(!p.isKeepDependencies()) continue; 250 251 for (AbstractBuild build : p.getBuilds()) { 253 if(e.getValue().includes(build.getNumber())) 254 return "kept because of "+build; 255 } 256 } 257 258 return super.getWhyKeepLog(); 259 } 260 261 269 public RangeSet getDownstreamRelationship(AbstractProject that) { 270 RangeSet rs = new RangeSet(); 271 272 FingerprintAction f = getAction(FingerprintAction.class); 273 if(f==null) return rs; 274 275 for (Fingerprint e : f.getFingerprints().values()) { 277 BuildPtr o = e.getOriginal(); 278 if(o!=null && o.is(this)) 279 rs.add(e.getRangeSet(that)); 280 } 281 282 return rs; 283 } 284 285 293 public int getUpstreamRelationship(AbstractProject that) { 294 FingerprintAction f = getAction(FingerprintAction.class); 295 if(f==null) return -1; 296 297 int n = -1; 298 299 for (Fingerprint e : f.getFingerprints().values()) { 301 BuildPtr o = e.getOriginal(); 302 if(o!=null && o.is(that)) 303 n = Math.max(n,o.getNumber()); 304 } 305 306 return n; 307 } 308 309 317 public Map <AbstractProject,RangeSet> getDownstreamBuilds() { 318 Map <AbstractProject,RangeSet> r = new HashMap <AbstractProject,RangeSet>(); 319 for (AbstractProject p : getParent().getDownstreamProjects()) { 320 if(p.isFingerprintConfigured()) 321 r.put(p,getDownstreamRelationship(p)); 322 } 323 return r; 324 } 325 326 330 public Map <AbstractProject,Integer > getUpstreamBuilds() { 331 Map <AbstractProject,Integer > r = new HashMap <AbstractProject,Integer >(); 332 for (AbstractProject p : getParent().getUpstreamProjects()) { 333 int n = getUpstreamRelationship(p); 334 if(n>=0) 335 r.put(p,n); 336 } 337 return r; 338 } 339 340 343 public Map <AbstractProject,DependencyChange> getDependencyChanges(AbstractBuild from) { 344 if(from==null) return Collections.emptyMap(); FingerprintAction n = this.getAction(FingerprintAction.class); 346 FingerprintAction o = from.getAction(FingerprintAction.class); 347 if(n==null || o==null) return Collections.emptyMap(); 348 349 Map <AbstractProject,Integer > ndep = n.getDependencies(); 350 Map <AbstractProject,Integer > odep = o.getDependencies(); 351 352 Map <AbstractProject,DependencyChange> r = new HashMap <AbstractProject,DependencyChange>(); 353 354 for (Map.Entry <AbstractProject,Integer > entry : odep.entrySet()) { 355 AbstractProject p = entry.getKey(); 356 Integer oldNumber = entry.getValue(); 357 Integer newNumber = ndep.get(p); 358 if(newNumber!=null && oldNumber.compareTo(newNumber)<0) { 359 r.put(p,new DependencyChange(p,oldNumber,newNumber)); 360 } 361 } 362 363 return r; 364 } 365 366 369 public static final class DependencyChange { 370 373 public final AbstractProject project; 374 377 public final int fromId; 378 381 public final AbstractBuild from; 382 385 public final int toId; 386 387 public final AbstractBuild to; 388 389 public DependencyChange(AbstractProject<?,?> project, int fromId, int toId) { 390 this.project = project; 391 this.fromId = fromId; 392 this.toId = toId; 393 this.from = project.getBuildByNumber(fromId); 394 this.to = project.getBuildByNumber(toId); 395 } 396 } 397 398 399 410 public synchronized void doStop( StaplerRequest req, StaplerResponse rsp ) throws IOException , ServletException { 411 Executor e = getExecutor(); 412 if(e!=null) 413 e.doStop(req,rsp); 414 else 415 rsp.forwardToPreviousPage(req); 417 } 418 } 419 | Popular Tags |