提交 ed7828b9 编写于 作者: A Alex Earl

Merge branch 'scmpolllistener'

......@@ -26,4 +26,3 @@ All about Jenkins CI can be found on our [website]. Follow us on Twitter @[jenki
[GitHub]: https://github.com/jenkinsci/jenkins
[website]: http://jenkins-ci.org
[jenkinsci]: http://twitter.com/jenkinsci
......@@ -54,6 +54,30 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
</ul>
</div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.545>What's new in 1.545</a> <!--=DATE=--></h3>
<ul class=image>
<li class=bug>
<code>CannotResolveClassException</code> breaks loading of entire containing folder, not just one job.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20951">issue 20951</a>)
<li class=bug>
Better robustness against XML deserialization errors.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21024">issue 21024</a>)
<li class=bug>
Minimizing disk I/O while loading the <em>names</em> of build records during Jenkins startup.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21078">issue 21078</a>)
<li class=bug>
Avoiding serializing the owning build as part of a test result action, as this can lead to errors later.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18410">issue 18410</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.544>What's new in 1.544</a> (2013/12/15)</h3>
<ul class=image>
<li class=bug>
RingBufferLogHandler throws ArrayIndexOutOfBoundsException after int-overflow.
......@@ -67,6 +91,9 @@ Upcoming changes</a>
<li class=bug>
<code>groovysh</code> command did not work in authenticated Jenkins instances.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17929">issue 17929</a>)
<li class=bug>
Avoid eagerly loading all builds when displaying lists of them (<i>Build History</i> and <i>Build Time Trend</i> UIs).
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20892">issue 20892</a>)
<li class=bug>
Error page should be visible even if the anonymous user does not have overall/read access.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20866">issue 20866</a>)
......@@ -74,11 +101,7 @@ Upcoming changes</a>
JavaScript errors when navigating away from a page with a build timeline widget while the timeline is loading.
(<a href="https://github.com/jenkinsci/jenkins/pull/1041">pull request 1041</a>)
</ul>
</div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.543>What's new in 1.543</a> <!--=DATE=--></h3>
<h3><a name=v1.543>What's new in 1.543</a> (2013/12/10)</h3>
<ul class=image>
<li class=bug>
Fixed a possible dead lock problem in deleting projects.
......@@ -87,7 +110,6 @@ Upcoming changes</a>
HTML metacharacters not escaped in log messages.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20800">issue 20800</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.542>What's new in 1.542</a> (2013/12/02)</h3>
<ul class=image>
<li class=bug>
......@@ -798,6 +820,9 @@ Upcoming changes</a>
<li class=bug>
NPE from <code>MatrixConfiguration.newBuild</code>.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17728">issue 17728</a>)
<li class=bug>
Identify the short name of an uploaded plugin from the manifest, so it does not matter what the filename was.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-4543">issue 4543</a>)
<li class='major bug'>
NPE configuring Copy Artifact with Maven jobs.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17402">issue 17402</a>)
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
......@@ -150,6 +150,7 @@ import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgume
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import hudson.util.RunList;
import java.util.concurrent.atomic.AtomicLong;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -1431,7 +1432,8 @@ public class Functions {
}
/**
* Returns a sub-list if the given list is bigger than the specified 'maxSize'
* Returns a sub-list if the given list is bigger than the specified {@code maxSize}.
* <strong>Warning:</strong> do not call this with a {@link RunList}, or you will break lazy loading!
*/
public static <T> List<T> subList(List<T> base, int maxSize) {
if(maxSize<base.size())
......@@ -1824,8 +1826,8 @@ public class Functions {
*/
public static String breakableString(final String plain) {
return plain.replaceAll("(\\p{Punct}+\\w)", "<wbr>$1")
.replaceAll("(\\w{10})(?=\\w{3})", "$1<wbr>")
return plain.replaceAll("([\\p{Punct}&&[^;]]+\\w)", "<wbr>$1")
.replaceAll("([^\\p{Punct}\\s-]{10})(?=[^\\p{Punct}\\s-]{3})", "$1<wbr>")
;
}
......
......@@ -24,7 +24,7 @@
package hudson;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.StreamException;
......@@ -140,9 +140,7 @@ public final class XmlFile {
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
return xs.fromXML(in);
} catch(StreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(ConversionException e) {
} catch (XStreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(Error e) {// mostly reflection errors
throw new IOException("Unable to read "+file,e);
......@@ -163,9 +161,7 @@ public final class XmlFile {
try {
// TODO: expose XStream the driver from XStream
return xs.unmarshal(DEFAULT_DRIVER.createReader(in), o);
} catch (StreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(ConversionException e) {
} catch (XStreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(Error e) {// mostly reflection errors
throw new IOException("Unable to read "+file,e);
......
......@@ -299,7 +299,7 @@ public class LogRecorder extends AbstractModelObject implements Saveable {
* The file we save our configuration.
*/
private XmlFile getConfigFile() {
return new XmlFile(XSTREAM, new File(Jenkins.getInstance().getRootDir(),"log/"+name+".xml"));
return new XmlFile(XSTREAM, new File(LogRecorderManager.configDir(), name + ".xml"));
}
/**
......
......@@ -33,7 +33,6 @@ import hudson.model.RSS;
import hudson.util.CopyOnWriteMap;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ModelObjectWithContextMenu;
import jenkins.model.ModelObjectWithContextMenu.ContextMenu;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.kohsuke.stapler.QueryParameter;
......@@ -52,7 +51,6 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
......@@ -84,12 +82,16 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje
return logRecorders.get(token);
}
static File configDir() {
return new File(Jenkins.getInstance().getRootDir(), "log");
}
/**
* Loads the configuration from disk.
*/
public void load() throws IOException {
logRecorders.clear();
File dir = new File(Jenkins.getInstance().getRootDir(), "log");
File dir = configDir();
File[] files = dir.listFiles((FileFilter)new WildcardFileFilter("*.xml"));
if(files==null) return;
for (File child : files) {
......
......@@ -45,13 +45,15 @@ public class BuildTimelineWidget {
protected final RunList<?> builds;
public BuildTimelineWidget(RunList<?> builds) {
this.builds = builds;
this.builds = builds.limit(20); // TODO instead render lazily
}
@Deprecated
public Run<?, ?> getFirstBuild() {
return builds.getFirstBuild();
}
@Deprecated
public Run<?, ?> getLastBuild() {
return builds.getLastBuild();
}
......
......@@ -40,6 +40,8 @@ import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Defines a bunch of static methods to be used as a "mix-in" for {@link ItemGroup}
......@@ -99,7 +101,7 @@ public abstract class ItemGroupMixIn {
V item = (V) Items.load(parent,subdir);
configurations.put(key.call(item), item);
} catch (IOException e) {
e.printStackTrace(); // TODO: logging
Logger.getLogger(ItemGroupMixIn.class.getName()).log(Level.WARNING, "could not load " + subdir, e);
}
}
......
......@@ -1269,7 +1269,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
}
DataSetBuilder<String, ChartLabel> data = new DataSetBuilder<String, ChartLabel>();
for (Run r : getBuilds()) {
for (Run r : getNewBuilds()) {
if (r.isBuilding())
continue;
data.add(((double) r.getDuration()) / (1000 * 60), "min",
......
/*
* The MIT License
*
* Copyright (c) 2013 Red Hat, 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.
*/
package hudson.model;
import java.io.IOException;
import javax.annotation.Nonnull;
/**
* {@link ViewGroup} that can be modified.
*
* @author ogondza
* @since 1.545
*/
public interface ModifiableViewGroup extends ViewGroup {
/**
* Add new {@link View} to this {@link ViewGroup}.
*/
public void addView(@Nonnull View view) throws IOException;
}
......@@ -58,7 +58,7 @@ import org.kohsuke.stapler.StaplerResponse;
*
* @author Tom Huybrechts
*/
public class MyViewsProperty extends UserProperty implements ViewGroup, Action, StaplerFallback {
public class MyViewsProperty extends UserProperty implements ModifiableViewGroup, Action, StaplerFallback {
private String primaryViewName;
/**
......@@ -136,6 +136,7 @@ public class MyViewsProperty extends UserProperty implements ViewGroup, Action,
viewGroupMixIn.onViewRenamed(view,oldName,newName);
}
@Override
public void addView(View view) throws IOException {
viewGroupMixIn.addView(view);
}
......
......@@ -194,24 +194,21 @@ public final class RunMap<R extends Run<?,R>> extends AbstractLazyLoadRunMap<R>
final SimpleDateFormat formatter = Run.ID_FORMATTER.get();
return new FilenameFilter() {
public boolean accept(File dir, String name) {
// JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
// or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
// Don't even bother trying.
if (!isCorrectDate(name)) {
LOGGER.log(FINE, "Skipping {0}", new File(dir,name));
@Override public boolean accept(File dir, String name) {
if (name.startsWith("0000")) {
// JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
// or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
// Don't even bother trying.
return false;
}
return !name.startsWith("0000") && new File(dir,name).isDirectory();
}
private boolean isCorrectDate(String name) {
try {
if(formatter.format(formatter.parse(name)).equals(name))
if (formatter.format(formatter.parse(name)).equals(name)) {
return true;
}
} catch (ParseException e) {
// fall through
}
LOGGER.log(FINE, "Skipping {0} in {1}", new Object[] {name, dir});
return false;
}
};
......
......@@ -24,6 +24,7 @@
*/
package hudson.model;
import com.google.common.base.Predicate;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import hudson.*;
import hudson.model.Descriptor.FormException;
......@@ -451,19 +452,14 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
/**
* Gets the list of {@link Build}s that include changes by this user,
* by the timestamp order.
*
* TODO: do we need some index for this?
*/
@WithBridgeMethods(List.class)
public RunList getBuilds() {
List<AbstractBuild> r = new ArrayList<AbstractBuild>();
for (AbstractProject<?,?> p : Jenkins.getInstance().getAllItems(AbstractProject.class))
for (AbstractBuild<?,?> b : p.getBuilds().newBuilds()){
if (relatedTo(b)) {
r.add(b);
}
return new RunList<Run<?,?>>(Jenkins.getInstance().getAllItems(Job.class)).filter(new Predicate<Run<?,?>>() {
@Override public boolean apply(Run<?,?> r) {
return r instanceof AbstractBuild && relatedTo((AbstractBuild<?,?>) r);
}
return RunList.fromRuns(r);
});
}
/**
......
......@@ -265,7 +265,7 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
synchronized(AbstractNodeMonitorDescriptor.this) {
if(inProgress!=null) {
// maybe it got stuck?
LOGGER.warning("Previous "+getDisplayName()+" monitoring activity still in progress. Interrupting");
LOGGER.log(Level.WARNING, "Previous {0} monitoring activity still in progress. Interrupting", getDisplayName());
inProgress.interrupt();
}
inProgress = this;
......@@ -283,7 +283,9 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
timestamp = System.currentTimeMillis();
record = this;
LOGGER.fine("Node monitoring "+getDisplayName()+" completed in "+(System.currentTimeMillis()-startTime)+"ms");
LOGGER.log(Level.FINE, "Node monitoring {0} completed in {1}ms", new Object[] {getDisplayName(), System.currentTimeMillis()-startTime});
} catch (InterruptedException x) {
// interrupted by new one, fine
} catch (Throwable t) {
LOGGER.log(Level.WARNING, "Unexpected node monitoring termination: "+getDisplayName(),t);
} finally {
......
......@@ -133,6 +133,7 @@ public class JUnitResultArchiver extends Recorder implements MatrixAggregatable
TestResult result = parse(testResults, build, launcher, listener);
try {
// TODO can the build argument be omitted now, or is it used prior to the call to addAction?
action = new TestResultAction(build, result, listener);
} catch (NullPointerException npe) {
throw new AbortException(Messages.JUnitResultArchiver_BadXML(testResults));
......@@ -173,7 +174,7 @@ public class JUnitResultArchiver extends Recorder implements MatrixAggregatable
return true;
}
build.getActions().add(action);
build.addAction(action);
CHECKPOINT.report();
if (action.getResult().getFailCount() > 0)
......
......@@ -62,11 +62,17 @@ public class TestResultAction extends AbstractTestResultAction<TestResultAction>
private Integer totalCount;
private List<Data> testData = new ArrayList<Data>();
@Deprecated
public TestResultAction(AbstractBuild owner, TestResult result, BuildListener listener) {
super(owner);
setResult(result, listener);
}
/** @since 1.545 */
public TestResultAction(TestResult result, BuildListener listener) {
this(null, result, listener);
}
/**
* Overwrites the {@link TestResult} by a new data set.
*/
......
......@@ -28,6 +28,14 @@ import hudson.model.*;
import hudson.tasks.junit.CaseResult;
import hudson.util.*;
import hudson.util.ChartUtil.NumberOnlyBuildLabel;
import java.awt.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jenkins.model.RunAction2;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
......@@ -44,13 +52,6 @@ import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.awt.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Common base class for recording test result.
*
......@@ -61,15 +62,28 @@ import java.util.concurrent.ConcurrentHashMap;
* @author Kohsuke Kawaguchi
*/
@ExportedBean
public abstract class AbstractTestResultAction<T extends AbstractTestResultAction> implements HealthReportingAction {
public final AbstractBuild<?,?> owner;
public abstract class AbstractTestResultAction<T extends AbstractTestResultAction> implements HealthReportingAction, RunAction2 {
public transient AbstractBuild<?,?> owner;
private Map<String,String> descriptions = new ConcurrentHashMap<String, String>();
/** @since 1.545 */
protected AbstractTestResultAction() {}
/** @deprecated Use the default constructor and just call {@link Run#addAction} to associate the build with the action. */
@Deprecated
protected AbstractTestResultAction(AbstractBuild owner) {
this.owner = owner;
}
@Override public void onAttached(Run<?, ?> r) {
this.owner = (AbstractBuild<?,?>) r;
}
@Override public void onLoad(Run<?, ?> r) {
this.owner = (AbstractBuild<?,?>) r;
}
/**
* Gets the number of failed tests.
*/
......
......@@ -67,10 +67,14 @@ public abstract class AggregatedTestResultAction extends AbstractTestResultActio
*/
public final List<Child> children = new ArrayList<Child>();
@Deprecated
public AggregatedTestResultAction(AbstractBuild owner) {
super(owner);
}
/** @since 1.545 */
public AggregatedTestResultAction() {}
protected void update(List<? extends AbstractTestResultAction> children) {
failCount = skipCount = totalCount = 0;
this.children.clear();
......
......@@ -87,7 +87,7 @@ public class AggregatedTestResultPublisher extends Recorder {
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
// add a TestResult just so that it can show up later.
build.addAction(new TestResultAction(jobs,includeFailedBuilds,build));
build.addAction(new TestResultAction(jobs, includeFailedBuilds));
return true;
}
......@@ -131,6 +131,11 @@ public class AggregatedTestResultPublisher extends Recorder {
private transient List<AbstractProject> didntRun;
private transient List<AbstractProject> noFingerprints;
public TestResultAction(String jobs, boolean includeFailedBuilds) {
this(jobs, includeFailedBuilds, null);
}
@Deprecated
public TestResultAction(String jobs, boolean includeFailedBuilds, AbstractBuild<?,?> owner) {
super(owner);
this.includeFailedBuilds = includeFailedBuilds;
......
......@@ -38,10 +38,15 @@ import hudson.model.Action;
* @author Kohsuke Kawaguchi
*/
public class MatrixTestResult extends AggregatedTestResultAction {
@Deprecated
public MatrixTestResult(MatrixBuild owner) {
super(owner);
}
/** @since 1.545 */
public MatrixTestResult() {}
/**
* Use the configuration name.
*/
......
......@@ -46,7 +46,7 @@ public class TestResultAggregator extends MatrixAggregator {
@Override
public boolean startBuild() throws InterruptedException, IOException {
result = new MatrixTestResult(build);
result = new MatrixTestResult();
build.addAction(result);
return true;
}
......
......@@ -74,6 +74,12 @@ import jenkins.model.RunAction2;
/**
* {@link Trigger} that checks for SCM updates periodically.
*
* You can add UI elements under the SCM section by creating a
* config.jelly or config.groovy in the resources area for
* your class that inherits from SCMTrigger and has the
* @{@link hudson.model.Extension} annotation. The UI should
* be wrapped in an f:section element to denote it.
*
* @author Kohsuke Kawaguchi
*/
public class SCMTrigger extends Trigger<SCMedItem> {
......
......@@ -23,7 +23,7 @@
*/
package hudson.util;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
......@@ -38,8 +38,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Arrays;
import static java.util.logging.Level.FINE;
import java.util.logging.Logger;
/**
......@@ -192,11 +190,9 @@ public class CopyOnWriteList<E> implements Iterable<E> {
try {
Object item = readItem(reader, context, items);
items.add(item);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Failed to resolve class", e);
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve class", e);
RobustReflectionConverter.addErrorInContext(context, e);
}
reader.moveUp();
......@@ -206,5 +202,4 @@ public class CopyOnWriteList<E> implements Iterable<E> {
}
}
private static final Logger LOGGER = Logger.getLogger(CopyOnWriteList.class.getName());
}
......@@ -23,7 +23,6 @@
*/
package hudson.util;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
......@@ -31,16 +30,15 @@ import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import static java.util.logging.Level.FINE;
import java.util.logging.Logger;
/**
* {@link CollectionConverter} that ignores {@link CannotResolveClassException}.
* {@link CollectionConverter} that ignores {@link XStreamException}.
*
* <p>
* This allows Hudson to load XML files that contain non-existent classes
......@@ -84,16 +82,13 @@ public class RobustCollectionConverter extends CollectionConverter {
try {
Object item = readItem(reader, context, collection);
collection.add(item);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Failed to resolve class", e);
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve class", e);
RobustReflectionConverter.addErrorInContext(context, e);
}
reader.moveUp();
}
}
private static final Logger LOGGER = Logger.getLogger(RobustCollectionConverter.class.getName());
}
......@@ -23,12 +23,12 @@
*/
package hudson.util;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.MissingFieldException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
......@@ -38,7 +38,6 @@ import com.thoughtworks.xstream.core.util.Primitives;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.Saveable;
......@@ -293,14 +292,9 @@ public class RobustReflectionConverter implements Converter {
implicitCollectionsForCurrentObject = writeValueToImplicitCollection(context, value, implicitCollectionsForCurrentObject, result, fieldName);
}
}
} catch (MissingFieldException e) {
LOGGER.log(FINE, "Skipping a non-existent field " + e.getFieldName(), e);
addErrorInContext(context, e);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Skipping a non-existent type", e);
} catch (XStreamException e) {
addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve a type", e);
addErrorInContext(context, e);
}
......@@ -316,6 +310,7 @@ public class RobustReflectionConverter implements Converter {
}
public static void addErrorInContext(UnmarshallingContext context, Throwable e) {
LOGGER.log(FINE, "Failed to load", e);
ArrayList<Throwable> list = (ArrayList<Throwable>)context.get("ReadError");
if (list == null)
context.put("ReadError", list = new ArrayList<Throwable>());
......
......@@ -186,9 +186,10 @@ public class RunList<R extends Run> extends AbstractList<R> {
/**
* Returns elements that satisfy the given predicate.
* <em>Warning:</em> this method mutates the original list and then returns it.
* @since 1.544
*/
// for compatibility reasons, this method doesn't create a new list but updates the current one
private RunList<R> filter(Predicate<R> predicate) {
public RunList<R> filter(Predicate<R> predicate) {
size = null;
first = null;
base = Iterables.filter(base,predicate);
......
......@@ -26,12 +26,12 @@ package hudson.util.xstream;
import com.google.common.collect.ImmutableList;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import hudson.util.RobustReflectionConverter;
......@@ -76,7 +76,7 @@ public class ImmutableListConverter extends CollectionConverter {
try {
Object item = readItem(reader, context, items);
items.add(item);
} catch (CannotResolveClassException e) {
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
RobustReflectionConverter.addErrorInContext(context, e);
......
......@@ -56,6 +56,7 @@ import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.ItemGroupMixIn;
import hudson.model.Items;
import hudson.model.ModifiableViewGroup;
import hudson.model.JDK;
import hudson.model.Job;
import hudson.model.JobPropertyDescriptor;
......@@ -78,7 +79,6 @@ import hudson.model.UnprotectedRootAction;
import hudson.model.UpdateCenter;
import hudson.model.User;
import hudson.model.View;
import hudson.model.ViewGroup;
import hudson.model.ViewGroupMixIn;
import hudson.model.Descriptor.FormException;
import hudson.model.labels.LabelAtom;
......@@ -305,7 +305,7 @@ import javax.annotation.Nullable;
*/
@ExportedBean
public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGroup, StaplerProxy, StaplerFallback,
ViewGroup, AccessControlled, DescriptorByNameOwner,
ModifiableViewGroup, AccessControlled, DescriptorByNameOwner,
ModelObjectWithContextMenu, ModelObjectWithChildren {
private transient final Queue queue;
......@@ -1456,6 +1456,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
return viewGroupMixIn.getViews();
}
@Override
public void addView(View v) throws IOException {
viewGroupMixIn.addView(v);
}
......
......@@ -26,19 +26,15 @@ package jenkins.model.lazy;
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.RunMap;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.ref.Reference;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
......@@ -50,6 +46,9 @@ import javax.annotation.CheckForNull;
import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.*;
import static jenkins.model.lazy.Boundary.*;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* {@link SortedMap} that keeps build records by their build numbers, in the descending order
......@@ -224,26 +223,27 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
}
private void loadIdOnDisk() {
String[] buildDirs = dir.list(createDirectoryFilter());
if (buildDirs==null) {
String[] kids = dir.list();
if (kids == null) {
// the job may have just been created
buildDirs=EMPTY_STRING_ARRAY;
kids = EMPTY_STRING_ARRAY;
}
// wrap into ArrayList to enable mutation
Arrays.sort(buildDirs);
idOnDisk = new SortedList<String>(new ArrayList<String>(Arrays.asList(buildDirs)));
// TODO: should we check that shortcuts is a symlink?
String[] shortcuts = dir.list();
if (shortcuts==null) shortcuts=EMPTY_STRING_ARRAY;
SortedIntList list = new SortedIntList(shortcuts.length/2);
for (String s : shortcuts) {
try {
list.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
// this isn't a shortcut
List<String> buildDirs = new ArrayList<String>();
FilenameFilter buildDirFilter = createDirectoryFilter();
SortedIntList list = new SortedIntList(kids.length / 2);
for (String s : kids) {
if (buildDirFilter.accept(dir, s)) {
buildDirs.add(s);
} else {
try {
list.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
// this isn't a shortcut
}
}
}
Collections.sort(buildDirs);
idOnDisk = new SortedList<String>(buildDirs);
list.sort();
numberOnDisk = list;
}
......
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.
*/
package jenkins.widgets;
import hudson.Functions;
import hudson.model.BallColor;
import hudson.model.Run;
import net.sf.json.JSONObject;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
@Restricted(DoNotUse.class) // only for buildListTable.jelly
public class BuildListTable extends RunListProgressiveRendering {
@Override protected void calculate(Run<?,?> build, JSONObject element) {
BallColor iconColor = build.getIconColor();
element.put("iconColorOrdinal", iconColor.ordinal());
element.put("iconColorDescription", iconColor.getDescription());
element.put("url", build.getUrl());
element.put("buildStatusUrl", build.getBuildStatusUrl());
element.put("parentUrl", build.getParent().getUrl());
element.put("parentFullDisplayName", Functions.breakableString(Functions.escape(build.getParent().getFullDisplayName())));
element.put("displayName", build.getDisplayName());
element.put("timestampString", build.getTimestampString());
element.put("timestampString2", build.getTimestampString2());
Run.Summary buildStatusSummary = build.getBuildStatusSummary();
element.put("buildStatusSummaryWorse", buildStatusSummary.isWorse);
element.put("buildStatusSummaryMessage", buildStatusSummary.message);
}
}
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.
*/
package jenkins.widgets;
import hudson.model.AbstractBuild;
import hudson.model.BallColor;
import hudson.model.Node;
import hudson.model.Run;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
@Restricted(DoNotUse.class) // only for buildTimeTrend.jelly
public class BuildTimeTrend extends RunListProgressiveRendering {
@Override protected void calculate(Run<?,?> build, JSONObject element) {
BallColor iconColor = build.getIconColor();
element.put("iconColorOrdinal", iconColor.ordinal());
element.put("iconColorDescription", iconColor.getDescription());
element.put("buildStatusUrl", build.getBuildStatusUrl());
element.put("number", build.getNumber());
element.put("displayName", build.getDisplayName());
element.put("duration", build.getDuration());
element.put("durationString", build.getDurationString());
if (build instanceof AbstractBuild) {
AbstractBuild<?,?> b = (AbstractBuild) build;
Node n = b.getBuiltOn();
if (n == null) {
String ns = b.getBuiltOnStr();
if (ns != null && !ns.isEmpty()) {
element.put("builtOnStr", ns);
}
} else if (n != Jenkins.getInstance()) {
element.put("builtOn", n.getNodeName());
element.put("builtOnStr", n.getDisplayName());
} else {
element.put("builtOnStr", hudson.model.Messages.Hudson_Computer_DisplayName());
}
}
}
}
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.
*/
package jenkins.widgets;
import hudson.model.Run;
import hudson.util.RunList;
import java.util.ArrayList;
import java.util.List;
import jenkins.util.ProgressiveRendering;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Makes it possible to incrementally render some information from a {@link RunList}.
*/
@Restricted(NoExternalUse.class)
public abstract class RunListProgressiveRendering extends ProgressiveRendering {
/**
* Since we cannot predict how many runs there will be, just show an ever-growing progress bar.
* The first increment will be sized as if this many runs will be in the total,
* but then like Zeno’s paradox we will never seem to finish until we actually do.
*/
private static final double MAX_LIKELY_RUNS = 20;
private final List<JSONObject> results = new ArrayList<JSONObject>();
private Iterable<? extends Run<?,?>> builds;
/** Jelly cannot call a constructor with arguments. */
public void setBuilds(Iterable<? extends Run<?,?>> builds) {
this.builds = builds;
}
@Override protected void compute() throws Exception {
double decay = 1;
for (Run<?,?> build : builds) {
if (canceled()) {
return;
}
JSONObject element = new JSONObject();
calculate(build, element);
synchronized (results) {
results.add(element);
}
decay *= (1 - 1 / MAX_LIKELY_RUNS);
progress(1 - decay);
}
}
@Override protected synchronized JSON data() {
JSONArray d = JSONArray.fromObject(results);
results.clear();
return d;
}
protected abstract void calculate(Run<?,?> build, JSONObject element);
}
......@@ -24,13 +24,13 @@ HTTP\ Proxy\ Configuration=Configuration du proxy HTTP
Submit=Soumettre
Upload\ Plugin=Soumettre un plugin
File=Fichier
Update\ Site=Rafra\u00EEchir site
Update\ Site=Site de mise \u00E0 jour
Upload=Soumettre
lastUpdated=Derni\u00E8re mise \u00E0 jour\u00A0: il y a {0}
Check\ now=Vérifier maintenant
Check\ now=V\u00E9rifier maintenant
uploadtext=Vous pouvez t\u00E9l\u00E9verser un fichier .hpi pour installer un plugin ext\u00E9rieur au d\u00E9p\u00F4t centralis\u00E9 de plugin.
Proxy\ Needs\ Authorization=Le proxy n\u00E9cessite une authentification
Server=Serveur
User\ name=Nom d''utilisateur
No\ Proxy\ for=Pas de proxy pour
No\ Proxy\ Host=Pas de proxy pour
Password=Mot de passe
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Not\ configured=Non configuree
Not\ configured=Non configur\u00E9e
......@@ -21,9 +21,7 @@
# THE SOFTWARE.
Advanced\ Project\ Options=Options avanc\u00E9es du projet
Restrict\ where\ this\ project\ can\ be\ run=Restreindre o\u00F9 le projet peut \u00EAtre ex\u00E9cuter
Tie\ this\ project\ to\ a\ node=Associer ce projet \u00E0 un noeud
Node=Noeud
Execute\ concurrent\ builds\ if\ necessary\ =Ex\u00E9cuter les builds en parall\u00E8le si n\u00E9cessaire
JDK\ to\ be\ used\ for\ this\ project=Le JDK \u00E0 utiliser pour ce projet
default.value=(Valeur par d\u00E9faut)
......@@ -22,4 +22,4 @@
Are\ you\ sure\ about\ deleting\ the\ job?=Etes-vous sûr de vouloir supprimer ce job?
Yes=Oui
blurb=\u00CAtes vous s\u00FBr de vouloir supprimer ce {0} "{1}"?
blurb=\u00CAtes-vous s\u00FBr de vouloir supprimer ce {0} "{1}"?
\ No newline at end of file
......@@ -77,10 +77,7 @@ THE SOFTWARE.
// theme1.autoWidth = true; // Set the Timeline's "width" automatically.
// Set autoWidth on the Timeline's first band's theme,
// will affect all bands.
theme1.timeline_start = new Date(${it.firstBuild.timeInMillis-24*60*60*1000});
theme1.timeline_stop = new Date(${it.lastBuild.timeInMillis+24*60*60*1000});
var d = new Date(${it.lastBuild.timeInMillis});
var bandInfos = [
// the bar that shows outline
Timeline.createBandInfo({
......
......@@ -34,15 +34,39 @@ THE SOFTWARE.
<div style="height:2em"/><!-- spacer -->
<h1>${%Build Time Trend}</h1>
<j:choose>
<j:when test="${it.builds.size()&gt;1}">
<div align="center">
<img src="buildTimeGraph/png" width="500" height="400" lazymap="buildTimeGraph/map" alt="[Build time graph]" style="float:right"/>
</div>
<j:set var="isMasterSlaveEnabled" value="${!empty(app.slaves)}"/>
<div align="center">
<table class="sortable" style="margin-top:1em;">
<script>
function displayBuilds(data) {
var p = $$('trend');
for (var x = 0; data.length > x; x++) {
var e = data[x];
var tr = new Element('tr');
tr.insert(new Element('td', {data: e.iconColorOrdinal}).
insert(new Element('img', {width: 16, height: 16, src: '${imagesURL}/16x16/' + e.buildStatusUrl, alt: e.iconColorDescription})));
tr.insert(new Element('td', {data: e.number}).
insert(new Element('a', {href: e.number + '/', 'class': 'model-link inside'}).
update(e.displayName.escapeHTML())));
tr.insert(new Element('td', {data: e.duration}).
update(e.durationString.escapeHTML()));
<j:if test="${isMasterSlaveEnabled}">
tr.insert(new Element('td').
update(e.builtOn ? new Element('a', {href: '${rootURL}/computer/' + e.builtOn, 'class': 'model-link inside'}).update(e.builtOnStr) : e.builtOnStr));
</j:if>
p.insert(tr);
Behaviour.applySubtree(tr);
}
ts_refresh(p);
}
</script>
<j:new var="handler" className="jenkins.widgets.BuildTimeTrend"/>
${handler.setBuilds(it.builds)}
<l:progressiveRendering handler="${handler}" callback="displayBuilds"/>
<table class="sortable" style="margin-top:1em;" id="trend">
<tr>
<th><st:nbsp/></th>
<th initialSortDir="up">${%Build}</th>
......@@ -51,33 +75,8 @@ THE SOFTWARE.
<th>${%Slave}</th>
</j:if>
</tr>
<j:forEach var="r" items="${it.builds}">
<tr>
<td data="${r.iconColor.ordinal()}">
<img width="16" height="16" src="${imagesURL}/16x16/${r.buildStatusUrl}" alt="${r.iconColor.description}" />
</td>
<td data="${r.number}">
<a href="${r.number}/" class="model-link inside">
${r.displayName}
</a>
</td>
<td data="${r.duration}">
${r.durationString}
</td>
<j:if test="${isMasterSlaveEnabled}">
<td>
<t:node value="${r.builtOn}" valueStr="${r.builtOnStr}"/>
</td>
</j:if>
</tr>
</j:forEach>
</table>
</div>
</j:when>
<j:otherwise>
${%More than 1 builds are needed for the trend report.}
</j:otherwise>
</j:choose>
</l:main-panel>
</l:layout>
</j:jelly>
......@@ -30,6 +30,7 @@ THE SOFTWARE.
<img src="${h.getUserAvatar(it,'48x48')}" alt="" height="48" width="48" />
${%title(it)}
</h1>
<!-- TODO consider adding a BuildTimelineWidget (cf. Job, View, Computer) -->
<t:buildListTable builds="${it.builds}" jobBaseUrl="${rootURL}/" />
</l:main-panel>
</l:layout>
......
......@@ -20,8 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
NewJob=Nouvelle {0}
People=Utilsateurs
NewJob=Nouveau {0}
People=Utilisateurs
Build\ History=Historique des constructions
Edit\ View=\u00C9diter cette vue
Delete\ View=Supprimer cette vue
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<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">
<table class="pane sortable" id="testresult">
<table class="pane sortable bigtable" id="testresult">
<tr>
<td class="pane-header" style="width:10em">${%Build}</td>
<td class="pane-header" style="width:10em">${%Test Description}</td>
......
......@@ -26,7 +26,7 @@ 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">
<j:if test="${it.totalCount!=0}">
<h2>${%All Tests}</h2>
<table class="pane sortable" id="testresult">
<table class="pane sortable bigtable" id="testresult">
<tr>
<td class="pane-header">${%Test name}</td>
<td class="pane-header" style="width:6em">${%Duration}</td>
......
......@@ -25,7 +25,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<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">
<table class="pane sortable" id="testresult">
<table class="pane sortable bigtable" id="testresult">
<tr>
<td class="pane-header">${%Build}</td>
<td class="pane-header">${%Description}</td>
......
......@@ -57,6 +57,8 @@ THE SOFTWARE.
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Skip}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Pass}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Total}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
</tr>
......@@ -80,6 +82,10 @@ THE SOFTWARE.
<td class="pane" style="text-align:right" data="${p.skipCount-prev.skipCount}">
${h.getDiffString2(p.skipCount-prev.skipCount)}
</td>
<td class="pane" style="text-align:right">${p.passCount}</td>
<td class="pane" style="text-align:right">
${h.getDiffString2(p.passCount-prev.passCount)}
</td>
<td class="pane" style="text-align:right">${p.totalCount}</td>
<td class="pane" style="text-align:right" data="${p.totalCount-prev.totalCount}">
${h.getDiffString2(p.totalCount-prev.totalCount)}
......
......@@ -25,7 +25,7 @@ THE SOFTWARE.
<?jelly escape-by-default='true'?>
<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">
<table class="pane sortable" id="testresult">
<table class="pane sortable bigtable" id="testresult">
<tr>
<td class="pane-header">${%Build}</td>
<td class="pane-header">${%Description}</td>
......
# This file is under the MIT License by authors
Apply=V\u00E4rkst\u00E4ll
Apply=Verkst\u00E4ll
......@@ -58,7 +58,7 @@ THE SOFTWARE.
if present, the foldable section will not be grouped into a separate JSON object upon submission
</st:attribute>
</st:documentation>
<j:if test="${attrs.help==null}">
<j:if test="${attrs.help == null and attrs.field != null}">
<!-- infer the help page from the current descriptor and field if possible -->
<j:set target="${attrs}" property="help"
value="${descriptor.getHelpFile(attrs.field)}" />
......
......@@ -35,6 +35,37 @@ THE SOFTWARE.
</st:documentation>
<t:setIconSize/>
<script>
function displayBuilds(data) {
var p = $$('projectStatus');
for (var x = 0; data.length > x; x++) {
var e = data[x];
var tr = new Element('tr');
tr.insert(new Element('td', {data: e.iconColorOrdinal}).
insert(new Element('a', {href: '${jobBaseUrl}' + e.url}).
insert(new Element('img', {src: '${imagesURL}/${iconSize}/' + e.buildStatusUrl, alt: e.iconColorDescription, 'class': 'icon${iconSize}'}))));
tr.insert(new Element('td').
insert(new Element('a', {href: '${jobBaseUrl}' + e.parentUrl, 'class': 'model-link'}).
update(e.parentFullDisplayName)).
insert('\u00A0').
insert(new Element('a', {href: '${jobBaseUrl}' + e.url, 'class': 'model-link inside'}).
update(e.displayName.escapeHTML())));
tr.insert(new Element('td', {data: e.timestampString2, tooltip: '${%Click to center timeline on event}', onclick: 'javascript:tl.getBand(0).scrollToCenter(Timeline.DateTime.parseGregorianDateTime("' + e.timestampString2 + '"))'}).
update(e.timestampString.escapeHTML()));
tr.insert(new Element('td', {style: e.buildStatusSummaryWorse ? 'color: red' : ''}).
update(e.buildStatusSummaryMessage.escapeHTML()));
tr.insert(new Element('td').
insert(new Element('a', {href: '${jobBaseUrl}' + e.url + 'console'}).
insert(new Element('img', {src: '${imagesURL}/${subIconSize}/terminal.png', alt: '${%Console output}', border: 0}))));
p.insert(tr);
Behaviour.applySubtree(tr);
}
ts_refresh(p);
}
</script>
<j:new var="handler" className="jenkins.widgets.BuildListTable"/>
${handler.setBuilds(attrs.builds)}
<l:progressiveRendering handler="${handler}" callback="displayBuilds"/>
<table class="sortable pane bigtable" id="projectStatus">
<tr>
<th><st:nbsp/></th>
......@@ -43,33 +74,6 @@ THE SOFTWARE.
<th>${%Status}</th>
<th><st:nbsp/></th>
</tr>
<!-- TODO: support gradual expansion of the list -->
<j:forEach var="b" items="${h.subList(attrs.builds,50)}">
<tr>
<td data="${b.iconColor.ordinal()}">
<a href="${jobBaseUrl}${b.url}">
<img src="${imagesURL}/${iconSize}/${b.buildStatusUrl}"
alt="${b.iconColor.description}" class="icon${iconSize}"/>
</a>
</td>
<td>
<a href="${jobBaseUrl}${b.parent.url}" class="model-link"><l:breakable value="${b.parent.fullDisplayName}"/></a>
<st:nbsp/>
<a href="${jobBaseUrl}${b.url}" class="model-link inside">${b.displayName}</a>
</td>
<td data="${b.timestampString2}" tooltip="${%Click to center timeline on event}" onclick="javascript:tl.getBand(0).scrollToCenter(Timeline.DateTime.parseGregorianDateTime('${b.timestampString2}'))">
${b.timestampString}
</td>
<td>
<t:buildStatusSummary build="${b}" />
</td>
<td>
<a href="${jobBaseUrl}${b.url}console">
<img src="${imagesURL}/${subIconSize}/terminal.png" title="${%Console output}" alt="${%Console output}" border="0" />
</a>
</td>
</tr>
</j:forEach>
</table>
<t:rssBar-with-iconSize/>
</j:jelly>
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest
#
# 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.
Restrict\ where\ this\ project\ can\ be\ run=Restreindre o\u00F9 le projet peut \u00EAtre ex\u00E9cut\u00E9
Label\ Expression=Expression
......@@ -50,5 +50,5 @@ THE SOFTWARE.
<span class="copy-button" tooltip="${attrs.tooltip}" text="${attrs.text}" message="${attrs.message}" container="${attrs.container}">
<input type="button"/>
</span>
<st:adjunct includes="org.kohsuke.stapler.zeroclipboard, lib.layout.copyButton.copyButton"/>
<st:adjunct includes="lib.layout.copyButton.copyButton"/>
</j:jelly>
\ No newline at end of file
......@@ -291,9 +291,26 @@ public class FunctionsTest {
@Test
public void testBreakableString() {
assertEquals("Hello world!", Functions.breakableString("Hello world!"));
assertEquals("H<wbr>,e<wbr>.l<wbr>/l<wbr>:o<wbr>-w<wbr>_o<wbr>=+|d", Functions.breakableString("H,e.l/l:o-w_o=+|d"));
assertEquals("ALongStrin<wbr>gThatCanNo<wbr>tBeBrokenB<wbr>yDefault", Functions.breakableString("ALongStringThatCanNotBeBrokenByDefault"));
assertBrokenAs("Hello world!", "Hello world!");
assertBrokenAs("Hello-world!", "Hello", "-world!");
assertBrokenAs("ALongStringThatCanNotBeBrokenByDefault", "ALongStrin", "gThatCanNo", "tBeBrokenB", "yDefault");
assertBrokenAs("jenkins_main_trunk", "jenkins", "_main", "_trunk");
assertBrokenAs("&lt;&lt;&lt;&lt;&lt;", "", "&lt;", "&lt;", "&lt;", "&lt;", "&lt;");
assertBrokenAs("&amp;&amp;&amp;&amp;&amp;", "", "&amp;", "&amp;", "&amp;", "&amp;", "&amp;");
assertBrokenAs("&thetasym;&thetasym;&thetasym;", "", "&thetasym;", "&thetasym;", "&thetasym;");
assertBrokenAs("Crazy &lt;ha ha&gt;", "Crazy ", "&lt;ha ha", "&gt;");
assertBrokenAs("A;String>Full]Of)Weird}Punctuation", "A;String", ">Full", "]Of", ")Weird", "}Punctuation");
assertBrokenAs("&lt;&lt;a&lt;bc&lt;def&lt;ghi&lt;", "", "&lt;", "&lt;a", "&lt;bc", "&lt;def", "&lt;ghi", "&lt;");
assertBrokenAs("H,e.l/l:o=w_o+|d", "H", ",e", ".l", "/l", ":o", "=w", "_o", "+|d");
assertBrokenAs("a¶‱ﻷa¶‱ﻷa¶‱ﻷa¶‱ﻷa¶‱ﻷa¶‱ﻷa¶‱ﻷa¶‱ﻷ", "a¶‱ﻷa¶‱ﻷa¶", "‱ﻷa¶‱ﻷa¶‱ﻷ", "a¶‱ﻷa¶‱ﻷa¶‱ﻷ");
}
private void assertBrokenAs(String plain, String... chunks) {
assertEquals(
Util.join(Arrays.asList(chunks), "<wbr>"),
Functions.breakableString(plain)
);
}
@Bug(20800)
......
......@@ -41,7 +41,7 @@ public class CronTabEventualityTest {
this.hash = hash;
}
@Test(timeout = 1000)
@Test
@Bug(12388)
public void testYearlyWillBeEventuallyTriggeredWithinOneYear() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
......@@ -49,7 +49,7 @@ public class CronTabEventualityTest {
checkEventuality(start, "@yearly", limit);
}
@Test(timeout = 1000)
@Test
@Bug(12388)
public void testAnnuallyWillBeEventuallyTriggeredWithinOneYear() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
......@@ -57,49 +57,49 @@ public class CronTabEventualityTest {
checkEventuality(start, "@annually", limit);
}
@Test(timeout = 1000)
@Test
public void testMonthlyWillBeEventuallyTriggeredWithinOneMonth() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.MONTH, 1);
checkEventuality(start, "@monthly", limit);
}
@Test(timeout = 1000)
@Test
public void testWeeklyWillBeEventuallyTriggeredWithinOneWeek() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.WEEK_OF_YEAR, 1);
checkEventuality(start, "@weekly", limit);
}
@Test(timeout = 1000)
@Test
public void testDailyWillBeEventuallyTriggeredWithinOneDay() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.DAY_OF_MONTH, 1);
checkEventuality(start, "@daily", limit);
}
@Test(timeout = 1000)
@Test
public void testMidnightWillBeEventuallyTriggeredWithinOneDay() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.DAY_OF_MONTH, 1);
checkEventuality(start, "@midnight", limit);
}
@Test(timeout = 1000)
@Test
public void testHourlyWillBeEventuallyTriggeredWithinOneHour() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.HOUR, 1);
checkEventuality(start, "@hourly", limit);
}
@Test(timeout = 1000)
@Test
public void testFirstDayOfMonthWillBeEventuallyTriggeredWithinOneMonth() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.MONTH, 1);
checkEventuality(start, "H H 1 * *", limit);
}
@Test(timeout = 1000)
@Test
public void testFirstSundayOfMonthWillBeEventuallyTriggeredWithinOneMonthAndOneWeek() throws ANTLRException {
Calendar start = new GregorianCalendar(2012, 0, 11, 22, 33); // Jan 11th 2012 22:33
Calendar limit = createLimit(start, Calendar.DAY_OF_MONTH, 31+7);
......
jenkins (1.544) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
-- Kohsuke Kawaguchi <kk@kohsuke.org> Sun, 15 Dec 2013 07:15:04 -0800
jenkins (1.543) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
-- Kohsuke Kawaguchi <kk@kohsuke.org> Tue, 10 Dec 2013 18:12:44 -0800
jenkins (1.542) unstable; urgency=low
* See http://jenkins-ci.org/changelog for more details.
......
......@@ -14,7 +14,7 @@ defaults="defaults read /Library/Preferences/org.jenkins-ci"
war=`$defaults war` || war="/Applications/Jenkins/jenkins.war"
javaArgs=""
javaArgs="-Dfile.encoding=UTF-8"
minPermGen=`$defaults minPermGen` && javaArgs="$javaArgs -XX:PermSize=${minPermGen}"
permGen=`$defaults permGen` && javaArgs="$javaArgs -XX:MaxPermSize=${permGen}"
......
......@@ -11,7 +11,7 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<name>Jenkins plugin POM</name>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<packaging>pom</packaging>
<!--
......@@ -39,19 +39,19 @@
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-war</artifactId>
<type>war</type>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-core</artifactId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<!--
......
......@@ -33,7 +33,7 @@ THE SOFTWARE.
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Jenkins main module</name>
......@@ -94,7 +94,7 @@ THE SOFTWARE.
<patch.tracker.serverId>jenkins-jira</patch.tracker.serverId>
<slf4jVersion>1.7.4</slf4jVersion> <!-- < 1.6.x version didn't specify the license (MIT) -->
<maven-plugin.version>2.0</maven-plugin.version>
<maven-plugin.version>2.1</maven-plugin.version>
<netbeans.compile.on.save>none</netbeans.compile.on.save> <!-- we rely on Maven source generation -->
<animal.sniffer.skip>${skipTests}</animal.sniffer.skip>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
</parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
......@@ -79,7 +79,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>mailer</artifactId>
<version>1.5</version>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
......
......@@ -653,7 +653,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
LOGGER.warning("Extracting a copy of Maven bundled in the test harness into " + mvnHome + ". " +
"To avoid a performance hit, set the system property 'maven.home' to point to a Maven2 installation.");
FilePath mvn = jenkins.getRootPath().createTempFile("maven", "zip");
mvn.copyFrom(HudsonTestCase.class.getClassLoader().getResource(mavenVersion + "-bin.zip"));
mvn.copyFrom(JenkinsRule.class.getClassLoader().getResource(mavenVersion + "-bin.zip"));
mvn.unzip(new FilePath(buildDirectory));
// TODO: switch to tar that preserves file permissions more easily
if(!Functions.isWindows())
......@@ -676,7 +676,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
LOGGER.warning("Extracting a copy of Ant bundled in the test harness. " +
"To avoid a performance hit, set the environment variable ANT_HOME to point to an Ant installation.");
FilePath ant = jenkins.getRootPath().createTempFile("ant", "zip");
ant.copyFrom(HudsonTestCase.class.getClassLoader().getResource("apache-ant-1.8.1-bin.zip"));
ant.copyFrom(JenkinsRule.class.getClassLoader().getResource("apache-ant-1.8.1-bin.zip"));
File antHome = createTmpDir();
ant.unzip(new FilePath(antHome));
// TODO: switch to tar that preserves file permissions more easily
......@@ -1667,7 +1667,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* in the context of an HTTP request.
*
* <p>
* In {@link HudsonTestCase}, a thread that's executing the test code is different from the thread
* In {@link JenkinsRule}, a thread that's executing the test code is different from the thread
* that carries out HTTP requests made through {@link WebClient}. But sometimes you want to
* make assertions and other calls with side-effect from within the request handling thread.
*
......@@ -1783,7 +1783,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* Logs in to Hudson, by using the user name as the password.
*
* <p>
* See {@link HudsonTestCase#configureUserRealm()} for how the container is set up with the user names
* See {@link #configureUserRealm} for how the container is set up with the user names
* and passwords. All the test accounts have the same user name and password.
*/
public WebClient login(String username) throws Exception {
......@@ -1796,7 +1796,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
* in the context of an HTTP request.
*
* <p>
* In {@link HudsonTestCase}, a thread that's executing the test code is different from the thread
* In {@link JenkinsRule}, a thread that's executing the test code is different from the thread
* that carries out HTTP requests made through {@link WebClient}. But sometimes you want to
* make assertions and other calls with side-effect from within the request handling thread.
*
......@@ -2070,7 +2070,7 @@ public class JenkinsRule implements TestRule, MethodRule, RootAction {
/**
* Specify this to a TCP/IP port number to have slaves started with the debugger.
*/
public static int SLAVE_DEBUG_PORT = Integer.getInteger(HudsonTestCase.class.getName()+".slaveDebugPort",-1);
public static final int SLAVE_DEBUG_PORT = Integer.getInteger(HudsonTestCase.class.getName()+".slaveDebugPort",-1);
public static final MimeTypes MIME_TYPES = new MimeTypes();
static {
......
......@@ -33,11 +33,11 @@ import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.ItemGroupMixIn;
import hudson.model.ModifiableViewGroup;
import hudson.model.Job;
import hudson.model.TopLevelItem;
import hudson.model.TopLevelItemDescriptor;
import hudson.model.View;
import hudson.model.ViewGroup;
import hudson.model.ViewGroupMixIn;
import hudson.util.Function1;
import hudson.views.DefaultViewsTabBar;
......@@ -69,7 +69,7 @@ import org.kohsuke.stapler.WebMethod;
* @since 1.494
*/
@SuppressWarnings({"unchecked", "rawtypes"}) // the usual API mistakes
public class MockFolder extends AbstractItem implements ModifiableTopLevelItemGroup, TopLevelItem, ViewGroup, StaplerFallback {
public class MockFolder extends AbstractItem implements ModifiableTopLevelItemGroup, TopLevelItem, ModifiableViewGroup, StaplerFallback {
private transient Map<String,TopLevelItem> items = new TreeMap<String,TopLevelItem>();
private final List<View> views = new ArrayList<View>(Collections.singleton(new AllView("All", this)));
......@@ -94,6 +94,9 @@ public class MockFolder extends AbstractItem implements ModifiableTopLevelItemGr
}
@Override public TopLevelItem getItem(String name) {
if (items == null) {
return null; // cf. parent hack in AbstractProject.onLoad
}
return items.get(name);
}
......@@ -188,7 +191,7 @@ public class MockFolder extends AbstractItem implements ModifiableTopLevelItemGr
return Jenkins.getInstance().getDescriptorByType(DescriptorImpl.class);
}
public void addView(View view) throws IOException {
@Override public void addView(View view) throws IOException {
vgmixin().addView(view);
}
......
......@@ -89,17 +89,21 @@ final class WarExploder {
// TODO this assumes that the CWD of the Maven process is the plugin ${basedir}, which may not be the case
File explodeDir = new File("./target/jenkins-for-test").getAbsoluteFile();
while (new File(explodeDir + ".exploding").isFile()) {
explodeDir = new File(explodeDir + "x");
}
File timestamp = new File(explodeDir,".timestamp");
if(!timestamp.exists() || (timestamp.lastModified()!=war.lastModified())) {
System.out.println("Exploding jenkins.war at "+war);
System.out.println("Exploding " + war + " into " + explodeDir);
new FileOutputStream(explodeDir + ".exploding").close();
new FilePath(explodeDir).deleteRecursive();
// TODO this can fail (race condition?) when running tests in parallel; need a three-state flag, and switch to a different explodeDir as needed
new FilePath(war).unzip(new FilePath(explodeDir));
if(!explodeDir.exists()) // this is supposed to be impossible, but I'm investigating HUDSON-2605
throw new IOException("Failed to explode "+war);
new FileOutputStream(timestamp).close();
timestamp.setLastModified(war.lastModified());
new File(explodeDir + ".exploding").delete();
} else {
System.out.println("Picking up existing exploded jenkins.war at "+explodeDir.getAbsolutePath());
}
......
......@@ -278,6 +278,7 @@ public class AbstractProjectTest extends HudsonTestCase {
assertSymlinkForBuild(lastStable, 1);
}
/* TODO too slow, seems capable of causing testWorkspaceLock to time out:
@Bug(15156)
public void testGetBuildAfterGC() {
FreeStyleProject job = createFreeStyleProject();
......@@ -286,6 +287,7 @@ public class AbstractProjectTest extends HudsonTestCase {
MemoryAssert.assertGC(new WeakReference(job.getLastBuild()));
assert job.lastBuild != null;
}
*/
@Bug(13502)
public void testHandleBuildTrigger() {
......
......@@ -53,7 +53,11 @@ class RunMapTest extends HudsonTestCase {
b.save()
p._getRuns().purgeCache()
assert p.getBuildByNumber(b.number)==null
b = p.getBuildByNumber(b.number)
// Original test assumed that b == null, but after JENKINS-21024 this is no longer true,
// so this may not really be testing anything interesting:
assert b != null
assert b.getAction(BombAction.class) == null
assert bombed
}
......
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.
*/
package hudson.model;
import java.util.Collection;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockFolder;
import org.jvnet.hudson.test.recipes.LocalData;
public class ItemGroupMixInTest {
@Rule public JenkinsRule r = new JenkinsRule();
@Bug(20951)
@LocalData
@Test public void xmlFileReadCannotResolveClassException() throws Exception {
MockFolder d = r.jenkins.getItemByFullName("d", MockFolder.class);
assertNotNull(d);
Collection<TopLevelItem> items = d.getItems();
assertEquals(1, items.size());
assertEquals("valid", items.iterator().next().getName());
}
}
......@@ -32,12 +32,19 @@ import org.kohsuke.stapler.StaplerProxy;
public class TrivialTestResultAction extends AbstractTestResultAction<TrivialTestResultAction> implements StaplerProxy {
protected TrivialTestResult result;
@Deprecated
protected TrivialTestResultAction(AbstractBuild owner, TrivialTestResult result) {
super(owner);
this.result = result;
this.result.setParentAction(this);
}
/** @since 1.545 */
protected TrivialTestResultAction(TrivialTestResult result) {
this(null, result);
}
/**
* Gets the number of failed tests.
*/
......
......@@ -48,9 +48,9 @@ public class TrivialTestResultRecorder extends Recorder implements Serializable
System.out.println("performing TrviialTestResultRecorder");
listener.getLogger().println("perfoming TrivialTestResultRecorder");
TrivialTestResult r = new TrivialTestResult("gubernatorial");
TrivialTestResultAction action = new TrivialTestResultAction(build, r);
TrivialTestResultAction action = new TrivialTestResultAction(r);
r.setParentAction(action);
build.getActions().add(action);
build.addAction(action);
listener.getLogger().println("done with TrivialTestResultRecorder");
System.out.println("done with TrivialTestResultRecorder");
return true;
......
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.
*/
package hudson.util;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.FreeStyleProject;
import hudson.model.Saveable;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;
public class RobustReflectionConverterTest {
@Rule public JenkinsRule r = new JenkinsRule();
@Bug(21024)
@LocalData
@Test public void randomExceptionsReported() throws Exception {
FreeStyleProject p = r.jenkins.getItemByFullName("j", FreeStyleProject.class);
assertNotNull(p);
assertEquals(Collections.emptyMap(), p.getTriggers());
OldDataMonitor odm = (OldDataMonitor) r.jenkins.getAdministrativeMonitor("OldData");
Map<Saveable,OldDataMonitor.VersionRange> data = odm.getData();
assertEquals(Collections.singleton(p), data.keySet());
String text = data.values().iterator().next().extra;
assertTrue(text, text.contains("Could not call hudson.triggers.TimerTrigger.readResolve"));
}
}
......@@ -65,7 +65,7 @@ THE SOFTWARE.
<j:if test="${it.totalCount!=0}">
<h2>${%All Tests}</h2>
<table class="pane sortable" id="testresult">
<table class="pane sortable bigtable" id="testresult">
<tr>
<td class="pane-header">${it.childTitle}</td>
<td class="pane-header" style="width:5em">${%Duration}</td>
......@@ -73,6 +73,8 @@ THE SOFTWARE.
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Skip}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Pass}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
<td class="pane-header" style="width:5em">${%Total}</td>
<td class="pane-header" style="width:1em; font-size:smaller; white-space:nowrap;">(${%diff})</td>
</tr>
......@@ -96,6 +98,10 @@ THE SOFTWARE.
<td class="pane" style="text-align:right">
${h.getDiffString2(p.skipCount-prev.skipCount)}
</td>
<td class="pane" style="text-align:right">${p.passCount}</td>
<td class="pane" style="text-align:right">
${h.getDiffString2(p.passCount-prev.passCount)}
</td>
<td class="pane" style="text-align:right">${p.totalCount}</td>
<td class="pane" style="text-align:right">
${h.getDiffString2(p.totalCount-prev.totalCount)}
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.544-SNAPSHOT</version>
<version>1.546-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
<div>
If configured, Jenkins will send out an e-mail to the specified recipients
when a certain important event occurs.
<ol>
<li>Every failed build triggers a new e-mail.
<li>A successful build after a failed (or unstable) build triggers a new e-mail,
indicating that a crisis is over.
<li>An unstable build after a successful build triggers a new e-mail,
indicating that there's a regression.
<li>Unless configured, every unstable build triggers a new e-mail,
indicating that regression is still there.
</ol>
For lazy projects where unstable builds are the norm, Uncheck "Send e-mail for every unstable build".
</div>
\ No newline at end of file
<div>
Ist diese Option konfiguriert, sendet Jenkins E-Mails an die angegebenen Empfänger
wenn bestimmte wichtige Ereignisse eintreten.
<ol>
<li>Jeder fehlgeschlagene Build löst eine neue E-Mail aus.
<li>Ein erfolgreicher Build nach einem fehlgeschlagenen (oder instabilen)
löst eine neue E-Mail aus, um über eine überstandene Krise zu informieren.
<li>Ein instabiler Build nach einem erfolgreichen löst eine neue E-Mail aus,
um über einen Regressionsfehler zu informieren.
<li>Sofern nicht anders konfiguriert, lost jeder instabile Build eine neue
E-Mail aus, um über weiter anhaltende Regressionsfehler zu informieren.
</ol>
Für nachlässige Projekte, in denen instabile Projekte der Regelfall sind, wählen Sie
"E-Mail für jeden instabilen Build senden" ab.
</div>
\ No newline at end of file
<div>
Jenkins a la capacité d'envoyer des emails aux destinaires spécifiés
lorsque certains évènements importants ont eu lieu.
<ol>
<li>Chaque build en échec provoque l'envoi d'un mail.
<li>Un build qui passe avec succès après un build en échec
provoque l'envoi d'un mail, ce qui permet de savoir qu'une situation
de crise est résolue.
<li>Un build instable après un build avec succès provoque l'envoi
d'un mail, indiquant ainsi qu'il y a eu une régression.
<li>Sauf configuration contraire, chaque build instable
provoque l'envoi d'un mail, indiquant ainsi qu'une régression est
toujours d'actualité.
</ol>
Pour les projets qui ne suivent pas les bonnes pratiques et
où les builds instables sont la norme, décochez la case
"Envoyer un email à chaque build instable".
</div>
\ No newline at end of file
<div>
設定すると、Jenkinsは特定の重要なイベントが発生した際に、指定した宛先にメールを送信します。
<ol>
<li>ビルドが失敗するごとに、メールを送信します。
<li>ビルドが失敗(もしくは不安定)した直後にビルドが成功すると、
危機を脱したことを告げるメールを送信します。
<li>ビルドが成功した直後にビルドが不安定になると、
デグレートがあることを告げるメールを送信します。
<li>設定しなければ、ビルドが不安定になるごとに、
デグレートがまだ存在することを告げるメールを送信します。
</ol>
不安定ビルドであることが常である、だらだらしたプロジェクトでは、
"不安定ビルドも逐一メールを送る"をチェックしないようにします。
</div>
<div>
Se configurado, o Jenkins enviar&#225; um e-mail para os destinat&#225;rios especificados
quanod um certo evento importante ocorrer.
<ol>
<li>Toda constru&#231;&#227;o que falha dispara um novo e-mail.
<li>Uma constru&#231;&#227;o feita com sucesso ap&#243;s uma constru&#231;&#227;o falha (ou inst&#225;vel) dipara um novo e-mail,
indicando que uma crise terminou.
<li>Uma constru&#231;&#227;o inst&#225;vel ap&#243;s uma constru&#231;&#227;o bem sucedida dispara um novo e-mail,
indicando que h&#225; uma regress&#227;o.
<li>A menos que configurado, toda constru&#231;&#227;o inst&#225;vel dipara um novo e-mail,
indicando que a regress&#227;o ainda est&#225; l&#225;.
</ol>
Par projetos pregui&#231;osos (lazy) onde constru&#231;&#245;es inst&#225;vei s&#227;o a norma, Marque "N&#227;o enviar e-mail para toda constru&#231;&#227;o inst&#225;vel".
</div>
<div>
Если указан список получателей, Jenkins будет отправлять уведомления по электронной
почте на эти адреса при наступлении следующих событий:
<ol>
<li>Каждая провалившаяся сборка
<li>Успешная сборка после провалившихся (или нестабильных)
<li>Нестабильная сборка после стабильной (сообщает о появлении регрессии)
<li>Каждая нестабильная сборка (если не запрещено другими настройками)
</ol>
Для "ленивых" проектов, где нестабильная сборка считается нормой, установите
флажок "Не отправлять уведомление для каждой нестабильной сборки".
</div>
\ No newline at end of file
<div>
Bu ayar, Husdon'&#305;n &#246;nemli bir durum olu&#351;tu&#287;unda belirtilen al&#305;c&#305;lara mail atmas&#305;n&#305; sa&#287;lar.
<ol>
<li>Her ba&#351;ar&#305;s&#305;z yap&#305;land&#305;rma e-posta at&#305;lmas&#305;n&#305; tetikler.
<li>Ba&#351;ar&#305;s&#305;z (veya dengesiz) bir yap&#305;land&#305;rmadan sonraki ilk ba&#351;ar&#305;l&#305; yap&#305;land&#305;rma yeni
bir e-posta at&#305;lmas&#305;n&#305; tetikler, ki bu da kriz durumunun sona erdi&#287;ini ifade eder.
<li>Ba&#351;ar&#305;l&#305; bir yap&#305;land&#305;rmadan hemen sonraki dengesiz yap&#305;land&#305;rma e-posta at&#305;lmas&#305;n&#305; tetikler,
ki bu da bir gerileme oldu&#287;unu ifade eder.
<li>Konfig&#252;rasyon yap&#305;lmazsa, her dengesiz yap&#305;land&#305;rma e-posta at&#305;lmas&#305;n&#305; tetikler,
ki bu da gerilemenin hala mevcut oldu&#287;unu ifade eder.
</ol>
Dengesiz yap&#305;land&#305;rmalar&#305;n standartla&#351;t&#305;&#287;&#305; projelerde, "Her dengesiz yap&#305;land&#305;rmada e-posta g&#246;nderme" se&#231;ene&#287;ini se&#231;iniz.
</div>
\ No newline at end of file
<div>
設定後,Jenkins 會在特定重大事情發生時,寄送電子郵件給指定的收件人。
<ol>
<li>每次建置失敗都會觸發寄送新郵件。
<li>建置失敗 (或不穩定) 後建置成功將會觸發寄送郵件,告訴大家危機已經解除。
<li>建置成功後如果發生建置不穩定也會觸發寄送郵件,昭告天下我們又倒退了一步。
<li>除非另外設定,不然每次不穩定的建置都會觸發寄送郵件,告訴大家狀況還沒解除。
</ol>
對散漫的專案來說,不穩定的建置是常態,就把「每次建置不穩定都寄送郵件」選項給勾掉吧...。
</div>
\ No newline at end of file
<div>
If this option is checked, the notification e-mail will be sent to individuals who have
committed changes for the broken build (by assuming that those changes broke the build).
<p>
If e-mail addresses are also specified in the recipient list, then both the individuals
as well as the specified addresses get the notification e-mail. If the recipient list
is empty, then only the individuals will receive e-mails.
</div>
\ No newline at end of file
<div>
Schickt E-Mail-Benachrichtigungen an alle "verursachenden" Benutzer, die mit
eingecheckten Änderungen an einem fehlgeschlagenen Build beteiligt waren
(in der Vermutung, daß diese Änderungen den Fehlschlag verursachten).
<p>
Wenn im Empfänger-Verteiler ebenfalls Adressen angegeben sind, werden
E-Mail-Benachrichtigungen sowohl an alle Adressen des Empfänger-Verteilers
als auch an die "verursachenden" Benutzer geschickt. Ist der E-Mail-Verteiler
hingegen leer, erhalten ausschließlich die "verursachenden" Benutzer
E-Mail-Benachrichtigungen.
</div>
\ No newline at end of file
<div>
Si cette option est choisie, les notifications par email seront envoyées
aux personnes qui ont fait des modifications dans un build en échec
(on suppose que ces changements ont cassé ce build).
<p>
Si des adresses email sont aussi spécifiées sur la liste des destinataires,
alors l'email de notification est envoyé à la fois à cette liste et aux
personnes ayant fait des modifications.
Si la liste des destinataires est vide, alors seules les personnes
changeurs recevront des emails.
</div>
\ No newline at end of file
<div>
壊れたビルドに含まれる変更をコミットした個人にメールを送信します(変更がビルドを壊したとみなします)。
<p>
宛先にもメールアドレスが指定されている場合、ここに指定された個人と指定されたアドレスにもにメールを送信します。
宛先が指定されていない場合、ここに指定した個人にだけメールを送信します。
</div>
\ No newline at end of file
<div>
Indien aangevinkt, zal er een e-mail verstuurd worden naar de personen die wijzigingen
opgeladen hebben, in de context van een gefaalde bouwpoging. Hierbij wordt ervan uitgegaan
dat één van die wijziging de bouwpoging heeft doen falen.
<p>
Indien u de lijst van geaddresseerden opgeeft, worden zowel de personen die wijzigingen
hebben doorgevoerd als de geaddresseerden, via e-mail op de hoogte gebracht. Indien U geen
geaddresseerden opgeeft worden enkel de personen die wijzigingen hebben doorgevoerd via e-mail
op de hoogte gebracht.
</div>
\ No newline at end of file
<div>
Se esta op&#231;&#227;o estiver marcada, o e-mail de notifica&#231;&#227;o ser&#225; enviado para os indiv&#237;duos que
comitaram mudan&#231;as para a costru&#231;&#227;o que falhou (assumindo que estas mudan&#231;as causaram a falha na constru&#231;&#227;o).
<p>
Se os endere&#231;os de e-mail tamb&#233;m forem especificados na lista de destinat&#225;rios, ent&#227;o ambos os indiv&#237;duos
bem como os endere&#231;os especificados na lista receber&#227;o e-mails. Se a lista de destinat&#225;rios
estiver vazia, ent&#227;o apens os indiv&#237;duos receber&#227;o e-mails.
</div>
<div>
Если эта настройка включена, уведомление будет отправлено тем лицам,
которые вносили изменения в провалившуюся сборку (предполагая, что сборку сломали
именно эти изменения).
<p>
Если адреса также указаны в списке получателей, тогда два списка будут объединены.
Если список получателей пуст, уведомления получат только авторы последний изменений
(произошедших от момента предыдущей сборки до текущей).
</div>
\ No newline at end of file
<div>
Bu se&#231;enek, bozuk bir yap&#305;land&#305;rmaya de&#287;i&#351;iklikleri ile kat&#305;lan bireylere, yap&#305;land&#305;rman&#305;n bozuk
oldu&#287;u ile ilgili e-posta at&#305;lmas&#305;n&#305; sa&#287;lar (yap&#305;land&#305;rmay&#305; bozan&#305;n, de&#287;i&#351;iklikleri yapan
bireyler oldu&#287;u varsay&#305;larak)
<p>
E&#287;er al&#305;c&#305; listesinde e-posta adresi belirtilmi&#351;se, hem bu al&#305;c&#305;lar, hem de de&#287;i&#351;iklikleri g&#246;nderen
bireyler bu e-postay&#305; alacaklard&#305;r. E&#287;er al&#305;c&#305; listesi bo&#351;sa, sadece de&#287;i&#351;iklikleri g&#246;nderen
bireylere e-posta g&#246;nderilir.
</div>
\ No newline at end of file
<div>
If this option is checked, the notification e-mail will be sent to individuals who have
committed changes for the broken build (by assuming that those changes broke the build).
<p>
If e-mail addresses are also specified in the recipient list, then both the individuals
as well as the specified addresses get the notification e-mail. If the recipient list
is empty, then only the individuals will receive e-mails.
</div>
\ No newline at end of file
<div>
選項啟用後,通知信會寄給有 Commit 變更,導致這次建置失敗的每一個人
(假設是這些變更造成建置失敗)。
<p>
如果有指定收件人清單,那些有嫌疑的人及指定的人都會收到通知郵件。
要是收件人清單是空的,就只有那些人會收到信。
</div>
\ No newline at end of file
<div>
Use SMTP authentication when sending out e-mails. If your environment requires
the use of SMTP authentication, specify its user name and the password here.
</div>
\ No newline at end of file
<div>
Verwendet SMTP Authentifizierung beim Verschicken von E-Mails. Wenn Ihr E-Mail-Server
SMTP Authentifizierung verlangt, geben Sie hier Ihren Benutzernamen und Passwort an.
</div>
\ No newline at end of file
<div>
Cette option provoque l'authentification SMTP lors de l'envoi d'emails.
Si votre environnement nécessite l'utilisation de l'authentification SMTP,
spécifiez ici son nom d'utilisateur et mot de passe.
</div>
\ No newline at end of file
<div>
メール送信時にSMTP認証を使用します。SMTP認証が必要な環境であれば、
ユーザー名とパスワードを指定してください。
</div>
\ No newline at end of file
<div>
Gebruikt SMTP authenticatie bij het uitsturen van e-mails. Gelieve, indien uw omgeving
SMTP authenticatie vereist, hier uw gebruikersnaam en paswoord op te geven.
</div>
\ No newline at end of file
<div>
Usa autentica&#231;&#227;o SMTP quando enviar e-mails. Se seu ambiente requer
o uso de autentica&#231;&#227;o SMTP, especifique o usu&#225;rio e senha aqui.
</div>
<div>
Использовать аутентификацию SMTP при отправке почты. Если ваш сервер требует
аутентификации, укажите логин и пароль здесь.
</div>
\ No newline at end of file
<div>
E-posta g&#246;nderilmesi esnas&#305;nda SMTP do&#287;rulamas&#305; kullan&#305;l&#305;r. E&#287;er ortam&#305;n&#305;z SMTP
do&#287;rulamas&#305; kullan&#305;yorsa, kullan&#305;c&#305; ad&#305; ve &#351;ifreyi burada belirtiniz.
</div>
\ No newline at end of file
<div>
当发送邮件时使用SMTP认证.如果你的环境需要使用SMTP认证,在这里指定其用户名和密码.
</div>
\ No newline at end of file
<div>
送出電子郵件時使用 SMTP 驗證。如果您的環境要求要 SMTP 驗證,請把使用者名稱及密碼設在這裡。
</div>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册