26
26
import com.google.common.base.Function;
27
27
import com.google.common.collect.Collections2;
28
28
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
29
import hudson.BulkChange;
29
30
import hudson.EnvVars;
30
31
import hudson.Extension;
31
32
import hudson.ExtensionPoint;
52
53
import hudson.util.DescribableList;
53
54
import hudson.util.FormApply;
54
55
import hudson.util.Graph;
56
import hudson.util.ProcessTree;
55
57
import hudson.util.RunList;
56
58
import hudson.util.ShiftedCategoryAxis;
57
59
import hudson.util.StackedAreaRenderer2;
59
61
import hudson.widgets.HistoryWidget;
60
62
import hudson.widgets.HistoryWidget.Adapter;
61
63
import hudson.widgets.Widget;
64
import jenkins.model.BuildDiscarder;
62
65
import jenkins.model.Jenkins;
63
66
import jenkins.model.ProjectNamingStrategy;
67
import jenkins.scm.SCMCheckoutStrategy;
64
68
import jenkins.security.HexStringConfidentialKey;
65
69
import jenkins.util.io.OnMaster;
66
70
import net.sf.json.JSONException;
124
128
private transient volatile boolean holdOffBuildUntilSave;
126
private volatile LogRotator logRotator;
130
private volatile BuildDiscarder logRotator;
129
133
* Not all plugins are good at calculating their health report quickly.
309
* Builds up the environment variable map that's sufficient to identify a process
310
* as ours. This is used to kill run-away processes via {@link ProcessTree#killAll(Map)}.
312
public EnvVars getCharacteristicEnvVars() {
313
EnvVars env = new EnvVars();
314
env.put("JENKINS_SERVER_COOKIE",SERVER_COOKIE.get());
315
env.put("HUDSON_SERVER_COOKIE",SERVER_COOKIE.get()); // Legacy compatibility
316
env.put("JOB_NAME",getFullName());
321
* Creates an environment variable override for launching processes for this project.
324
* This is for process launching outside the build execution (such as polling, tagging, deployment, etc.)
325
* that happens in a context of a specific job.
328
* Node to eventually run a process on. The implementation must cope with this parameter being null
329
* (in which case none of the node specific properties would be reflected in the resulting override.)
331
public EnvVars getEnvironment(Node node, TaskListener listener) throws IOException, InterruptedException {
335
env = node.toComputer().buildEnvironment(listener);
339
env.putAll(getCharacteristicEnvVars());
341
// servlet container may have set CLASSPATH in its launch script,
342
// so don't let that inherit to the new child process.
343
// see http://www.nabble.com/Run-Job-with-JDK-1.4.2-tf4468601.html
344
env.put("CLASSPATH","");
306
350
* Programatically updates the next build number.
324
* Returns the log rotator for this job, or null if none.
368
* Returns the configured build discarder for this job, or null if none.
370
public BuildDiscarder getBuildDiscarder() {
374
public void setBuildDiscarder(BuildDiscarder bd) throws IOException {
375
this.logRotator = bd;
380
* Left for backward compatibility. Returns non-null if and only
381
* if {@link LogRotator} is configured as {@link BuildDiscarder}.
383
* @deprecated as of 1.503
384
* Use {@link #getBuildDiscarder()}.
326
386
public LogRotator getLogRotator() {
387
if (logRotator instanceof LogRotator)
388
return (LogRotator) logRotator;
330
public void setLogRotator(LogRotator logRotator) {
331
this.logRotator = logRotator;
393
* @deprecated as of 1.503
394
* Use {@link #setBuildDiscarder(BuildDiscarder)}
396
public void setLogRotator(LogRotator logRotator) throws IOException {
397
setBuildDiscarder(logRotator);
335
401
* Perform log rotation.
337
403
public void logRotate() throws IOException, InterruptedException {
338
LogRotator lr = getLogRotator();
404
BuildDiscarder bd = getBuildDiscarder();
508
575
public void renameTo(String newName) throws IOException {
576
File oldBuildDir = getBuildDir();
509
577
super.renameTo(newName);
578
File newBuildDir = getBuildDir();
579
if (oldBuildDir.isDirectory() && !newBuildDir.isDirectory()) {
580
if (!oldBuildDir.renameTo(newBuildDir)) {
581
throw new IOException("failed to rename " + oldBuildDir + " to " + newBuildDir);
586
@Override public synchronized void delete() throws IOException, InterruptedException {
588
Util.deleteRecursive(getBuildDir());
521
600
* @return never null. The first entry is the latest build.
602
@Exported(name="allBuilds",visibility=-2)
524
603
@WithBridgeMethods(List.class)
525
604
public RunList<RunT> getBuilds() {
526
605
return RunList.fromRuns(_getRuns().values());
609
* Gets the read-only view of the recent builds.
613
@Exported(name="builds")
614
public RunList<RunT> getNewBuilds() {
615
return getBuilds().limit(100);
530
619
* Obtains all the {@link Run}s whose build numbers matches the given {@link RangeSet}.
532
621
public synchronized List<RunT> getBuilds(RangeSet rs) {
602
691
* This is useful when you'd like to fetch a build but the exact build might
603
692
* be already gone (deleted, rotated, etc.)
605
public final RunT getNearestBuild(int n) {
694
public RunT getNearestBuild(int n) {
606
695
SortedMap<Integer, ? extends RunT> m = _getRuns().headMap(n - 1); // the map should
607
696
// include n, so n-1
616
705
* This is useful when you'd like to fetch a build but the exact build might
617
706
* be already gone (deleted, rotated, etc.)
619
public final RunT getNearestOldBuild(int n) {
708
public RunT getNearestOldBuild(int n) {
620
709
SortedMap<Integer, ? extends RunT> m = _getRuns().tailMap(n);
628
717
StaplerResponse rsp) {
630
719
// try to interpret the token as build number
631
return _getRuns().get(Integer.valueOf(token));
720
return getBuildByNumber(Integer.valueOf(token));
632
721
} catch (NumberFormatException e) {
633
722
// try to map that to widgets
634
723
for (Widget w : getWidgets()) {
658
protected File getBuildDir() {
747
public File getBuildDir() {
659
748
return Jenkins.getInstance().getBuildDirFor(this);
663
752
* Gets all the runs.
665
* The resulting map must be immutable (by employing copy-on-write
754
* The resulting map must be treated immutable (by employing copy-on-write
666
755
* semantics.) The map is descending order, with newest builds at the top.
668
757
protected abstract SortedMap<Integer, ? extends RunT> _getRuns();
712
801
public RunT getLastSuccessfulBuild() {
713
RunT r = getLastBuild();
714
// temporary hack till we figure out what's causing this bug
716
&& (r.isBuilding() || r.getResult() == null || r.getResult()
717
.isWorseThan(Result.UNSTABLE)))
718
r = r.getPreviousBuild();
802
return (RunT)Permalink.LAST_SUCCESSFUL_BUILD.resolve(this);
978
1061
setDisplayName(json.optString("displayNameOrNull"));
980
if (req.getParameter("logrotate") != null)
981
logRotator = LogRotator.DESCRIPTOR.newInstance(req,json.getJSONObject("logrotate"));
1063
if (json.optBoolean("logrotate"))
1064
logRotator = req.bindJSON(BuildDiscarder.class, json.optJSONObject("buildDiscarder"));
983
1066
logRotator = null;
1262
1345
return new BuildTimelineWidget(getBuilds());
1265
/*package*/ final static HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class,"serverCookie",16);
1348
private final static HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class,"serverCookie",16);