diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index 4bbb0171fdb3a909cb0e0a1b7dd9a3aa5b543a09..e42035bd4f45dce00abd31e623ae64287c6c875b 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -111,6 +111,7 @@ import java.util.regex.Pattern; import static hudson.FilePath.TarCompression.*; import static hudson.Util.*; +import javax.annotation.Nonnull; /** * {@link File} like object with remoting support. @@ -1161,7 +1162,7 @@ public final class FilePath implements Serializable { * @param relOrAbsolute a relative or absolute path * @return a file on the same channel */ - public FilePath child(String relOrAbsolute) { + public @Nonnull FilePath child(String relOrAbsolute) { return new FilePath(this,relOrAbsolute); } diff --git a/core/src/main/java/hudson/model/AbstractBuild.java b/core/src/main/java/hudson/model/AbstractBuild.java index d1e291d52eeb494298c9bca2dddca19c7425aa96..28ef3ff5e83c985d5da9b9b8a2018d298589871d 100644 --- a/core/src/main/java/hudson/model/AbstractBuild.java +++ b/core/src/main/java/hudson/model/AbstractBuild.java @@ -292,7 +292,7 @@ public abstract class AbstractBuild

,R extends Abs * Normally, a workspace is assigned by {@link hudson.model.Run.RunExecution}, but this lets you set the workspace in case * {@link AbstractBuild} is created without a build. */ - protected void setWorkspace(FilePath ws) { + protected void setWorkspace(@Nonnull FilePath ws) { this.workspace = ws.getRemote(); } diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 6e36007578c0de655d69a83dd17fe11cd9555bf8..947c5179f782d9aed64470267b9ef202d8494047 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -1432,7 +1432,7 @@ public abstract class AbstractProject

,R extends A } } - private PollingResult pollWithWorkspace(TaskListener listener, SCM scm, R lb, FilePath ws, WorkspaceList l) throws InterruptedException, IOException { + private PollingResult pollWithWorkspace(TaskListener listener, SCM scm, R lb, @Nonnull FilePath ws, WorkspaceList l) throws InterruptedException, IOException { // if doing non-concurrent build, acquire a workspace in a way that causes builds to block for this workspace. // this prevents multiple workspaces of the same job --- the behavior of Hudson < 1.319. // diff --git a/core/src/main/java/hudson/slaves/WorkspaceList.java b/core/src/main/java/hudson/slaves/WorkspaceList.java index b6dd917da314deb180d7f025cb54a9cbf0c70d3a..5e335f23e26c1f60c808126ecc404f8ac4e381fa 100644 --- a/core/src/main/java/hudson/slaves/WorkspaceList.java +++ b/core/src/main/java/hudson/slaves/WorkspaceList.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nonnull; /** * Used by {@link Computer} to keep track of workspaces that are actively in use. @@ -72,7 +73,7 @@ public final class WorkspaceList { */ public final boolean quick; - public final FilePath path; + public final @Nonnull FilePath path; /** * Multiple threads can acquire the same lock if they share the same context object. @@ -81,11 +82,11 @@ public final class WorkspaceList { public int lockCount=1; - private Entry(FilePath path, boolean quick) { + private Entry(@Nonnull FilePath path, boolean quick) { this(path,quick,new Object()); // unique context } - private Entry(FilePath path, boolean quick, Object context) { + private Entry(@Nonnull FilePath path, boolean quick, Object context) { this.path = path; this.quick = quick; this.context = context; @@ -104,9 +105,10 @@ public final class WorkspaceList { * Represents a leased workspace that needs to be returned later. */ public static abstract class Lease { - public final FilePath path; + public final @Nonnull FilePath path; - protected Lease(FilePath path) { + protected Lease(@Nonnull FilePath path) { + path.getRemote(); // null check this.path = path; } @@ -118,7 +120,7 @@ public final class WorkspaceList { /** * Creates a dummy {@link Lease} object that does no-op in the release. */ - public static Lease createDummyLease(FilePath p) { + public static Lease createDummyLease(@Nonnull FilePath p) { return new Lease(p) { public void release() { // noop @@ -130,7 +132,7 @@ public final class WorkspaceList { * Creates a {@link Lease} object that points to the specified path, but the lock * is controlled by the given parent lease object. */ - public static Lease createLinkedDummyLease(FilePath p, final Lease parent) { + public static Lease createLinkedDummyLease(@Nonnull FilePath p, final Lease parent) { return new Lease(p) { public void release() { parent.release(); @@ -151,7 +153,7 @@ public final class WorkspaceList { * This method doesn't block prolonged amount of time. Whenever a desired workspace * is in use, the unique variation is added. */ - public synchronized Lease allocate(FilePath base) throws InterruptedException { + public synchronized Lease allocate(@Nonnull FilePath base) throws InterruptedException { return allocate(base,new Object()); } @@ -162,7 +164,7 @@ public final class WorkspaceList { * Threads that share the same context can re-acquire the same lock (which will just increment the lock count.) * This allows related executors to share the same workspace. */ - public synchronized Lease allocate(FilePath base, Object context) throws InterruptedException { + public synchronized Lease allocate(@Nonnull FilePath base, Object context) throws InterruptedException { for (int i=1; ; i++) { FilePath candidate = i==1 ? base : base.withSuffix(COMBINATOR+i); Entry e = inUse.get(candidate); @@ -175,7 +177,7 @@ public final class WorkspaceList { /** * Just record that this workspace is being used, without paying any attention to the synchronization support. */ - public synchronized Lease record(FilePath p) { + public synchronized Lease record(@Nonnull FilePath p) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "recorded " + p, new Throwable("from " + this)); } @@ -188,7 +190,7 @@ public final class WorkspaceList { /** * Releases an allocated or acquired workspace. */ - private synchronized void _release(FilePath p) { + private synchronized void _release(@Nonnull FilePath p) { Entry old = inUse.get(p); if (old==null) throw new AssertionError("Releasing unallocated workspace "+p); @@ -207,7 +209,7 @@ public final class WorkspaceList { * @return * The same {@link FilePath} as given to this method. */ - public synchronized Lease acquire(FilePath p) throws InterruptedException { + public synchronized Lease acquire(@Nonnull FilePath p) throws InterruptedException { return acquire(p,false); } @@ -218,7 +220,7 @@ public final class WorkspaceList { * If true, indicates that the acquired workspace will be returned quickly. * This makes other calls to {@link #allocate(FilePath)} to wait for the release of this workspace. */ - public synchronized Lease acquire(FilePath p, boolean quick) throws InterruptedException { + public synchronized Lease acquire(@Nonnull FilePath p, boolean quick) throws InterruptedException { return acquire(p,quick,new Object()); } @@ -229,7 +231,7 @@ public final class WorkspaceList { * Threads that share the same context can re-acquire the same lock (which will just increment the lock count.) * This allows related executors to share the same workspace. */ - public synchronized Lease acquire(FilePath p, boolean quick, Object context) throws InterruptedException { + public synchronized Lease acquire(@Nonnull FilePath p, boolean quick, Object context) throws InterruptedException { Entry e; Thread t = Thread.currentThread(); @@ -257,7 +259,7 @@ public final class WorkspaceList { /** * Wraps a path into a valid lease. */ - private Lease lease(FilePath p) { + private Lease lease(@Nonnull FilePath p) { return new Lease(p) { public void release() { _release(path); diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index 235243333ce4d0eef33fbd5759812d4ecbd5b541..5ad6795cca4e17fb82691bc09589783011bc9688 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -419,7 +419,9 @@ public class ProjectTest { FreeStyleProject p = j.createFreeStyleProject("project"); Slave slave = j.createOnlineSlave(); AbstractBuild build = p.createExecutable(); - FilePath path = slave.toComputer().getWorkspaceList().allocate(slave.getWorkspaceFor(p), build).path; + FilePath ws = slave.getWorkspaceFor(p); + assertNotNull(ws); + FilePath path = slave.toComputer().getWorkspaceList().allocate(ws, build).path; build.setWorkspace(path); BuildListener listener = new StreamBuildListener(BuildListener.NULL.getLogger(), Charset.defaultCharset()); assertTrue("Project with null smc should perform checkout without problems.", p.checkout(build, new RemoteLauncher(listener, slave.getChannel(), true), listener, new File(build.getRootDir(),"changelog.xml")));