diff --git a/core/src/main/java/hudson/maven/MavenModule.java b/core/src/main/java/hudson/maven/MavenModule.java index 3682f9990ffbaa4e633fb06e0b24e130fd403c86..336015cc03c6e865aed32a6094d6c980f1cd64d7 100644 --- a/core/src/main/java/hudson/maven/MavenModule.java +++ b/core/src/main/java/hudson/maven/MavenModule.java @@ -6,7 +6,9 @@ import hudson.model.Descriptor.FormException; import hudson.model.Hudson; import hudson.model.Items; import hudson.model.Job; +import hudson.model.ItemGroup; import hudson.util.DescribableList; +import hudson.FilePath; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -36,6 +38,17 @@ public final class MavenModule extends AbstractProject i reporters.setOwner(this); } + @Override + public FilePath getWorkspace() { + // TODO: implement this method later + throw new UnsupportedOperationException(); + } + + + public MavenModuleSet getParent() { + return (MavenModuleSet)super.getParent(); + } + @Override public MavenBuild newBuild() throws IOException { MavenBuild lastBuild = new MavenBuild(this); diff --git a/core/src/main/java/hudson/maven/MavenModuleSet.java b/core/src/main/java/hudson/maven/MavenModuleSet.java index 88a1fab75f30e6b5d6436fbd02b6db2738379dde..9380c415e3d6904ae06c78bf7234d904af7e94d3 100644 --- a/core/src/main/java/hudson/maven/MavenModuleSet.java +++ b/core/src/main/java/hudson/maven/MavenModuleSet.java @@ -1,30 +1,31 @@ package hudson.maven; +import hudson.FilePath; +import hudson.Launcher; import hudson.model.AbstractItem; +import hudson.model.Descriptor.FormException; import hudson.model.Hudson; import hudson.model.ItemGroup; -import hudson.model.TopLevelItem; -import hudson.model.TopLevelItemDescriptor; import hudson.model.Items; import hudson.model.JDK; import hudson.model.Project; -import hudson.model.Descriptor.FormException; -import hudson.util.CopyOnWriteMap; -import hudson.scm.SCM; +import hudson.model.TaskListener; +import hudson.model.TopLevelItem; +import hudson.model.TopLevelItemDescriptor; import hudson.scm.NullSCM; +import hudson.scm.SCM; import hudson.scm.SCMS; +import hudson.util.CopyOnWriteMap; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import javax.servlet.ServletException; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.Collection; import java.util.Map; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; - -import javax.servlet.ServletException; - /** * Group of {@link MavenModule}s. * @@ -61,7 +62,7 @@ public class MavenModuleSet extends AbstractItem implements TopLevelItem, ItemGr private boolean disabled; public MavenModuleSet(String name) { - super(name); + super(Hudson.getInstance(),name); } public String getUrlChildPrefix() { @@ -100,6 +101,14 @@ public class MavenModuleSet extends AbstractItem implements TopLevelItem, ItemGr return getItems(); } + /** + * Gets the workspace of this job. + */ + public FilePath getWorkspace() { + // TODO: support roaming and etc + return Hudson.getInstance().getWorkspaceFor(this); + } + public void onLoad(String name) throws IOException { super.onLoad(name); @@ -123,6 +132,22 @@ public class MavenModuleSet extends AbstractItem implements TopLevelItem, ItemGr } } + /** + * Obtains a workspace. + */ + public boolean checkout(Launcher launcher, TaskListener listener) throws IOException { + try { + FilePath workspace = getWorkspace(); + workspace.mkdirs(); + + return scm.checkout(launcher, workspace, listener); + } catch (InterruptedException e) { + e.printStackTrace(listener.fatalError("SCM check out aborted")); + return false; + } + } + + public synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { if(!Hudson.adminCheck(req,rsp)) return; diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 7bc69307dd9638d225cd05acd5ddc031dd124641..8762183a4cd34140cd08c8664e43f7f13d961217 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -35,8 +35,11 @@ public abstract class AbstractItem extends Actionable implements Item { */ protected transient File root; - protected AbstractItem(String name) { + private ItemGroup parent; + + protected AbstractItem(ItemGroup parent, String name) { doSetName(name); + this.parent = parent; } public String getName() { @@ -51,6 +54,11 @@ public abstract class AbstractItem extends Actionable implements Item { return root; } + public ItemGroup getParent() { + assert parent!=null; + return parent; + } + /** * Gets the project description HTML. */ diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 185c1c0587fcf57c3dae82d925253a4aaf0fcb82..fc32d249b2a50807d6efeb1fdf954599826961e0 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -94,10 +94,10 @@ public abstract class AbstractProject

,R extends A */ protected List triggers = new Vector(); - protected AbstractProject(Hudson parent, String name) { - super(name); + protected AbstractProject(ItemGroup parent, String name) { + super(parent,name); - if(!parent.getSlaves().isEmpty()) { + if(!Hudson.getInstance().getSlaves().isEmpty()) { // if a new job is configured with Hudson that already has slave nodes // make it roamable by default canRoam = true; @@ -132,23 +132,13 @@ public abstract class AbstractProject

,R extends A if(assignedNode ==null) return Hudson.getInstance(); - return getParent().getSlave(assignedNode); + return Hudson.getInstance().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 abstract FilePath getWorkspace(); /** * Returns the root directory of the checked-out module. @@ -161,7 +151,7 @@ public abstract class AbstractProject

,R extends A } public int getQuietPeriod() { - return quietPeriod!=null ? quietPeriod : getParent().getQuietPeriod(); + return quietPeriod!=null ? quietPeriod : Hudson.getInstance().getQuietPeriod(); } // ugly name because of EL @@ -182,7 +172,7 @@ public abstract class AbstractProject

,R extends A */ public void scheduleBuild() { if(!disabled) - getParent().getQueue().add(this); + Hudson.getInstance().getQueue().add(this); } /** @@ -190,11 +180,11 @@ public abstract class AbstractProject

,R extends A */ @Override public boolean isInQueue() { - return getParent().getQueue().contains(this); + return Hudson.getInstance().getQueue().contains(this); } public JDK getJDK() { - return getParent().getJDK(jdk); + return Hudson.getInstance().getJDK(jdk); } /** @@ -444,7 +434,7 @@ public abstract class AbstractProject

,R extends A if(!Hudson.adminCheck(req,rsp)) return; - getParent().getQueue().cancel(this); + Hudson.getInstance().getQueue().cancel(this); rsp.forwardToPreviousPage(req); } diff --git a/core/src/main/java/hudson/model/ExternalJob.java b/core/src/main/java/hudson/model/ExternalJob.java index bc06e793b2b4da38be388d0fe439a08b9c52af82..daeebb6c08a2cdd2e622d4d7ec6b2e1c4034de86 100644 --- a/core/src/main/java/hudson/model/ExternalJob.java +++ b/core/src/main/java/hudson/model/ExternalJob.java @@ -22,6 +22,11 @@ public class ExternalJob extends ViewJob implements Top super(parent,name); } + @Override + public Hudson getParent() { + return (Hudson)super.getParent(); + } + @Override protected void reload() { this.runs.load(this,new Constructor() { diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index d1b0753f07503ca59c763eca3a718ba42ecc465e..da2bcf99e7f90f8d9e7732dbc30832a4fbde3aee 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -10,6 +10,7 @@ import hudson.PluginManager; import hudson.PluginWrapper; import hudson.Util; import hudson.XmlFile; +import hudson.FilePath; import hudson.model.Descriptor.FormException; import hudson.model.listeners.ItemListener; import hudson.model.listeners.JobListener; @@ -578,6 +579,10 @@ public final class Hudson extends View implements ItemGroup, Node return root; } + public FilePath getWorkspaceFor(TopLevelItem item) { + return new FilePath(new File(item.getRootDir(),"workspace")); + } + public boolean isUseSecurity() { return useSecurity; } diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index 8fed2847f4445eb230db4bdf9e739cf88dc40901..ea109177833023987ce21b955147aa38683af01c 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -72,8 +72,8 @@ public abstract class Job, RunT extends Run> properties = new CopyOnWriteList>(); - protected Job(String name) { - super(name); + protected Job(ItemGroup parent,String name) { + super(parent,name); getBuildDir().mkdirs(); } @@ -114,10 +114,6 @@ public abstract class Job, RunT extends Run + * Workspace directory is usually used for keeping out the checked out + * source code, but it can be used for anything. + */ + FilePath getWorkspaceFor(TopLevelItem item); + public enum Mode { NORMAL("Utilize this slave as much as possible"), EXCLUSIVE("Leave this machine for tied jobs only"); diff --git a/core/src/main/java/hudson/model/Project.java b/core/src/main/java/hudson/model/Project.java index 75a7d5547713e633a2665637f33978acc965493c..4e62a4c06c5c8396d3c856b05d08aacaef84a375 100644 --- a/core/src/main/java/hudson/model/Project.java +++ b/core/src/main/java/hudson/model/Project.java @@ -9,6 +9,7 @@ import hudson.tasks.Builder; import hudson.tasks.Fingerprinter; import hudson.tasks.Publisher; import hudson.triggers.Trigger; +import hudson.FilePath; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -71,6 +72,18 @@ public class Project extends AbstractProject implements TopLevelI updateTransientActions(); } + @Override + public Hudson getParent() { + return Hudson.getInstance(); + } + + @Override + public FilePath getWorkspace() { + Node node = getLastBuiltOn(); + if(node==null) node = getParent(); + return node.getWorkspaceFor(this); + } + @Override public BallColor getIconColor() { if(isDisabled()) diff --git a/core/src/main/java/hudson/model/Slave.java b/core/src/main/java/hudson/model/Slave.java index d79f449125f991802d479266a94a7a02e4ab14f8..e4c8f5c5ab11d557fce60ff55d140136dc1d1829 100644 --- a/core/src/main/java/hudson/model/Slave.java +++ b/core/src/main/java/hudson/model/Slave.java @@ -179,6 +179,10 @@ public final class Slave implements Node, Serializable { return new ComputerImpl(this); } + public FilePath getWorkspaceFor(TopLevelItem item) { + return getWorkspaceRoot().child(item.getName()); + } + /** * Root directory on this slave where all the job workspaces are laid out. */ diff --git a/core/src/main/java/hudson/model/ViewJob.java b/core/src/main/java/hudson/model/ViewJob.java index ec4bb2b241abffd1cdd0a2bfe3ac496056193dab..49275f98d2380b703fab0956e88d9b7ca6ce63d4 100644 --- a/core/src/main/java/hudson/model/ViewJob.java +++ b/core/src/main/java/hudson/model/ViewJob.java @@ -52,7 +52,7 @@ public abstract class ViewJob, RunT extends Run< } protected ViewJob(Hudson parent, String name) { - super(name); + super(parent,name); } public boolean isBuildable() { diff --git a/core/src/main/java/hudson/scm/CVSSCM.java b/core/src/main/java/hudson/scm/CVSSCM.java index 90d19605c8c7edff91d220c25a5b91d7e6df27cf..18397fe1bf2e643a6c79f205903f00b006ac1e2c 100644 --- a/core/src/main/java/hudson/scm/CVSSCM.java +++ b/core/src/main/java/hudson/scm/CVSSCM.java @@ -182,18 +182,7 @@ public class CVSSCM extends AbstractCVSFamilySCM implements Serializable { if(changedFiles==null) return false; // failed } else { - dir.deleteContents(); - - ArgumentListBuilder cmd = new ArgumentListBuilder(); - cmd.add(getDescriptor().getCvsExe(),debugLogging?"-t":"-Q","-z9","-d",cvsroot,"co"); - if(branch!=null) - cmd.add("-r",branch); - if(flatten) - cmd.add("-d",dir.getName()); - configureDate(cmd, build.getTimestamp().getTime()); - cmd.addTokenized(module); - - if(!run(launcher,cmd,listener, flatten ? dir.getParent() : dir)) + if(!checkout(launcher,dir,listener,build.getTimestamp().getTime())) return false; } @@ -241,6 +230,25 @@ public class CVSSCM extends AbstractCVSFamilySCM implements Serializable { return calcChangeLog(build, changedFiles, changelogFile, listener); } + public boolean checkout(Launcher launcher, FilePath dir, TaskListener listener) throws IOException, InterruptedException { + return checkout(launcher,dir,listener,new Date()); + } + + private boolean checkout(Launcher launcher, FilePath dir, TaskListener listener, Date dt) throws IOException, InterruptedException { + dir.deleteContents(); + + ArgumentListBuilder cmd = new ArgumentListBuilder(); + cmd.add(getDescriptor().getCvsExe(),debugLogging?"-t":"-Q","-z9","-d",cvsroot,"co"); + if(branch!=null) + cmd.add("-r",branch); + if(flatten) + cmd.add("-d",dir.getName()); + configureDate(cmd,dt); + cmd.addTokenized(module); + + return run(launcher,cmd,listener, flatten ? dir.getParent() : dir); + } + /** * Returns the file name used to archive the build. */ diff --git a/core/src/main/java/hudson/scm/NullSCM.java b/core/src/main/java/hudson/scm/NullSCM.java index 5b0833be19c1066d0afb623f42dbdb7314e96c76..dc101f808e2097cb87ceec8e2411d0720e25820b 100644 --- a/core/src/main/java/hudson/scm/NullSCM.java +++ b/core/src/main/java/hudson/scm/NullSCM.java @@ -28,6 +28,10 @@ public class NullSCM extends AbstractCVSFamilySCM /*to reuse createEmptyChangeLo return createEmptyChangeLog(changeLogFile, listener, "log"); } + public boolean checkout(Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { + return true; + } + public Descriptor getDescriptor() { return DESCRIPTOR; } diff --git a/core/src/main/java/hudson/scm/SCM.java b/core/src/main/java/hudson/scm/SCM.java index 849824b5edd92c6d49a876d42ab5ca4da4b2df0e..8aabc4046502b787bc02e04fb711cff5b0f9a6c9 100644 --- a/core/src/main/java/hudson/scm/SCM.java +++ b/core/src/main/java/hudson/scm/SCM.java @@ -78,6 +78,14 @@ public interface SCM extends Describable, ExtensionPoint { */ boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener, File changelogFile) throws IOException, InterruptedException; + /** + * Checks out the code into the workspace, but without computing changelog. + * + * TODO: This is an ugly abstraction. + * come back and check if this abstraction is really making much sense. + */ + boolean checkout(Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException; + /** * Adds environmental variables for the builds to the given map. */ diff --git a/core/src/main/java/hudson/scm/SubversionSCM.java b/core/src/main/java/hudson/scm/SubversionSCM.java index 2c65d392bfeed6654a62111accc7b0e133d286e5..3c51c55dca0c61c4137f6f45ce9aebfdc3d9498c 100644 --- a/core/src/main/java/hudson/scm/SubversionSCM.java +++ b/core/src/main/java/hudson/scm/SubversionSCM.java @@ -17,7 +17,6 @@ import hudson.util.FormFieldValidator; import hudson.util.Scrambler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; -import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -217,37 +216,11 @@ public class SubversionSCM extends AbstractCVSFamilySCM implements Serializable } public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, final BuildListener listener, File changelogFile) throws IOException, InterruptedException { - boolean result; - if(useUpdate && isUpdatable(workspace, listener)) { - result = update(launcher,workspace,listener); - if(!result) + if(!update(launcher,workspace,listener)) return false; } else { - final ISVNAuthenticationProvider authProvider = getDescriptor().createAuthenticationProvider(); - result = workspace.act(new FileCallable() { - public Boolean invoke(File ws, VirtualChannel channel) throws IOException { - Util.deleteContentsRecursive(ws); - SVNUpdateClient svnuc = createSvnClientManager(authProvider).getUpdateClient(); - svnuc.setEventHandler(new SubversionUpdateEventHandler(listener)); - - StringTokenizer tokens = new StringTokenizer(modules); - while(tokens.hasMoreTokens()) { - try { - SVNURL url = SVNURL.parseURIEncoded(tokens.nextToken()); - listener.getLogger().println("Checking out "+url); - - svnuc.doCheckout(url, new File(ws, getLastPathComponent(url.getPath())), SVNRevision.HEAD, SVNRevision.HEAD, true ); - } catch (SVNException e) { - e.printStackTrace(listener.error("Error in subversion")); - return false; - } - } - - return true; - } - }); - if(!result) + if(!checkout(launcher,workspace, listener)) return false; } @@ -265,6 +238,34 @@ public class SubversionSCM extends AbstractCVSFamilySCM implements Serializable return calcChangeLog(build, changelogFile, listener); } + public boolean checkout(Launcher launcher, FilePath workspace, final TaskListener listener) throws IOException, InterruptedException { + boolean result; + final ISVNAuthenticationProvider authProvider = getDescriptor().createAuthenticationProvider(); + result = workspace.act(new FileCallable() { + public Boolean invoke(File ws, VirtualChannel channel) throws IOException { + Util.deleteContentsRecursive(ws); + SVNUpdateClient svnuc = createSvnClientManager(authProvider).getUpdateClient(); + svnuc.setEventHandler(new SubversionUpdateEventHandler(listener)); + + StringTokenizer tokens = new StringTokenizer(modules); + while(tokens.hasMoreTokens()) { + try { + SVNURL url = SVNURL.parseURIEncoded(tokens.nextToken()); + listener.getLogger().println("Checking out "+url); + + svnuc.doCheckout(url, new File(ws, getLastPathComponent(url.getPath())), SVNRevision.HEAD, SVNRevision.HEAD, true ); + } catch (SVNException e) { + e.printStackTrace(listener.error("Error in subversion")); + return false; + } + } + + return true; + } + }); + return result; + } + /** * Creates {@link SVNClientManager}. *