Skip to content

Commit 7144158

Browse files
committed
Deduplicate build causes in tooltip and build overview
fixes jenkinsci#16557
1 parent 9b6147f commit 7144158

File tree

6 files changed

+52
-4
lines changed

6 files changed

+52
-4
lines changed

core/src/main/java/hudson/model/Cause.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@
3636
import hudson.util.XStream2;
3737
import java.util.ArrayList;
3838
import java.util.Arrays;
39+
import java.util.Collections;
3940
import java.util.HashSet;
41+
import java.util.LinkedHashMap;
4042
import java.util.List;
43+
import java.util.Map;
4144
import java.util.Objects;
4245
import java.util.Set;
4346
import jenkins.model.Jenkins;
@@ -167,6 +170,7 @@ public static class UpstreamCause extends Cause {
167170
@Deprecated
168171
private transient Cause upstreamCause;
169172
private @NonNull List<Cause> upstreamCauses;
173+
private transient Map<Cause, Integer> causeBag = new LinkedHashMap<>();
170174

171175
/**
172176
* @deprecated since 2009-02-28
@@ -190,13 +194,28 @@ public UpstreamCause(Run<?, ?> up) {
190194
}
191195
upstreamCauses.add(trim(c, MAX_DEPTH, traversed));
192196
}
197+
fillCauseBag();
193198
}
194199

195200
private UpstreamCause(String upstreamProject, int upstreamBuild, String upstreamUrl, @NonNull List<Cause> upstreamCauses) {
196201
this.upstreamProject = upstreamProject;
197202
this.upstreamBuild = upstreamBuild;
198203
this.upstreamUrl = upstreamUrl;
199204
this.upstreamCauses = upstreamCauses;
205+
fillCauseBag();
206+
}
207+
208+
private void fillCauseBag() {
209+
if (causeBag == null) {
210+
causeBag = new LinkedHashMap<>();
211+
}
212+
for (Cause c : upstreamCauses) {
213+
causeBag.compute(c, (unused, cnt) -> cnt == null ? 1 : cnt + 1);
214+
}
215+
}
216+
217+
public Map<Cause, Integer> getCauseCounts() {
218+
return Collections.unmodifiableMap(causeBag);
200219
}
201220

202221
@Override
@@ -351,6 +370,7 @@ public static class ConverterImpl extends XStream2.PassthruConverter<UpstreamCau
351370
uc.upstreamCause = null;
352371
OldDataMonitor.report(context, "1.288");
353372
}
373+
uc.fillCauseBag();
354374
}
355375
}
356376

@@ -359,6 +379,16 @@ public static class DeeplyNestedUpstreamCause extends Cause {
359379
return "(deeply nested causes)";
360380
}
361381

382+
@Override
383+
public int hashCode() {
384+
return 11;
385+
}
386+
387+
@Override
388+
public boolean equals(Object obj) {
389+
return obj instanceof DeeplyNestedUpstreamCause;
390+
}
391+
362392
@Override public String toString() {
363393
return "JENKINS-14814";
364394
}

core/src/main/java/hudson/model/Queue.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,6 +2399,14 @@ public final List<Cause> getCauses() {
23992399
return Collections.emptyList();
24002400
}
24012401

2402+
@Restricted(DoNotUse.class) // used from Jelly
2403+
public final Map<Cause, Integer> getCauseCounts() {
2404+
CauseAction ca = getAction(CauseAction.class);
2405+
if (ca != null)
2406+
return ca.getCauseCounts();
2407+
return Collections.emptyMap();
2408+
}
2409+
24022410
@Restricted(DoNotUse.class) // used from Jelly
24032411
@Override
24042412
public String getCausesDescription() {

core/src/main/resources/hudson/model/Cause/UpstreamCause/description.jelly

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ THE SOFTWARE.
4141
</j:otherwise>
4242
</j:choose>
4343

44-
<j:if test="${!it.upstreamCauses.isEmpty()}">
44+
<j:set var="causeCounts" value="${it.causeCounts}" />
45+
<j:if test="${!causeCounts.isEmpty()}">
4546
<br />${%caused_by}
4647
<ul>
47-
<j:forEach var="c" items="${it.upstreamCauses}">
48-
<li><st:include page="description.jelly" it="${c}" /></li>
48+
<j:forEach var="c" items="${causeCounts.entrySet()}">
49+
<li><st:include page="description.jelly" it="${c.key}" />
50+
<j:if test="${c.value > 1}"><st:nbsp/>${%Ntimes(c.value)}</j:if><br/>
51+
</li>
4952
</j:forEach>
5053
</ul>
5154
</j:if>

core/src/main/resources/hudson/model/Cause/UpstreamCause/description.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
started_by_project=Started by upstream project <a class="model-link model-link--float" href="{3}/{2}">{0}</a> build number <a class="model-link model-link--float" href="{3}/{2}{1}/">{1}</a>
2424
started_by_project_with_deleted_build=Started by upstream project <a class="model-link model-link--float" href="{3}/{2}">{0}</a> build number {1}
2525
caused_by=originally caused by:
26+
Ntimes=({0} times)

core/src/main/resources/lib/hudson/queue.jelly

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,13 @@ THE SOFTWARE.
7474
<j:set var="stuck" value="${item.isStuck()}"/>
7575
<j:choose>
7676
<j:when test="${h.hasPermission(item.task,item.task.READ)}">
77+
<j:set var="causeDescription">
78+
<j:forEach var="entry" items="${item.causeCounts.entrySet()}">${entry.key.shortDescription}<j:if test="${entry.value > 1}"><st:nbsp/>${%Ntimes(entry.value)}</j:if><br/>
79+
</j:forEach>${item.why} ${item.params}
80+
${%WaitingFor(item.inQueueForString)}
81+
</j:set>
7782
<a href="${rootURL}/${item.task.url}" class="model-link inside tl-tr"
78-
tooltip="${item.causesDescription} ${item.why} ${item.params} \n ${%WaitingFor(item.inQueueForString)}"
83+
data-html-tooltip="${causeDescription}"
7984
data-tooltip-append-to-parent="true">
8085
<l:breakable value="${item.displayName}"/>
8186
</a>

core/src/main/resources/lib/hudson/queue.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ Build\ Queue=Build Queue{0,choice,0#|0< ({0,number})}
22
Filtered\ Build\ Queue=Filtered Build Queue{0,choice,0#|0< ({0,number})}
33
WaitingFor=Waiting for {0}
44
confirm=Are you sure you want to cancel the queued run of {0}?
5+
Ntimes=({0} times)

0 commit comments

Comments
 (0)