提交 44f444e2 编写于 作者: K kohsuke

Started working on a better integrated maven support.

For a starter, I introduced AbstractProject/Build classes that host code that can be shared between Project/Build and MavenJob/MavenBuild. (I avoided the name MavenProject because it already exists in Maven.)


git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@1579 71c3de6d-444a-0410-be80-ed276b4c234a
上级 57edca0e
package hudson.maven;
import hudson.model.AbstractBuild;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
/**
* @author Kohsuke Kawaguchi
*/
public class MavenBuild extends AbstractBuild<MavenJob,MavenBuild> {
public MavenBuild(MavenJob job) throws IOException {
super(job);
}
public MavenBuild(MavenJob job, Calendar timestamp) {
super(job, timestamp);
}
public MavenBuild(MavenJob project, File buildDir) throws IOException {
super(project, buildDir);
}
public void run() {
// TODO
throw new UnsupportedOperationException();
}
}
package hudson.maven;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.model.JobDescriptor;
import hudson.model.RunMap;
import hudson.model.RunMap.Constructor;
import java.io.File;
import java.io.IOException;
/**
* @author Kohsuke Kawaguchi
*/
public final class MavenJob extends AbstractProject<MavenJob,MavenBuild> {
public MavenJob(Hudson parent, String name) {
super(parent, name);
}
protected void onLoad(Hudson root, String name) throws IOException {
super.onLoad(root, name);
this.builds = new RunMap<MavenBuild>();
this.builds.load(this,new Constructor<MavenBuild>() {
public MavenBuild create(File dir) throws IOException {
return new MavenBuild(MavenJob.this,dir);
}
});
}
@Override
public MavenBuild newBuild() throws IOException {
MavenBuild lastBuild = new MavenBuild(this);
builds.put(lastBuild);
return lastBuild;
}
public JobDescriptor<MavenJob,MavenBuild> getDescriptor() {
return DESCRIPTOR;
}
public static final JobDescriptor<MavenJob,MavenBuild> DESCRIPTOR = new JobDescriptor<MavenJob,MavenBuild>(MavenJob.class) {
public String getDisplayName() {
return "Building Maven2 project (alpha)";
}
public MavenJob newInstance(String name) {
return new MavenJob(Hudson.getInstance(),name);
}
};
}
<html><body>
Maven support (still a work in progress).
</body></html>
\ No newline at end of file
package hudson.model;
import hudson.Launcher;
import hudson.Proc.LocalProc;
import hudson.Util;
import hudson.maven.MavenBuild;
import static hudson.model.Hudson.isWindows;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Calendar;
/**
* Base implementation of {@link Run}s that build software.
*
* For now this is primarily the common part of {@link Build} and {@link MavenBuild}.
*
* @author Kohsuke Kawaguchi
* @see AbstractProject
*/
public abstract class AbstractBuild<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends Run<P,R> implements Runnable {
/**
* Name of the slave this project was built on.
* Null if built by the master.
*/
private String builtOn;
protected AbstractBuild(P job) throws IOException {
super(job);
}
protected AbstractBuild(P job, Calendar timestamp) {
super(job, timestamp);
}
protected AbstractBuild(P project, File buildDir) throws IOException {
super(project, buildDir);
}
public final P getProject() {
return getParent();
}
/**
* Returns a {@link Slave} on which this build was done.
*/
public Node getBuiltOn() {
if(builtOn==null)
return Hudson.getInstance();
else
return Hudson.getInstance().getSlave(builtOn);
}
/**
* Returns the name of the slave it was built on, or null if it was the master.
*/
public String getBuiltOnStr() {
return builtOn;
}
protected abstract class AbstractRunner implements Runner {
/**
* Since configuration can be changed while a build is in progress,
* stick to one launcher and use it.
*/
protected Launcher launcher;
public final Result run(BuildListener listener) throws Exception {
Node node = Executor.currentExecutor().getOwner().getNode();
assert builtOn==null;
builtOn = node.getNodeName();
launcher = node.createLauncher(listener);
if(node instanceof Slave)
listener.getLogger().println("Building remotely on "+node.getNodeName());
Result result = doRun(listener);
if(result!=null)
return result; // abort here
if(!isWindows()) {
try {
// ignore a failure.
new LocalProc(new String[]{"rm","../lastSuccessful"},new String[0],listener.getLogger(),getProject().getBuildDir()).join();
int r = new LocalProc(new String[]{
"ln","-s","builds/"+getId()/*ugly*/,"../lastSuccessful"},
new String[0],listener.getLogger(),getProject().getBuildDir()).join();
if(r!=0)
listener.getLogger().println("ln failed: "+r);
} catch (IOException e) {
PrintStream log = listener.getLogger();
log.println("ln failed");
Util.displayIOException(e,listener);
e.printStackTrace( log );
}
}
return Result.SUCCESS;
}
protected abstract Result doRun(BuildListener listener) throws Exception;
}
}
package hudson.model;
import hudson.maven.MavenJob;
import hudson.FilePath;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.File;
import java.util.SortedMap;
/**
* Base implementation of {@link Job}s that build software.
*
* For now this is primarily the common part of {@link Project} and {@link MavenJob}.
*
* @author Kohsuke Kawaguchi
* @see AbstractBuild
*/
public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends Job<P,R> {
/**
* All the builds keyed by their build number.
*/
protected transient /*almost final*/ RunMap<R> builds = new RunMap<R>();
/**
* The quiet period. Null to delegate to the system default.
*/
private Integer quietPeriod = null;
/**
* If this project is configured to be only built on a certain node,
* this value will be set to that node. Null to indicate the affinity
* with the master node.
*
* see #canRoam
*/
private String assignedNode;
/**
* True if this project can be built on any node.
*
* <p>
* This somewhat ugly flag combination is so that we can migrate
* existing Hudson installations nicely.
*/
private boolean canRoam;
/**
* True to suspend new builds.
*/
private boolean disabled;
/**
* Identifies {@link JDK} to be used.
* Null if no explicit configuration is required.
*
* <p>
* Can't store {@link JDK} directly because {@link Hudson} and {@link Project}
* are saved independently.
*
* @see Hudson#getJDK(String)
*/
private String jdk;
private boolean enableRemoteTrigger = false;
private String authToken = null;
protected AbstractProject(Hudson parent, String name) {
super(parent, name);
if(!parent.getSlaves().isEmpty()) {
// if a new job is configured with Hudson that already has slave nodes
// make it roamable by default
canRoam = true;
}
}
/**
* If this project is configured to be always built on this node,
* return that {@link Node}. Otherwise null.
*/
public Node getAssignedNode() {
if(canRoam)
return null;
if(assignedNode ==null)
return Hudson.getInstance();
return getParent().getSlave(assignedNode);
}
/**
* Gets the directory where the module is checked out.
*/
public FilePath getWorkspace() {
Node node = getLastBuiltOn();
if(node==null)
node = getParent();
if(node instanceof Slave)
return ((Slave)node).getWorkspaceRoot().child(getName());
else
return new FilePath(new File(getRootDir(),"workspace"));
}
public int getQuietPeriod() {
return quietPeriod!=null ? quietPeriod : getParent().getQuietPeriod();
}
// ugly name because of EL
public boolean getHasCustomQuietPeriod() {
return quietPeriod!=null;
}
public final boolean isBuildable() {
return true;
}
public boolean isDisabled() {
return disabled;
}
/**
* Schedules a build of this project.
*/
public void scheduleBuild() {
if(!disabled)
getParent().getQueue().add(this);
}
/**
* Returns true if the build is in the queue.
*/
@Override
public boolean isInQueue() {
return getParent().getQueue().contains(this);
}
public JDK getJDK() {
return getParent().getJDK(jdk);
}
/**
* Overwrites the JDK setting.
*/
public synchronized void setJDK(JDK jdk) throws IOException {
this.jdk = jdk.getName();
save();
}
public boolean isEnableRemoteTrigger() {
// no need to enable this option if security disabled
return (Hudson.getInstance().isUseSecurity())
&& enableRemoteTrigger;
}
public String getAuthToken() {
return authToken;
}
public SortedMap<Integer, ? extends R> _getRuns() {
return builds.getView();
}
public void removeRun(R run) {
this.builds.remove(run);
}
/**
* Creates a new build of this project for immediate execution.
*/
protected abstract R newBuild() throws IOException;
/**
* Gets the {@link Node} where this project was last built on.
*
* @return
* null if no information is available (for example,
* if no build was done yet.)
*/
public Node getLastBuiltOn() {
// where was it built on?
AbstractBuild b = getLastBuild();
if(b==null)
return null;
else
return b.getBuiltOn();
}
//
//
// actions
//
//
/**
* Schedules a new build command.
*/
public void doBuild( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
if (authorizedToStartBuild(req, rsp)) {
scheduleBuild();
rsp.forwardToPreviousPage(req);
}
}
private boolean authorizedToStartBuild(StaplerRequest req, StaplerResponse rsp) throws IOException {
if (isEnableRemoteTrigger()) {
String providedToken = req.getParameter("token");
if (providedToken != null && providedToken.equals(getAuthToken())) {
return true;
}
}
return Hudson.adminCheck(req, rsp);
}
/**
* Cancels a scheduled build.
*/
public void doCancelQueue( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
if(!Hudson.adminCheck(req,rsp))
return;
getParent().getQueue().cancel(this);
rsp.forwardToPreviousPage(req);
}
public synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
super.doConfigSubmit(req, rsp);
disabled = req.getParameter("disable")!=null;
jdk = req.getParameter("jdk");
if(req.getParameter("hasCustomQuietPeriod")!=null) {
quietPeriod = Integer.parseInt(req.getParameter("quiet_period"));
} else {
quietPeriod = null;
}
if(req.getParameter("hasSlaveAffinity")!=null) {
canRoam = false;
assignedNode = req.getParameter("slave");
if(assignedNode !=null) {
if(Hudson.getInstance().getSlave(assignedNode)==null) {
assignedNode = null; // no such slave
}
}
} else {
canRoam = true;
assignedNode = null;
}
if (req.getParameter("pseudoRemoteTrigger") != null) {
authToken = req.getParameter("authToken");
enableRemoteTrigger = true;
} else {
enableRemoteTrigger = false;
}
}
/**
* Serves the workspace files.
*/
public void doWs( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, InterruptedException {
FilePath ws = getWorkspace();
if(!ws.exists()) {
// if there's no workspace, report a nice error message
rsp.forward(this,"noWorkspace",req);
} else {
serveFile(req, rsp, ws, "folder.gif", true);
}
}
}
package hudson.model;
import hudson.Launcher;
import hudson.Util;
import hudson.Proc.LocalProc;
import hudson.model.Fingerprint.BuildPtr;
import hudson.model.Fingerprint.RangeSet;
import static hudson.model.Hudson.isWindows;
import hudson.scm.CVSChangeLogParser;
import hudson.scm.ChangeLogParser;
import hudson.scm.ChangeLogSet;
......@@ -26,7 +22,6 @@ import org.xml.sax.SAXException;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
......@@ -37,13 +32,7 @@ import java.util.Map;
/**
* @author Kohsuke Kawaguchi
*/
public final class Build extends Run<Project,Build> implements Runnable {
/**
* Name of the slave this project was built on.
* Null if built by the master.
*/
private String builtOn;
public final class Build extends AbstractBuild<Project,Build> {
/**
* SCM used for this build.
......@@ -63,10 +52,6 @@ public final class Build extends Run<Project,Build> implements Runnable {
super(project);
}
public Project getProject() {
return getParent();
}
/**
* Loads a build from a log file.
*/
......@@ -133,23 +118,6 @@ public final class Build extends Run<Project,Build> implements Runnable {
return timestamp;
}
/**
* Returns a {@link Slave} on which this build was done.
*/
public Node getBuiltOn() {
if(builtOn==null)
return Hudson.getInstance();
else
return Hudson.getInstance().getSlave(builtOn);
}
/**
* Returns the name of the slave it was built on, or null if it was the master.
*/
public String getBuiltOnStr() {
return builtOn;
}
/**
* Gets {@link AbstractTestResultAction} associated with this build if any.
*/
......@@ -300,111 +268,6 @@ public final class Build extends Run<Project,Build> implements Runnable {
*/
private transient List<Environment> buildEnvironments;
/**
* Performs a build.
*/
public void run() {
run(new Runner() {
/**
* Since configuration can be changed while a build is in progress,
* stick to one launcher and use it.
*/
private Launcher launcher;
public Result run(BuildListener listener) throws Exception {
Node node = Executor.currentExecutor().getOwner().getNode();
assert builtOn==null;
builtOn = node.getNodeName();
launcher = node.createLauncher(listener);
if(node instanceof Slave)
listener.getLogger().println("Building remotely on "+node.getNodeName());
if(!project.checkout(Build.this,launcher,listener,new File(getRootDir(),"changelog.xml")))
return Result.FAILURE;
SCM scm = project.getScm();
Build.this.scm = scm.createChangeLogParser();
Build.this.changeSet = Build.this.calcChangeSet();
if(!preBuild(listener,project.getBuilders()))
return Result.FAILURE;
if(!preBuild(listener,project.getPublishers()))
return Result.FAILURE;
buildEnvironments = new ArrayList<Environment>();
try {
for( BuildWrapper w : project.getBuildWrappers().values() ) {
Environment e = w.setUp(Build.this, launcher, listener);
if(e==null)
return Result.FAILURE;
buildEnvironments.add(e);
}
if(!build(listener,project.getBuilders()))
return Result.FAILURE;
} finally {
// tear down in reverse order
for( int i=buildEnvironments.size()-1; i>=0; i-- )
buildEnvironments.get(i).tearDown(Build.this,listener);
buildEnvironments = null;
}
if(!isWindows()) {
try {
// ignore a failure.
new LocalProc(new String[]{"rm","../lastSuccessful"},new String[0],listener.getLogger(),getProject().getBuildDir()).join();
int r = new LocalProc(new String[]{
"ln","-s","builds/"+getId()/*ugly*/,"../lastSuccessful"},
new String[0],listener.getLogger(),getProject().getBuildDir()).join();
if(r!=0)
listener.getLogger().println("ln failed: "+r);
} catch (IOException e) {
PrintStream log = listener.getLogger();
log.println("ln failed");
Util.displayIOException(e,listener);
e.printStackTrace( log );
}
}
return Result.SUCCESS;
}
public void post(BuildListener listener) {
// run all of them even if one of them failed
try {
for( Publisher bs : project.getPublishers().values() )
bs.perform(Build.this, launcher, listener);
} catch (InterruptedException e) {
e.printStackTrace(listener.fatalError("aborted"));
setResult(Result.FAILURE);
} catch (IOException e) {
e.printStackTrace(listener.fatalError("failed"));
setResult(Result.FAILURE);
}
}
private boolean build(BuildListener listener, Map<?, Builder> steps) throws IOException, InterruptedException {
for( Builder bs : steps.values() )
if(!bs.perform(Build.this, launcher, listener))
return false;
return true;
}
private boolean preBuild(BuildListener listener,Map<?,? extends BuildStep> steps) {
for( BuildStep bs : steps.values() )
if(!bs.prebuild(Build.this,listener))
return false;
return true;
}
});
}
@Override
protected void onStartBuilding() {
SCMTrigger t = (SCMTrigger)project.getTriggers().get(SCMTrigger.DESCRIPTOR);
......@@ -472,4 +335,77 @@ public final class Build extends Run<Project,Build> implements Runnable {
// nothing is building
rsp.forwardToPreviousPage(req);
}
/**
* Performs a build.
*/
public void run() {
run(new RunnerImpl());
}
private class RunnerImpl extends AbstractRunner {
protected Result doRun(BuildListener listener) throws Exception {
if(!project.checkout(Build.this,launcher,listener,new File(getRootDir(),"changelog.xml")))
return Result.FAILURE;
SCM scm = project.getScm();
Build.this.scm = scm.createChangeLogParser();
Build.this.changeSet = Build.this.calcChangeSet();
if(!preBuild(listener,project.getBuilders()))
return Result.FAILURE;
if(!preBuild(listener,project.getPublishers()))
return Result.FAILURE;
buildEnvironments = new ArrayList<Environment>();
try {
for( BuildWrapper w : project.getBuildWrappers().values() ) {
Environment e = w.setUp(Build.this, launcher, listener);
if(e==null)
return Result.FAILURE;
buildEnvironments.add(e);
}
if(!build(listener,project.getBuilders()))
return Result.FAILURE;
} finally {
// tear down in reverse order
for( int i=buildEnvironments.size()-1; i>=0; i-- )
buildEnvironments.get(i).tearDown(Build.this,listener);
buildEnvironments = null;
}
return null;
}
public void post(BuildListener listener) {
// run all of them even if one of them failed
try {
for( Publisher bs : project.getPublishers().values() )
bs.perform(Build.this, launcher, listener);
} catch (InterruptedException e) {
e.printStackTrace(listener.fatalError("aborted"));
setResult(Result.FAILURE);
} catch (IOException e) {
e.printStackTrace(listener.fatalError("failed"));
setResult(Result.FAILURE);
}
}
private boolean build(BuildListener listener, Map<?, Builder> steps) throws IOException, InterruptedException {
for( Builder bs : steps.values() )
if(!bs.perform(Build.this, launcher, listener))
return false;
return true;
}
private boolean preBuild(BuildListener listener,Map<?,? extends BuildStep> steps) {
for( BuildStep bs : steps.values() )
if(!bs.prebuild(Build.this,listener))
return false;
return true;
}
}
}
package hudson.model;
import hudson.remoting.VirtualChannel;
import hudson.EnvVars;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import hudson.util.DaemonThreadFactory;
import hudson.util.RunList;
import hudson.EnvVars;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......
......@@ -17,7 +17,7 @@ public class Executor extends Thread {
private final Computer owner;
private final Queue queue;
private Build build;
private AbstractBuild<?,?> build;
private long startTime;
......@@ -48,7 +48,7 @@ public class Executor extends Thread {
}
try {
Project p = queue.pop();
AbstractProject p = queue.pop();
build = p.newBuild();
} catch (InterruptedException e) {
continue;
......@@ -75,7 +75,7 @@ public class Executor extends Thread {
* @return
* null if the executor is idle.
*/
public Build getCurrentBuild() {
public AbstractBuild getCurrentBuild() {
return build;
}
......@@ -104,7 +104,7 @@ public class Executor extends Thread {
* if it's impossible to estimate the progress.
*/
public int getProgress() {
Build b = build.getProject().getLastSuccessfulBuild();
AbstractBuild b = build.getProject().getLastSuccessfulBuild();
if(b==null) return -1;
long duration = b.getDuration();
......@@ -120,7 +120,7 @@ public class Executor extends Thread {
* until the build completes.
*/
public String getEstimatedRemainingTime() {
Build b = build.getProject().getLastSuccessfulBuild();
AbstractBuild b = build.getProject().getLastSuccessfulBuild();
if(b==null) return "N/A";
long duration = b.getDuration();
......
package hudson.model;
import hudson.util.CharSpool;
import hudson.util.CountingOutputStream;
import hudson.util.WriterOutputStream;
import hudson.util.CharSpool;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
......@@ -11,9 +13,6 @@ import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Writer;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
/**
* Represents a large text data.
*
......
......@@ -43,19 +43,10 @@ import java.util.Vector;
*
* @author Kohsuke Kawaguchi
*/
public class Project extends Job<Project,Build> {
/**
* All the builds keyed by their build number.
*/
private transient /*almost final*/ RunMap<Build> builds = new RunMap<Build>();
public class Project extends AbstractProject<Project,Build> {
private SCM scm = new NullSCM();
private boolean enableRemoteTrigger = false;
private String authToken = null;
/**
* List of all {@link Trigger}s for this project.
*/
......@@ -85,94 +76,13 @@ public class Project extends Job<Project,Build> {
*/
private transient /*final*/ List<Action> transientActions = new Vector<Action>();
/**
* Identifies {@link JDK} to be used.
* Null if no explicit configuration is required.
*
* <p>
* Can't store {@link JDK} directly because {@link Hudson} and {@link Project}
* are saved independently.
*
* @see Hudson#getJDK(String)
*/
private String jdk;
/**
* The quiet period. Null to delegate to the system default.
*/
private Integer quietPeriod = null;
/**
* If this project is configured to be only built on a certain node,
* this value will be set to that node. Null to indicate the affinity
* with the master node.
*
* see #canRoam
*/
private String assignedNode;
/**
* True if this project can be built on any node.
*
* <p>
* This somewhat ugly flag combination is so that we can migrate
* existing Hudson installations nicely.
*/
private boolean canRoam;
/**
* True to suspend new builds.
*/
private boolean disabled;
/**
* Creates a new project.
*/
public Project(Hudson parent,String name) {
super(parent,name);
if(!parent.getSlaves().isEmpty()) {
// if a new job is configured with Hudson that already has slave nodes
// make it roamable by default
canRoam = true;
}
}
/**
* If this project is configured to be always built on this node,
* return that {@link Node}. Otherwise null.
*/
public Node getAssignedNode() {
if(canRoam)
return null;
if(assignedNode ==null)
return Hudson.getInstance();
return getParent().getSlave(assignedNode);
}
public JDK getJDK() {
return getParent().getJDK(jdk);
}
/**
* Overwrites the JDK setting.
*/
public synchronized void setJDK(JDK jdk) throws IOException {
this.jdk = jdk.getName();
save();
}
public int getQuietPeriod() {
return quietPeriod!=null ? quietPeriod : getParent().getQuietPeriod();
}
// ugly name because of EL
public boolean getHasCustomQuietPeriod() {
return quietPeriod!=null;
}
protected void onLoad(Hudson root, String name) throws IOException {
super.onLoad(root, name);
......@@ -196,14 +106,6 @@ public class Project extends Job<Project,Build> {
updateTransientActions();
}
public boolean isBuildable() {
return !isDisabled();
}
public boolean isDisabled() {
return disabled;
}
public SCM getScm() {
return scm;
}
......@@ -212,16 +114,6 @@ public class Project extends Job<Project,Build> {
this.scm = scm;
}
public boolean isEnableRemoteTrigger() {
// no need to enable this option if security disabled
return (Hudson.getInstance().isUseSecurity())
&& enableRemoteTrigger;
}
public String getAuthToken() {
return authToken;
}
@Override
public BallColor getIconColor() {
if(isDisabled())
......@@ -299,17 +191,7 @@ public class Project extends Job<Project,Build> {
removeFromList(descriptor, publishers);
}
public SortedMap<Integer, ? extends Build> _getRuns() {
return builds.getView();
}
public void removeRun(Build run) {
this.builds.remove(run);
}
/**
* Creates a new build of this project for immediate execution.
*/
@Override
public Build newBuild() throws IOException {
Build lastBuild = new Build(this);
builds.put(lastBuild);
......@@ -364,37 +246,6 @@ public class Project extends Job<Project,Build> {
}
}
/**
* Gets the {@link Node} where this project was last built on.
*
* @return
* null if no information is available (for example,
* if no build was done yet.)
*/
public Node getLastBuiltOn() {
// where was it built on?
Build b = getLastBuild();
if(b==null)
return null;
else
return b.getBuiltOn();
}
/**
* Gets the directory where the module is checked out.
*/
public FilePath getWorkspace() {
Node node = getLastBuiltOn();
if(node==null)
node = getParent();
if(node instanceof Slave)
return ((Slave)node).getWorkspaceRoot().child(getName());
else
return new FilePath(new File(getRootDir(),"workspace"));
}
/**
* Returns the root directory of the checked-out module.
*
......@@ -467,22 +318,6 @@ public class Project extends Job<Project,Build> {
}
}
/**
* Schedules a build of this project.
*/
public void scheduleBuild() {
if(!disabled)
getParent().getQueue().add(this);
}
/**
* Returns true if the build is in the queue.
*/
@Override
public boolean isInQueue() {
return getParent().getQueue().contains(this);
}
/**
* Schedules the SCM polling. If a polling is already in progress
* or a build is in progress, polling will take place after that.
......@@ -515,39 +350,6 @@ public class Project extends Job<Project,Build> {
// actions
//
//
/**
* Schedules a new build command.
*/
public void doBuild( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
if (authorizedToStartBuild(req, rsp)) {
scheduleBuild();
rsp.forwardToPreviousPage(req);
}
}
private boolean authorizedToStartBuild(StaplerRequest req, StaplerResponse rsp) throws IOException {
if (isEnableRemoteTrigger()) {
String providedToken = req.getParameter("token");
if (providedToken != null && providedToken.equals(getAuthToken())) {
return true;
}
}
return Hudson.adminCheck(req, rsp);
}
/**
* Cancels a scheduled build.
*/
public void doCancelQueue( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
if(!Hudson.adminCheck(req,rsp))
return;
getParent().getQueue().cancel(this);
rsp.forwardToPreviousPage(req);
}
/**
* Accepts submission from the configuration page.
*/
......@@ -565,35 +367,6 @@ public class Project extends Job<Project,Build> {
int scmidx = Integer.parseInt(req.getParameter("scm"));
scm = SCMS.SCMS.get(scmidx).newInstance(req);
disabled = req.getParameter("disable")!=null;
jdk = req.getParameter("jdk");
if(req.getParameter("hasCustomQuietPeriod")!=null) {
quietPeriod = Integer.parseInt(req.getParameter("quiet_period"));
} else {
quietPeriod = null;
}
if(req.getParameter("hasSlaveAffinity")!=null) {
canRoam = false;
assignedNode = req.getParameter("slave");
if(assignedNode !=null) {
if(Hudson.getInstance().getSlave(assignedNode)==null) {
assignedNode = null; // no such slave
}
}
} else {
canRoam = true;
assignedNode = null;
}
if (req.getParameter("pseudoRemoteTrigger") != null) {
authToken = req.getParameter("authToken");
enableRemoteTrigger = true;
} else {
enableRemoteTrigger = false;
}
buildDescribable(req, BuildWrappers.WRAPPERS, buildWrappers, "wrapper");
buildDescribable(req, BuildStep.BUILDERS, builders, "builder");
buildDescribable(req, BuildStep.PUBLISHERS, publishers, "publisher");
......@@ -691,19 +464,6 @@ public class Project extends Job<Project,Build> {
}
}
/**
* Serves the workspace files.
*/
public void doWs( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, InterruptedException {
FilePath ws = getWorkspace();
if(!ws.exists()) {
// if there's no workspace, report a nice error message
rsp.forward(this,"noWorkspace",req);
} else {
serveFile(req, rsp, ws, "folder.gif", true);
}
}
/**
* @deprecated
* left for legacy config file compatibility
......
......@@ -57,13 +57,13 @@ public class Queue {
* {@link Project}s that can be built immediately
* but blocked because another build is in progress.
*/
private final Set<Project> blockedProjects = new HashSet<Project>();
private final Set<AbstractProject> blockedProjects = new HashSet<AbstractProject>();
/**
* {@link Project}s that can be built immediately
* that are waiting for available {@link Executor}.
*/
private final List<Project> buildables = new LinkedList<Project>();
private final List<AbstractProject> buildables = new LinkedList<AbstractProject>();
/**
* Data structure created for each idle {@link Executor}.
......@@ -84,13 +84,13 @@ public class Queue {
* The project that this {@link Executor} is going to build.
* (Or null, in which case event is used to trigger a queue maintenance.)
*/
Project project;
AbstractProject project;
public JobOffer(Executor executor) {
this.executor = executor;
}
public void set(Project p) {
public void set(AbstractProject p) {
this.project = p;
event.signal();
}
......@@ -158,7 +158,7 @@ public class Queue {
/**
* Schedule a new build for this project.
*/
public synchronized void add( Project p ) {
public synchronized void add( AbstractProject p ) {
if(contains(p))
return; // no double queueing
......@@ -170,7 +170,7 @@ public class Queue {
scheduleMaintenance(); // let an executor know that a new item is in the queue.
}
public synchronized void cancel( Project p ) {
public synchronized void cancel( AbstractProject<?,?> p ) {
for (Iterator itr = queue.iterator(); itr.hasNext();) {
Item item = (Item) itr.next();
if(item.project==p) {
......@@ -198,10 +198,10 @@ public class Queue {
queue.toArray(r);
int idx=queue.size();
Calendar now = new GregorianCalendar();
for (Project p : blockedProjects) {
for (AbstractProject p : blockedProjects) {
r[idx++] = new Item(now, p);
}
for (Project p : buildables) {
for (AbstractProject p : buildables) {
r[idx++] = new Item(now, p);
}
return r;
......@@ -210,7 +210,7 @@ public class Queue {
/**
* Returns true if this queue contains the said project.
*/
public synchronized boolean contains(Project p) {
public synchronized boolean contains(AbstractProject p) {
// if this project is already scheduled,
// don't do anything
if(blockedProjects.contains(p) || buildables.contains(p))
......@@ -227,7 +227,7 @@ public class Queue {
*
* This method blocks until a next project becomes buildable.
*/
public Project pop() throws InterruptedException {
public AbstractProject pop() throws InterruptedException {
final Executor exec = Executor.currentExecutor();
boolean successfulReturn = false;
......@@ -247,9 +247,9 @@ public class Queue {
maintain();
// allocate buildable jobs to executors
Iterator<Project> itr = buildables.iterator();
Iterator<AbstractProject> itr = buildables.iterator();
while(itr.hasNext()) {
Project p = itr.next();
AbstractProject p = itr.next();
JobOffer runner = choose(p);
if(runner==null)
// if we couldn't find the executor that fits,
......@@ -321,7 +321,7 @@ public class Queue {
* @return
* null if no {@link Executor} can run it.
*/
private JobOffer choose(Project p) {
private JobOffer choose(AbstractProject<?,?> p) {
if(Hudson.getInstance().isQuietingDown()) {
// if we are quieting down, don't run anything so that
// all executors will be free.
......@@ -352,7 +352,7 @@ public class Queue {
// duration of a build on a slave tends not to have an impact on
// the master/slave communication, so that means we should favor
// running long jobs on slaves.
Build succ = p.getLastSuccessfulBuild();
AbstractBuild succ = p.getLastSuccessfulBuild();
if(succ!=null && succ.getDuration()>15*60*1000) {
// consider a long job to be > 15 mins
for (JobOffer offer : parked.values()) {
......@@ -399,10 +399,10 @@ public class Queue {
* appropriately.
*/
private synchronized void maintain() {
Iterator<Project> itr = blockedProjects.iterator();
Iterator<AbstractProject> itr = blockedProjects.iterator();
while(itr.hasNext()) {
Project p = itr.next();
Build lastBuild = p.getLastBuild();
AbstractProject<?,?> p = itr.next();
AbstractBuild lastBuild = p.getLastBuild();
if (lastBuild == null || !lastBuild.isBuilding()) {
// ready to be executed
itr.remove();
......@@ -416,7 +416,7 @@ public class Queue {
if(!top.timestamp.before(new GregorianCalendar()))
return; // finished moving all ready items from queue
Build lastBuild = top.project.getLastBuild();
AbstractBuild lastBuild = top.project.getLastBuild();
if(lastBuild==null || !lastBuild.isBuilding()) {
// ready to be executed immediately
queue.remove(top);
......@@ -442,7 +442,7 @@ public class Queue {
/**
* Project to be built.
*/
final Project project;
final AbstractProject<?,?> project;
/**
* Unique number of this {@link Item}.
......@@ -450,7 +450,7 @@ public class Queue {
*/
final int id;
public Item(Calendar timestamp, Project project) {
public Item(Calendar timestamp, AbstractProject project) {
this.timestamp = timestamp;
this.project = project;
synchronized(Queue.this) {
......@@ -462,7 +462,7 @@ public class Queue {
return timestamp;
}
public Project getProject() {
public AbstractProject getProject() {
return project;
}
......
package hudson.model;
import hudson.CloseProofOutputStream;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Launcher.LocalLauncher;
import hudson.Proc;
import hudson.Proc.RemoteProc;
import hudson.Util;
import hudson.CloseProofOutputStream;
import hudson.Launcher.LocalLauncher;
import hudson.model.Descriptor.FormException;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Listener;
import hudson.remoting.RemoteInputStream;
import hudson.remoting.RemoteOutputStream;
import hudson.remoting.VirtualChannel;
import hudson.remoting.Channel.Listener;
import hudson.util.NullStream;
import hudson.util.StreamCopyThread;
import hudson.util.StreamTaskListener;
import hudson.util.NullStream;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
/**
* Information about a Hudson slave node.
*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册