提交 5de6f84e 编写于 作者: S Stephen Connolly

Handle mostly-absolute paths on windows that use a drive letter

- of course drive mappings are user scoped and can change from user session to user session, so calling them absolute is a bit of a joke... none the less, for our purposes they are absolute enough
上级 644d9a28
......@@ -53,6 +53,7 @@ import jenkins.slaves.EncryptedSlaveAgentJnlpFile;
import jenkins.slaves.systemInfo.SlaveSystemInfo;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.io.FilenameUtils;
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.interceptor.RequirePOST;
......@@ -412,6 +413,14 @@ public class SlaveComputer extends Computer {
return channel.call(new LoadingTime(true));
}
/**
* Returns the remote FS root absolute path or {@code null} if the slave is off-line. The absolute path may change
* between connections if the connection method does not provide a consistent working directory and the node's
* remote FS is specified as a relative path.
*
* @return the remote FS root absolute path or {@code null} if the slave is off-line.
* @since 1.FIXME
*/
@CheckForNull
public String getAbsoluteRemoteFs() {
return channel == null ? null : absoluteRemoteFs;
......@@ -490,7 +499,7 @@ public class SlaveComputer extends Computer {
}
String absoluteRemoteFs = node.getRemoteFS();
if (!absoluteRemoteFs.startsWith("\\") && !absoluteRemoteFs.startsWith("/")) {
if (isRelativePath(absoluteRemoteFs)) {
absoluteRemoteFs = channel.call(new AbsolutePath(absoluteRemoteFs));
log.println("NOTE: Relative remote path resolved to: "+absoluteRemoteFs);
}
......@@ -550,6 +559,22 @@ public class SlaveComputer extends Computer {
Jenkins.getInstance().getQueue().scheduleMaintenance();
}
/*package*/ static boolean isRelativePath(String path) {
if (path.startsWith("/"))
return false;
if (path.startsWith("\\\\") && path.length() > 3 && path.indexOf('\\', 3) != -1)
return false; // a UNC path which is the most absolute you can get on windows
if (path.length() >= 3 && ':' == path.charAt(1)) {
// never mind that the drive mappings can be changed between sessions, we just want to
// know if the 3rd character is a `\` (or a '/' is acceptable too)
char p = path.charAt(0);
if (('A' <= p && p <= 'Z') || ('a' <= p && p <= 'z')) {
return path.charAt(2) != '\\' && path.charAt(2) != '/';
}
}
return true;
}
@Override
public Channel getChannel() {
return channel;
......
package hudson.slaves;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
/**
* @author Stephen Connolly
*/
public class SlaveComputerTest {
@Test
public void isRelativePathUnix() {
assertThat("/", not(aRelativePath()));
assertThat("/foo/bar", not(aRelativePath()));
assertThat("/foo/../bar", not(aRelativePath()));
assertThat("", aRelativePath());
assertThat(".", aRelativePath());
assertThat("..", aRelativePath());
assertThat("./foo", aRelativePath());
assertThat("./foo/bar", aRelativePath());
assertThat("./foo/bar/", aRelativePath());
}
@Test
public void isRelativePathWindows() {
assertThat("\\", aRelativePath());
assertThat("\\foo\\bar", aRelativePath());
assertThat("\\foo\\..\\bar", aRelativePath());
assertThat("", aRelativePath());
assertThat(".", aRelativePath());
assertThat(".\\foo", aRelativePath());
assertThat(".\\foo\\bar", aRelativePath());
assertThat(".\\foo\\bar\\", aRelativePath());
assertThat("\\\\foo", aRelativePath());
assertThat("\\\\foo\\", not(aRelativePath()));
assertThat("\\\\foo\\c", not(aRelativePath()));
assertThat("C:", aRelativePath());
assertThat("z:", aRelativePath());
assertThat("0:", aRelativePath());
assertThat("c:.", aRelativePath());
assertThat("c:\\", not(aRelativePath()));
assertThat("c:/", not(aRelativePath()));
}
private static RelativePathMatcher aRelativePath() {
return new RelativePathMatcher();
}
private static class RelativePathMatcher extends BaseMatcher<String> {
@Override
public boolean matches(Object item) {
return SlaveComputer.isRelativePath((String)item);
}
@Override
public void describeTo(Description description) {
description.appendText("a relative path");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册