### Eclipse Workspace Patch 1.0
#P ivy
Index: src/main/resources/hudson/ivy/Messages.properties
===================================================================
--- src/main/resources/hudson/ivy/Messages.properties (revision 34220)
+++ src/main/resources/hudson/ivy/Messages.properties (working copy)
@@ -47,3 +47,7 @@
IvyModuleSetBuild.NoSuchPropertyFile=No such property file {0} exists\nPlease verify that your Ivy settings property files are specified properly and exist in the workspace.
IvyProbeAction.DisplayName=Monitor Ivy Process
+
+IvyBuild.DownstreamDisabled=Downstream project {0} is disabled. Triggering skipped
+IvyBuild.InQueue={0} is already in the queue
+IvyBuild.Triggering=Triggering a new build of {0}
Index: src/main/java/hudson/ivy/AbstractIvyBuild.java
===================================================================
--- src/main/java/hudson/ivy/AbstractIvyBuild.java (revision 34220)
+++ src/main/java/hudson/ivy/AbstractIvyBuild.java (working copy)
@@ -23,20 +23,23 @@
*/
package hudson.ivy;
-import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
+import hudson.model.Action;
import hudson.model.BuildListener;
import hudson.model.DependencyGraph;
import hudson.model.Hudson;
-import hudson.model.Result;
import hudson.model.Run;
import hudson.model.Cause.UpstreamCause;
-import hudson.tasks.BuildTrigger;
+import hudson.model.DependencyGraph.Dependency;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import java.util.Set;
public abstract class AbstractIvyBuild
,B extends AbstractIvyBuild
> extends AbstractBuild
{
@@ -57,90 +60,61 @@
public AbstractIvyBuild(P project, File buildDir) throws IOException {
super(project, buildDir);
}
-
+
/**
+ *
* Schedules all the downstream builds.
- * Returns immediately if build result doesn't meet the required level
- * (as specified by {@link BuildTrigger}, or {@link Result#SUCCESS} if none).
- *
+ *
+ *
+ * If a downstream project will end up being triggered by a longer route
+ * then it is not triggered.
+ *
+ *
* @param listener
- * Where the progress reports go.
+ * Where the progress reports go.
*/
protected final void scheduleDownstreamBuilds(BuildListener listener) {
- BuildTrigger bt = getParent().getPublishersList().get(BuildTrigger.class);
- if (getResult().isWorseThan(bt!=null ? bt.getThreshold() : Result.SUCCESS)) return;
+ final DependencyGraph graph = Hudson.getInstance().getDependencyGraph();
+ List downstreamProjects = new ArrayList(
+ graph.getDownstreamDependencies(getParent()));
+ // Sort topologically
+ Collections.sort(downstreamProjects, new Comparator() {
+ public int compare(Dependency lhs, Dependency rhs) {
+ // Swapping lhs/rhs to get reverse sort:
+ return graph.compare(rhs.getDownstreamProject(), lhs.getDownstreamProject());
+ }
+ });
- // trigger dependency builds
- for( AbstractProject,?> down : getParent().getDownstreamProjects()) {
- if(debug)
- listener.getLogger().println("Considering whether to trigger "+down+" or not");
-
- // if the downstream module depends on multiple modules,
- // only trigger them when all the upstream dependencies are updated.
- boolean trigger = true;
-
- if (down.isInQueue()) {
- if(debug)
- listener.getLogger().println(" -> No, because downstream is already in queue");
- trigger = false;
- }
- // Check to see if any of its upstream dependencies are already building or in queue.
- else if (areUpstreamsBuilding(down, getParent())) {
- if(debug)
- listener.getLogger().println(" -> No, because downstream has dependencies already building or in queue");
- trigger = false;
+ for (Dependency dep : downstreamProjects) {
+ AbstractProject,?> p = dep.getDownstreamProject();
+ if (p.isDisabled()) {
+ listener.getLogger().println(Messages.IvyBuild_DownstreamDisabled(p.getFullDisplayName()));
+ continue;
}
- // Check to see if any of its upstream dependencies are in this list of downstream projects.
- else if (inDownstreamProjects(down)) {
+ List buildActions = new ArrayList();
+ if (dep.shouldTriggerBuild(this, listener, buildActions)) {
if(debug)
- listener.getLogger().println(" -> No, because downstream has dependencies in the downstream projects list");
- trigger = false;
- }
- else {
- AbstractBuild,?> dlb = down.getLastBuild(); // can be null.
- for (AbstractIvyProject up : Util.filter(down.getUpstreamProjects(),AbstractIvyProject.class)) {
- Run ulb;
- if(up==getParent()) {
- // the current build itself is not registered as lastSuccessfulBuild
- // at this point, so we have to take that into account. ugly.
- if(getResult()==null || !getResult().isWorseThan(Result.UNSTABLE))
- ulb = this;
- else
- ulb = up.getLastSuccessfulBuild();
- } else
- ulb = up.getLastSuccessfulBuild();
- if(ulb==null) {
- // if no usable build is available from the upstream,
- // then we have to wait at least until this build is ready
- if(debug)
- listener.getLogger().println(" -> No, because another upstream "+up+" for "+down+" has no successful build");
- trigger = false;
- break;
+ listener.getLogger().println("Considering whether to trigger "+p+" or not");
+
+ if (inDownstreamProjects(p)) {
+ if(debug)
+ listener.getLogger().println(" -> No, because downstream has dependencies in the downstream projects list");
+ } else {
+ if(p.scheduleBuild(p.getQuietPeriod(), new UpstreamCause((Run,?>)this))) {
+ listener.getLogger().println(Messages.IvyBuild_Triggering(p.getFullDisplayName()));
+ } else {
+ listener.getLogger().println(Messages.IvyBuild_InQueue(p.getFullDisplayName()));
}
-
- // if no record of the relationship in the last build
- // is available, we'll just have to assume that the condition
- // for the new build is met, or else no build will be fired forever.
- if(dlb==null) continue;
- int n = dlb.getUpstreamRelationship(up);
- if(n==-1) continue;
-
- assert ulb.getNumber()>=n;
}
}
-
- if(trigger) {
- listener.getLogger().println(Messages.IvyBuild_Triggering(down.getName()));
- down.scheduleBuild(new UpstreamCause((Run,?>)this));
- }
}
}
- private boolean inDownstreamProjects(AbstractProject downstreamProject) {
+ private boolean inDownstreamProjects(AbstractProject,?> downstreamProject) {
DependencyGraph graph = Hudson.getInstance().getDependencyGraph();
Set tups = graph.getTransitiveUpstream(downstreamProject);
- for (AbstractProject tup : tups) {
+ for (AbstractProject,?> tup : tups) {
for (AbstractProject,?> dp : getParent().getDownstreamProjects()) {
if(dp!=getParent() && dp!=downstreamProject && dp==tup)
return true;
@@ -148,33 +122,4 @@
}
return false;
}
-
-
- /**
- * Determines whether any of the upstream project are either
- * building or in the queue.
- *
- * This means eventually there will be an automatic triggering of
- * the given project (provided that all builds went smoothly.)
- *
- * @param downstreamProject
- * The AbstractProject we want to build.
- * @param excludeProject
- * An AbstractProject to exclude - if we see this in the transitive
- * dependencies, we're not going to bother checking to see if it's
- * building. For example, pass the current parent project to be sure
- * that it will be ignored when looking for building dependencies.
- * @return
- * True if any upstream projects are building or in queue, false otherwise.
- */
- private boolean areUpstreamsBuilding(AbstractProject downstreamProject,
- AbstractProject excludeProject) {
- DependencyGraph graph = Hudson.getInstance().getDependencyGraph();
- Set tups = graph.getTransitiveUpstream(downstreamProject);
- for (AbstractProject tup : tups) {
- if(tup!=excludeProject && (tup.isBuilding() || tup.isInQueue()))
- return true;
- }
- return false;
- }
}