提交 bc66388f 编写于 作者: K kohsuke

support mark up in the text that explains why a build is pending

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@22946 71c3de6d-444a-0410-be80-ed276b4c234a
上级 b41472b4
......@@ -328,7 +328,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>stapler-jelly</artifactId>
<version>1.117</version>
<version>1.118</version>
<exclusions>
<exclusion>
<groupId>dom4j</groupId>
......
......@@ -38,6 +38,7 @@ import hudson.model.Fingerprint.RangeSet;
import hudson.model.RunMap.Constructor;
import hudson.model.Queue.WaitingItem;
import hudson.model.Queue.Executable;
import hudson.model.Queue.CauseOfBlockage;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import hudson.scm.NullSCM;
......@@ -854,37 +855,59 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
* project is building, but derived classes can also check other conditions.
*/
public boolean isBuildBlocked() {
boolean blocked = isBuilding() && !isConcurrentBuild();
if (!blocked && blockBuildWhenUpstreamBuilding()) {
AbstractProject bup = getBuildingUpstream();
if(bup!=null) {
return true;
}
return getCauseOfBlockage()!=null;
}
public String getWhyBlocked() {
CauseOfBlockage cb = getCauseOfBlockage();
return cb!=null ? cb.getShortDescription() : null;
}
/**
* Blocked because the previous build is already in progress.
*/
public static class BecauseOfBuildInProgress extends CauseOfBlockage {
private final AbstractBuild<?,?> build;
public BecauseOfBuildInProgress(AbstractBuild<?, ?> build) {
this.build = build;
}
return blocked;
public String getShortDescription() {
Executor e = build.getExecutor();
String eta = "";
if (e != null)
eta = Messages.AbstractProject_ETA(e.getEstimatedRemainingTime());
int lbn = build.getNumber();
return Messages.AbstractProject_BuildInProgress(lbn, eta);
}
}
public String getWhyBlocked() {
if (isBuilding() && !isConcurrentBuild()) {
AbstractBuild<?, ?> build = getLastBuild();
Executor e = build.getExecutor();
String eta="";
if(e!=null)
eta = Messages.AbstractProject_ETA(e.getEstimatedRemainingTime());
int lbn = build.getNumber();
return Messages.AbstractProject_BuildInProgress(lbn,eta);
}
else {
AbstractProject bup = getBuildingUpstream();
String projectName = "";
if(bup!=null) {
projectName = bup.getName();
}
return Messages.AbstractProject_UpstreamBuildInProgress(projectName);
}
/**
* Because the upstream build is in progress, and we are configured to wait for that.
*/
public static class BecauseOfUpstreamBuildInProgress extends CauseOfBlockage {
public final AbstractProject<?,?> up;
public BecauseOfUpstreamBuildInProgress(AbstractProject<?,?> up) {
this.up = up;
}
public String getShortDescription() {
return Messages.AbstractProject_UpstreamBuildInProgress(up.getName());
}
}
public CauseOfBlockage getCauseOfBlockage() {
if (isBuilding() && !isConcurrentBuild())
return new BecauseOfBuildInProgress(getLastBuild());
if (blockBuildWhenUpstreamBuilding()) {
AbstractProject<?,?> bup = getBuildingUpstream();
if (bup!=null)
return new BecauseOfUpstreamBuildInProgress(bup);
}
return null;
}
/**
* Returns the project if any of the upstream project (or itself) is either
......
......@@ -71,6 +71,7 @@ import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import org.jvnet.localizer.Localizable;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
......@@ -947,6 +948,31 @@ public class Queue extends ResourceController implements Saveable {
*/
public interface FlyweightTask extends Task {}
/**
* If a {@link Task} execution is blocked in the queue, this object represents why.
*
* <h2>View</h2>
* <tt>summary.jelly</tt> should do one-line HTML rendering to be used while rendering
* "build history" widget, next to the blocking build.
*/
public abstract static class CauseOfBlockage {
/**
* Human readable description of why the build is blocked.
*/
public abstract String getShortDescription();
/**
* Obtains a simple implementation backed by {@link Localizable}.
*/
public static CauseOfBlockage fromMessage(final Localizable l) {
return new CauseOfBlockage() {
public String getShortDescription() {
return l.toString();
}
};
}
}
/**
* Task whose execution is controlled by the queue.
*
......@@ -980,18 +1006,29 @@ public class Queue extends ResourceController implements Saveable {
* for temporary reasons.
*
* <p>
* This can be used to define mutual exclusion that goes beyond
* {@link #getResourceList()}.
* Short-hand for {@code getCauseOfBlockage()!=null}.
*/
boolean isBuildBlocked();
/**
* When {@link #isBuildBlocked()} is true, this method returns
* human readable description of why the build is blocked.
* Used for HTML rendering.
* @deprecated as of 1.330
* Use {@link CauseOfBlockage#getShortDescription()} instead.
*/
String getWhyBlocked();
/**
* If the execution of this task should be blocked for temporary reasons,
* this method returns a non-null object explaining why.
*
* <p>
* Otherwise this method returns null, indicating that the build can proceed right away.
*
* <p>
* This can be used to define mutual exclusion that goes beyond
* {@link #getResourceList()}.
*/
CauseOfBlockage getCauseOfBlockage();
/**
* Unique name of this task.
*
......@@ -1155,8 +1192,13 @@ public class Queue extends ResourceController implements Saveable {
* Gets a human-readable status message describing why it's in the queue.
*/
@Exported
public abstract String getWhy();
public final String getWhy() {
CauseOfBlockage cob = getCauseOfBlockage();
return cob!=null ? cob.getShortDescription() : null;
}
public abstract CauseOfBlockage getCauseOfBlockage();
/**
* Gets a human-readable message about the parameters of this item
* @return String
......@@ -1296,13 +1338,12 @@ public class Queue extends ResourceController implements Saveable {
return this.id - that.id;
}
@Override
public String getWhy() {
public CauseOfBlockage getCauseOfBlockage() {
long diff = timestamp.getTimeInMillis() - System.currentTimeMillis();
if (diff > 0)
return Messages.Queue_InQuietPeriod(Util.getTimeSpanString(diff));
return CauseOfBlockage.fromMessage(Messages._Queue_InQuietPeriod(Util.getTimeSpanString(diff)));
else
return Messages.Queue_Unknown();
return CauseOfBlockage.fromMessage(Messages._Queue_Unknown());
}
}
......@@ -1339,15 +1380,14 @@ public class Queue extends ResourceController implements Saveable {
super(ni);
}
@Override
public String getWhy() {
public CauseOfBlockage getCauseOfBlockage() {
ResourceActivity r = getBlockingActivity(task);
if (r != null) {
if (r == task) // blocked by itself, meaning another build is in progress
return Messages.Queue_InProgress();
return Messages.Queue_BlockedBy(r.getDisplayName());
return CauseOfBlockage.fromMessage(Messages._Queue_InProgress());
return CauseOfBlockage.fromMessage(Messages._Queue_BlockedBy(r.getDisplayName()));
}
return task.getWhyBlocked();
return task.getCauseOfBlockage();
}
}
......@@ -1363,11 +1403,10 @@ public class Queue extends ResourceController implements Saveable {
super(ni);
}
@Override
public String getWhy() {
public CauseOfBlockage getCauseOfBlockage() {
Hudson hudson = Hudson.getInstance();
if(hudson.isQuietingDown())
return Messages.Queue_HudsonIsAboutToShutDown();
return CauseOfBlockage.fromMessage(Messages._Queue_HudsonIsAboutToShutDown());
Label label = task.getAssignedLabel();
if (hudson.getNodes().isEmpty())
......@@ -1378,16 +1417,16 @@ public class Queue extends ResourceController implements Saveable {
name = label.getName();
if (label.isOffline()) {
if (label.getNodes().size() > 1)
return Messages.Queue_AllNodesOffline(name);
return CauseOfBlockage.fromMessage(Messages._Queue_AllNodesOffline(name));
else
return Messages.Queue_NodeOffline(name);
return CauseOfBlockage.fromMessage(Messages._Queue_NodeOffline(name));
}
}
if(name==null)
return Messages.Queue_WaitingForNextAvailableExecutor();
return CauseOfBlockage.fromMessage(Messages._Queue_WaitingForNextAvailableExecutor());
else
return Messages.Queue_WaitingForNextAvailableExecutorOn(name);
return CauseOfBlockage.fromMessage(Messages._Queue_WaitingForNextAvailableExecutorOn(name));
}
@Override
......
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<st:structuredMessageFormat key="description">
<st:structuredMessageArgument>
<t:jobLink job="${it.up}"/>
</st:structuredMessageArgument>
</st:structuredMessageFormat>
</j:jelly>
\ No newline at end of file
description=Upstream project {0} is already building.
\ No newline at end of file
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core">
<!-- defaults to short description -->
${it.shortDescription}
</j:jelly>
\ No newline at end of file
......@@ -45,7 +45,17 @@ THE SOFTWARE.
</a>
</j:if>
</div>
(${%pending}${h.prepend(' - ',item.why)})
<j:set var="cause" value="${item.getCauseOfBlockage()}"/>
<j:choose>
<j:when test="${cause!=null}">
(${%pending} -
<st:include it="${cause}" page="summary.jelly" />
)
</j:when>
<j:otherwise>
(${%pending})
</j:otherwise>
</j:choose>
</td>
</tr>
</j:forEach>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册