diff --git a/changelog.html b/changelog.html
index 862188aa35c5efaa8e1e0de69d72d0e55e62cc4e..3f316f00d22078102d086952adbdbac324ba9f8c 100644
--- a/changelog.html
+++ b/changelog.html
@@ -67,6 +67,9 @@ Upcoming changes
Plugin icons in the sidebar were not being properly cached.
(issue 16530)
+
+ Broadly as well as deeply nested build causes overwhelmed the UI after 1.482.
+ (issue 15747)
API typo DependecyDeclarer
corrected.
diff --git a/core/src/main/java/hudson/model/Cause.java b/core/src/main/java/hudson/model/Cause.java
index cf08e14725ce9c8cfc043c6fa817a2c0d653c5a0..911db3671978ff38fa0b652583210a9f48bbc91d 100644
--- a/core/src/main/java/hudson/model/Cause.java
+++ b/core/src/main/java/hudson/model/Cause.java
@@ -34,6 +34,7 @@ import jenkins.model.Jenkins;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nonnull;
/**
@@ -106,6 +107,10 @@ public abstract class Cause {
* Maximum depth of transitive upstream causes we want to record.
*/
private static final int MAX_DEPTH = 10;
+ /**
+ * Maximum number of transitive upstream causes we want to record.
+ */
+ private static final int MAX_LEAF = 25;
private String upstreamProject, upstreamUrl;
private int upstreamBuild;
/**
@@ -128,8 +133,9 @@ public abstract class Cause {
upstreamProject = up.getParent().getFullName();
upstreamUrl = up.getParent().getUrl();
upstreamCauses = new ArrayList();
+ AtomicInteger leaf = new AtomicInteger(MAX_LEAF);
for (Cause c : up.getCauses()) {
- upstreamCauses.add(trim(c, MAX_DEPTH));
+ upstreamCauses.add(trim(c, MAX_DEPTH, leaf));
}
}
@@ -140,7 +146,7 @@ public abstract class Cause {
this.upstreamCauses = upstreamCauses;
}
- private @Nonnull Cause trim(@Nonnull Cause c, int depth) {
+ private @Nonnull Cause trim(@Nonnull Cause c, int depth, AtomicInteger leaf) {
if (!(c instanceof UpstreamCause)) {
return c;
}
@@ -148,7 +154,11 @@ public abstract class Cause {
List cs = new ArrayList();
if (depth > 0) {
for (Cause c2 : uc.upstreamCauses) {
- cs.add(trim(c2, depth - 1));
+ if (leaf.decrementAndGet() > 0) {
+ cs.add(trim(c2, depth - 1, leaf));
+ } else {
+ cs.add(new DeeplyNestedUpstreamCause());
+ }
}
} else {
cs.add(new DeeplyNestedUpstreamCause());
diff --git a/test/src/test/java/hudson/model/CauseTest.java b/test/src/test/java/hudson/model/CauseTest.java
index e33c9a9e01b7b2c36d0f446edb81d824dacfb1f4..750a023411648316985f563d310d98a880a53235 100644
--- a/test/src/test/java/hudson/model/CauseTest.java
+++ b/test/src/test/java/hudson/model/CauseTest.java
@@ -26,6 +26,8 @@ package hudson.model;
import hudson.XmlFile;
import java.io.File;
+import java.util.concurrent.Future;
+import java.util.regex.Pattern;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
@@ -54,4 +56,27 @@ public class CauseTest {
assertFalse("too big:\n" + buildXml, buildXml.contains("1"));
}
+ @Bug(15747)
+ @Test public void broadlyNestedCauses() throws Exception {
+ FreeStyleProject a = j.createFreeStyleProject("a");
+ FreeStyleProject b = j.createFreeStyleProject("b");
+ FreeStyleProject c = j.createFreeStyleProject("c");
+ Run,?> last = null;
+ for (int i = 1; i <= 10; i++) {
+ Cause cause = last == null ? null : new Cause.UpstreamCause(last);
+ Future extends Run,?>> next1 = a.scheduleBuild2(0, cause);
+ a.scheduleBuild2(0, cause);
+ cause = new Cause.UpstreamCause(next1.get());
+ Future extends Run,?>> next2 = b.scheduleBuild2(0, cause);
+ b.scheduleBuild2(0, cause);
+ cause = new Cause.UpstreamCause(next2.get());
+ Future extends Run,?>> next3 = c.scheduleBuild2(0, cause);
+ c.scheduleBuild2(0, cause);
+ last = next3.get();
+ }
+ int count = new XmlFile(Run.XSTREAM, new File(last.getRootDir(), "build.xml")).asString().split(Pattern.quote(" 100);
+ //j.interactiveBreak();
+ }
+
}