提交 94b427f8 编写于 作者: J Jesse Glick

Merge branch 'master' into JenkinsRule-additions

......@@ -29,4 +29,4 @@ indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false~
\ No newline at end of file
trim_trailing_whitespace = false
......@@ -55,7 +55,15 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
<li class=bug>
Jenkins CLI doesn't handle arguments with equal signs
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21160">issue 21160</a>)
<li class=bug>
master/slave communication ping reacts badly if a clock jumps.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21251">issue 21251</a>)
<li class=rfe>
JNLP slaves can now connect to master through HTTP proxy.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-6167">issue 21251</a>)
</ul>
</div><!--=TRUNK-END=-->
<h3><a name=v1.605>What's new in 1.605</a> (2015/03/16)</h3>
......
......@@ -190,7 +190,7 @@ THE SOFTWARE.
<dependency><!-- JENKINS-21160: remoting also depends on args4j, please update accordingly -->
<groupId>args4j</groupId>
<artifactId>args4j</artifactId>
<version>2.0.23</version>
<version>2.0.31</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
......
......@@ -131,7 +131,7 @@ public class Util {
public static String replaceMacro( @CheckForNull String s, @Nonnull Map<String,String> properties) {
return replaceMacro(s,new VariableResolver.ByMap<String>(properties));
}
/**
* Replaces the occurrence of '$key' by <tt>resolver.get('key')</tt>.
*
......@@ -143,7 +143,7 @@ public class Util {
if (s == null) {
return null;
}
int idx=0;
while(true) {
Matcher m = VARIABLE.matcher(s);
......@@ -370,6 +370,30 @@ public class Util {
}
}
/**
* A mostly accurate check of whether a path is a relative path or not. This is designed to take a path against
* an unknown operating system so may give invalid results.
*
* @param path the path.
* @return {@code true} if the path looks relative.
* @since 1.606
*/
public 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;
}
/**
* Creates a new temporary directory.
*/
......@@ -624,7 +648,7 @@ public class Util {
* Converts a string into 128-bit AES key.
* @since 1.308
*/
@Nonnull
@Nonnull
public static SecretKey toAes128Key(@Nonnull String s) {
try {
// turn secretKey into 256 bit hash
......@@ -743,9 +767,9 @@ public class Util {
/**
* Combines number and unit, with a plural suffix if needed.
*
* @deprecated
* Use individual localization methods instead.
*
* @deprecated
* Use individual localization methods instead.
* See {@link Messages#Util_year(Object)} for an example.
* Deprecated since 2009-06-24, remove method after 2009-12-24.
*/
......@@ -780,7 +804,7 @@ public class Util {
* {@link #rawEncode(String)} should generally be used instead, though be careful to pass only
* a single path component to that method (it will encode /, but this method does not).
*/
@Nonnull
@Nonnull
public static String encode(@Nonnull String s) {
try {
boolean escaped = false;
......@@ -888,7 +912,7 @@ public class Util {
/**
* Escapes HTML unsafe characters like &lt;, &amp; to the respective character entities.
*/
@Nonnull
@Nonnull
public static String escape(@Nonnull String text) {
if (text==null) return null;
StringBuilder buf = new StringBuilder(text.length()+64);
......@@ -1112,7 +1136,7 @@ public class Util {
* @param symlinkPath
* Where to create a symlink in (relative to {@code baseDir})
*/
public static void createSymlink(@Nonnull File baseDir, @Nonnull String targetPath,
public static void createSymlink(@Nonnull File baseDir, @Nonnull String targetPath,
@Nonnull String symlinkPath, @Nonnull TaskListener listener) throws InterruptedException {
try {
if (createSymlinkJava7(baseDir, targetPath, symlinkPath)) {
......@@ -1346,7 +1370,7 @@ public class Util {
* @deprecated since 2008-05-13. This method is broken (see ISSUE#1666). It should probably
* be removed but I'm not sure if it is considered part of the public API
* that needs to be maintained for backwards compatibility.
* Use {@link #encode(String)} instead.
* Use {@link #encode(String)} instead.
*/
@Deprecated
public static String encodeRFC2396(String url) {
......@@ -1367,7 +1391,7 @@ public class Util {
s = "<span class=error style='display:inline-block'>"+s+"</span>";
return s;
}
/**
* Returns the parsed string if parsed successful; otherwise returns the default number.
* If the string is null, empty or a ParseException is thrown then the defaultNumber
......
......@@ -30,10 +30,12 @@ import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.FieldSetter;
import org.kohsuke.args4j.spi.Setter;
import org.kohsuke.args4j.spi.OptionHandler;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
......@@ -79,6 +81,16 @@ class MethodBinder {
public boolean isMultiValued() {
return false;
}
@Override
public FieldSetter asFieldSetter() {
return null;
}
@Override
public AnnotatedElement asAnnotatedElement() {
return p;
}
};
Option option = p.annotation(Option.class);
if (option!=null) {
......@@ -148,5 +160,10 @@ class MethodBinder {
public Class<? extends Annotation> annotationType() {
return base.annotationType();
}
@Override
public boolean hidden() {
return base.hidden();
}
}
}
/*
* The MIT License
*
*
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Erik Ramfelt, Martin Eigenbrodt, Stephen Connolly, Tom Huybrechts
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -63,6 +63,7 @@ import jenkins.security.MasterToSlaveCallable;
import jenkins.slaves.WorkspaceLocator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
......@@ -92,8 +93,12 @@ public abstract class Slave extends Node implements Serializable {
private final String description;
/**
* Absolute path to the root of the workspace
* from the view point of this node, such as "/hudson"
* Path to the root of the workspace from the view point of this node, such as "/hudson", this need not
* be absolute provided that the launcher establishes a consistent working directory, such as "./.jenkins-slave"
* when used with an SSH launcher.
*
* NOTE: if the administrator is using a relative path they are responsible for ensuring that the launcher used
* provides a consistent working directory
*/
protected final String remoteFS;
......@@ -121,14 +126,14 @@ public abstract class Slave extends Node implements Serializable {
* Whitespace-separated labels.
*/
private String label="";
private /*almost final*/ DescribableList<NodeProperty<?>,NodePropertyDescriptor> nodeProperties = new DescribableList<NodeProperty<?>,NodePropertyDescriptor>(Jenkins.getInstance());
/**
* Lazily computed set of labels from {@link #label}.
*/
private transient volatile Set<Label> labels;
/**
* Id of user which creates this slave {@link User}.
*/
......@@ -147,7 +152,7 @@ public abstract class Slave extends Node implements Serializable {
Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy) throws FormException, IOException {
this(name, nodeDescription, remoteFS, numExecutors, mode, labelString, launcher, retentionStrategy, new ArrayList());
}
public Slave(@Nonnull String name, String nodeDescription, String remoteFS, int numExecutors,
Mode mode, String labelString, ComputerLauncher launcher, RetentionStrategy retentionStrategy, List<? extends NodeProperty<?>> nodeProperties) throws FormException, IOException {
this.name = name;
......@@ -159,7 +164,7 @@ public abstract class Slave extends Node implements Serializable {
this.launcher = launcher;
this.retentionStrategy = retentionStrategy;
getAssignedLabels(); // compute labels now
this.nodeProperties.replaceBy(nodeProperties);
Slave node = (Slave) Jenkins.getInstance().getNode(name);
......@@ -168,7 +173,7 @@ public abstract class Slave extends Node implements Serializable {
}
else{
User user = User.current();
userId = user!=null ? user.getId() : "anonymous";
userId = user!=null ? user.getId() : "anonymous";
}
if (name.equals(""))
throw new FormException(Messages.Slave_InvalidConfig_NoName(), null);
......@@ -179,10 +184,10 @@ public abstract class Slave extends Node implements Serializable {
if (this.numExecutors<=0)
throw new FormException(Messages.Slave_InvalidConfig_Executors(name), null);
}
/**
* Return id of user which created this slave
*
*
* @return id of user
*/
public String getUserId() {
......@@ -192,7 +197,7 @@ public abstract class Slave extends Node implements Serializable {
public void setUserId(String userId){
this.userId = userId;
}
public ComputerLauncher getLauncher() {
return launcher == null ? new JNLPLauncher() : launcher;
}
......@@ -214,7 +219,7 @@ public abstract class Slave extends Node implements Serializable {
}
public void setNodeName(String name) {
this.name = name;
this.name = name;
}
public String getNodeDescription() {
......@@ -237,7 +242,7 @@ public abstract class Slave extends Node implements Serializable {
assert nodeProperties != null;
return nodeProperties;
}
public RetentionStrategy getRetentionStrategy() {
return retentionStrategy == null ? RetentionStrategy.Always.INSTANCE : retentionStrategy;
}
......@@ -273,14 +278,21 @@ public abstract class Slave extends Node implements Serializable {
return workspace;
}
}
FilePath r = getWorkspaceRoot();
if(r==null) return null; // offline
return r.child(item.getFullName());
}
@CheckForNull
public FilePath getRootPath() {
return createPath(remoteFS);
final SlaveComputer computer = getComputer();
if (computer == null) {
// if computer is null then channel is null and thus we were going to return null anyway
return null;
} else {
return createPath(StringUtils.defaultString(computer.getAbsoluteRemoteFs(), remoteFS));
}
}
/**
......@@ -422,10 +434,8 @@ public abstract class Slave extends Node implements Serializable {
if(value.startsWith("\\\\") || value.startsWith("/net/"))
return FormValidation.warning(Messages.Slave_Network_Mounted_File_System_Warning());
if (!value.contains("\\") && !value.startsWith("/")) {
// Unix-looking path that doesn't start with '/'
// TODO: detect Windows-looking relative path
return FormValidation.error(Messages.Slave_the_remote_root_must_be_an_absolute_path());
if (Util.isRelativePath(value)) {
return FormValidation.warning(Messages.Slave_Remote_Relative_Path_Warning());
}
return FormValidation.ok();
......
/*
* The MIT License
*
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -41,6 +41,7 @@ import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
......@@ -57,7 +58,7 @@ public class CommandLauncher extends ComputerLauncher {
* "ssh myslave java -jar /path/to/hudson-remoting.jar"
*/
private final String agentCommand;
/**
* Optional environment variables to add to the current environment. Can be null.
*/
......@@ -67,7 +68,7 @@ public class CommandLauncher extends ComputerLauncher {
public CommandLauncher(String command) {
this(command, null);
}
public CommandLauncher(String command, EnvVars env) {
this.agentCommand = command;
this.env = env;
......@@ -90,10 +91,10 @@ public class CommandLauncher extends ComputerLauncher {
Process _proc = null;
try {
Slave node = computer.getNode();
if (node == null) {
if (node == null) {
throw new AbortException("Cannot launch commands on deleted nodes");
}
listener.getLogger().println(hudson.model.Messages.Slave_Launching(getTimestamp()));
if(getCommand().trim().length()==0) {
listener.getLogger().println(Messages.CommandLauncher_NoLaunchCommand());
......@@ -103,8 +104,8 @@ public class CommandLauncher extends ComputerLauncher {
ProcessBuilder pb = new ProcessBuilder(Util.tokenize(getCommand()));
final EnvVars cookie = _cookie = EnvVars.createCookie();
pb.environment().putAll(cookie);
pb.environment().put("WORKSPACE", node.getRemoteFS()); //path for local slave log
pb.environment().putAll(cookie);
pb.environment().put("WORKSPACE", StringUtils.defaultString(computer.getAbsoluteRemoteFs(), node.getRemoteFS())); //path for local slave log
{// system defined variables
String rootUrl = Jenkins.getInstance().getRootUrl();
......@@ -118,7 +119,7 @@ public class CommandLauncher extends ComputerLauncher {
if (env != null) {
pb.environment().putAll(env);
}
final Process proc = _proc = pb.start();
// capture error information from stderr. this will terminate itself
......
/*
* The MIT License
*
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -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;
......@@ -102,7 +103,7 @@ public class SlaveComputer extends Computer {
*
* <p>
* This is normally the same as {@link Slave#getLauncher()} but
* can be different. See {@link #grabLauncher(Node)}.
* can be different. See {@link #grabLauncher(Node)}.
*/
private ComputerLauncher launcher;
......@@ -132,6 +133,8 @@ public class SlaveComputer extends Computer {
private Object constructed = new Object();
private transient volatile String absoluteRemoteFs;
public SlaveComputer(Slave slave) {
super(slave);
this.log = new ReopenableRotatingFileOutputStream(getLogFile(),10);
......@@ -249,6 +252,9 @@ public class SlaveComputer extends Computer {
} catch (InterruptedException e) {
e.printStackTrace(taskListener.error(Messages.ComputerLauncher_abortedLaunch()));
throw e;
} catch (Exception e) {
e.printStackTrace(taskListener.error(Messages.ComputerLauncher_unexpectedError()));
throw e;
}
} finally {
if (channel==null) {
......@@ -274,7 +280,7 @@ public class SlaveComputer extends Computer {
if (launcher instanceof ExecutorListener) {
((ExecutorListener)launcher).taskAccepted(executor, task);
}
//getNode() can return null at indeterminate times when nodes go offline
Slave node = getNode();
if (node != null && node.getRetentionStrategy() instanceof ExecutorListener) {
......@@ -410,6 +416,19 @@ 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.606
*/
@CheckForNull
public String getAbsoluteRemoteFs() {
return channel == null ? null : absoluteRemoteFs;
}
static class LoadingCount extends MasterToSlaveCallable<Integer,RuntimeException> {
private final boolean resource;
LoadingCount(boolean resource) {
......@@ -481,11 +500,16 @@ public class SlaveComputer extends Computer {
if (node == null) { // Node has been disabled/removed during the connection
throw new IOException("Node "+nodeName+" has been deleted during the channel setup");
}
String remoteFs = node.getRemoteFS();
if(_isUnix && !remoteFs.contains("/") && remoteFs.contains("\\"))
log.println("WARNING: "+remoteFs+" looks suspiciously like Windows path. Maybe you meant "+remoteFs.replace('\\','/')+"?");
FilePath root = new FilePath(channel,remoteFs);
String remoteFS = node.getRemoteFS();
if (Util.isRelativePath(remoteFS)) {
remoteFS = channel.call(new AbsolutePath(remoteFS));
log.println("NOTE: Relative remote path resolved to: "+remoteFS);
}
if(_isUnix && !remoteFS.contains("/") && remoteFS.contains("\\"))
log.println("WARNING: "+remoteFS
+" looks suspiciously like Windows path. Maybe you meant "+remoteFS.replace('\\','/')+"?");
FilePath root = new FilePath(channel,remoteFS);
// reference counting problem is known to happen, such as JENKINS-9017, and so as a preventive measure
// we pin the base classloader so that it'll never get GCed. When this classloader gets released,
......@@ -519,6 +543,7 @@ public class SlaveComputer extends Computer {
isUnix = _isUnix;
numRetryAttempt = 0;
this.channel = channel;
this.absoluteRemoteFs = remoteFS;
defaultCharset = Charset.forName(defaultCharsetName);
synchronized (statusChangeLock) {
......@@ -634,9 +659,13 @@ public class SlaveComputer extends Computer {
*/
private void closeChannel() {
// TODO: race condition between this and the setChannel method.
Channel c = channel;
channel = null;
isUnix = null;
Channel c;
synchronized (channelLock) {
c = channel;
channel = null;
absoluteRemoteFs = null;
isUnix = null;
}
if (c != null) {
try {
c.close();
......@@ -708,6 +737,21 @@ public class SlaveComputer extends Computer {
}
}
private static final class AbsolutePath extends MasterToSlaveCallable<String,IOException> {
private static final long serialVersionUID = 1L;
private final String relativePath;
private AbsolutePath(String relativePath) {
this.relativePath = relativePath;
}
public String call() throws IOException {
return new File(relativePath).getAbsolutePath();
}
}
private static final class DetectDefaultCharset extends MasterToSlaveCallable<String,IOException> {
public String call() throws IOException {
return Charset.defaultCharset().name();
......@@ -744,7 +788,7 @@ public class SlaveComputer extends Computer {
}
Channel.current().setProperty("slave",Boolean.TRUE); // indicate that this side of the channel is the slave side.
return null;
}
private static final long serialVersionUID = 1L;
......
......@@ -28,6 +28,7 @@ import org.kohsuke.stapler.ClassDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
......@@ -122,7 +123,7 @@ public class ReflectionUtils extends org.springframework.util.ReflectionUtils {
}
}
public static final class Parameter {
public static final class Parameter implements AnnotatedElement {
private final MethodInfo parent;
private final int index;
......@@ -180,6 +181,26 @@ public class ReflectionUtils extends org.springframework.util.ReflectionUtils {
return names[index];
return null;
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> type) {
return annotation(type)!=null;
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> type) {
return annotation(type);
}
@Override
public Annotation[] getAnnotations() {
return annotations();
}
@Override
public Annotation[] getDeclaredAnnotations() {
return annotations();
}
}
/**
......
# The MIT License
#
# Copyright (c) 2004-2012, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -25,7 +25,6 @@ Submit=\u4fdd\u5b58
Upload\ Plugin=\u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9
Upload=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9
File=\u30d5\u30a1\u30a4\u30eb
lastUpdated=\u30c7\u30fc\u30bf\u66f4\u65b0\u6642\u523b: {0}
uploadtext=\
.hpi\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u3066\u3001\u30d7\u30e9\u30b0\u30a4\u30f3\u30ea\u30dd\u30b8\u30c8\u30ea\u4ee5\u5916\u304b\u3089\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u304d\u307e\u3059\u3002
Update\ Site=\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u30b5\u30a4\u30c8
......
......@@ -25,9 +25,9 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<j:invokeStatic var="ds" className="jenkins.model.DownloadSettings" method="get"/>
<form method="post" action="${ds.useBrowser ? 'checkUpdates' : 'checkUpdatesServer'}">
${%lastUpdated(app.updateCenter.lastUpdatedString)}
<f:submit value="${%Check now}" />
</form>
${%lastUpdated(app.updateCenter.lastUpdatedString)}
<f:link href="${ds.useBrowser ? 'checkUpdates' : 'checkUpdatesServer'}" post="true" clazz="yui-button yui-submit-button submit-button primary">
<button>${%Check now}</button>
</f:link>
</j:jelly>
# The MIT License
#
# Copyright (c) 2004-2012, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -21,3 +21,4 @@
# THE SOFTWARE.
Check\ now=\u66f4\u65b0
lastUpdated=\u30c7\u30fc\u30bf\u66f4\u65b0\u6642\u523b: {0}
......@@ -25,4 +25,5 @@ MemoryUsageMonitor.TOTAL=\u5408\u8a08
OldDataMonitor.DisplayName=\u65e7\u30c7\u30fc\u30bf\u306e\u7ba1\u7406
OldDataMonitor.Description=\
\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u6574\u7406\u3057\u3066\u3001\u53e4\u3044\u30d7\u30e9\u30b0\u30a4\u30f3\u3084\u524d\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u4e0d\u8981\u306a\u60c5\u5831\u3092\u53d6\u308a\u9664\u304d\u307e\u3059\u3002
HudsonHomeDiskUsageMonitor.DisplayName=\u30c7\u30a3\u30b9\u30af\u4f7f\u7528\u91cf\u30e2\u30cb\u30bf
# The MIT License
#
# Copyright (c) 2011, Seiji Sogabe
# Copyright (c) 2011-2015, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -23,4 +23,4 @@
blurb=\
\u6b21\u306e\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u3001ID\u3092\u6301\u3063\u3066\u3044\u306a\u3044\u306e\u3067\u554f\u984c\u3092\u8d77\u3053\u3059\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\u30d7\u30e9\u30b0\u30a4\u30f3\u3092\u6700\u65b0\u306e\u7269\u306b\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u3057\u3066\u304f\u3060\u3055\u3044\u3002\
\u6700\u65b0\u306e\u7269\u3067\u3042\u308c\u3070\u3001\u4fee\u6b63\u3067\u304d\u308b\u3088\u3046\u306bJIRA\u306b\u30d0\u30b0\u3068\u3057\u3066\u767b\u9332\u3057\u3066\u304f\u3060\u3055\u3044\u3002
problem=Descriptor {0} from plugin {2} with display name {1}
\ No newline at end of file
problem=\u30d7\u30e9\u30b0\u30a4\u30f3 {2} \u306e\u30c7\u30a3\u30b9\u30af\u30ea\u30d7\u30bf {0} (\u8868\u793a\u540d {1})
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Welcome\ to\ Jenkins!=Jenkins\u3078\u3088\u3046\u3053\u305D\uFF01
newJob=\u958B\u59CB\u3059\u308B\u305F\u3081\u306B<a href="newJob">\u65B0\u3057\u3044\u30B8\u30E7\u30D6</a>\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002
login=\u65B0\u3057\u3044\u30B8\u30E7\u30D6\u3092\u4F5C\u6210\u3059\u308B\u306B\u306F\u3001<a href="{0}/{1}?from={2}">\u30ED\u30B0\u30A4\u30F3</a>\u3057\u3066\u304F\u3060\u3055\u3044\u3002
signup=\u3082\u3057\u3042\u306A\u305F\u304C\u30A2\u30AB\u30A6\u30F3\u30C8\u3092\u6301\u3063\u3066\u3044\u306A\u3051\u308C\u3070\u3001\u4ECA<a href="signup">\u53C2\u52A0</a>\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002
Welcome\ to\ Jenkins!=Jenkins\u3078\u3088\u3046\u3053\u305d\uff01
newJob=<a href="newJob">\u65b0\u3057\u3044\u30b8\u30e7\u30d6</a>\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044\u3002
login=\u65b0\u3057\u3044\u30b8\u30e7\u30d6\u3092\u4f5c\u6210\u3059\u308b\u306b\u306f\u3001<a href="{0}/{1}?from={2}">\u30ed\u30b0\u30a4\u30f3</a>\u3057\u3066\u304f\u3060\u3055\u3044\u3002
signup=\u3082\u3057\u3042\u306a\u305f\u304c\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6301\u3063\u3066\u3044\u306a\u3051\u308c\u3070\u3001\u4eca<a href="signup">\u53c2\u52a0</a>\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -23,7 +23,7 @@
submit.temporarilyOffline=\u3053\u306e\u30ce\u30fc\u30c9\u3092\u30aa\u30f3\u30e9\u30a4\u30f3\u306b\u623b\u3059
submit.not.temporarilyOffline=\u3053\u306e\u30ce\u30fc\u30c9\u3092\u4e00\u6642\u7684\u306b\u30aa\u30d5\u30e9\u30a4\u30f3\u306b\u3059\u308b
None=\u306a\u3057
Labels\:=\u30e9\u30d9\u30eb:
Labels\=\u30e9\u30d9\u30eb
title.projects_tied_on={0}\u3067\u306e\u307f\u8d77\u52d5\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
title.no_manual_launch=\u3053\u306e\u30ce\u30fc\u30c9\u306e\u53ef\u7528\u6027\u306e\u30dd\u30ea\u30b7\u30fc\u306f''{0}''\u3067\u3059\u3002\u73fe\u5728\u3001\u305d\u306e\u30dd\u30ea\u30b7\u30fc\u306b\u57fa\u3065\u3044\u3066\u3001\u3053\u306e\u30ce\u30fc\u30c9\u306f\u30aa\u30d5\u30e9\u30a4\u30f3\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002
Created\ by=\u30ce\u30fc\u30c9\u4f5c\u6210\u8005
......
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -20,10 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
title={0}\u306E\u30D3\u30EB\u30C9\u6642\u9593\u306E\u50BE\u5411
Timeline=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3
Build=\u30D3\u30EB\u30C9
Build\ Time\ Trend=\u30D3\u30EB\u30C9\u6642\u9593\u306E\u63A8\u79FB
title={0}\u306e\u30d3\u30eb\u30c9\u6642\u9593\u306e\u50be\u5411
Timeline=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3
Build=\u30d3\u30eb\u30c9
Build\ Time\ Trend=\u30d3\u30eb\u30c9\u6642\u9593\u306e\u63a8\u79fb
Duration=\u6240\u8981\u6642\u9593
Slave=\u30B9\u30EC\u30FC\u30D6
More\ than\ 1\ builds\ are\ needed\ for\ the\ trend\ report.=\u30B0\u30E9\u30D5\u3092\u63CF\u753B\u3059\u308B\u305F\u3081\u306B\u306F\u6700\u4F4E\uFF12\u3064\u306E\u30D3\u30EB\u30C9\u304C\u5FC5\u8981\u3067\u3059\u3002
Slave=\u30b9\u30ec\u30fc\u30d6
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Back\ to\ Dashboard=\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u3078\u623B\u308B
Back\ to\ Dashboard=\u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u3078\u623b\u308b
Overview=\u6982\u8981
Load\ Statistics=\u8CA0\u8377\u7D71\u8A08
Load\ Statistics=\u8ca0\u8377\u7d71\u8a08
Configure=\u8a2d\u5b9a
\ No newline at end of file
......@@ -244,7 +244,9 @@ Slave.Launching={0} Launching slave agent
Slave.Network.Mounted.File.System.Warning=Are you sure you want to use network mounted file system for FS root? Note that this directory does not need to be visible to the master.
Slave.Remote.Director.Mandatory=Remote directory is mandatory
Slave.Terminated={0} slave agent was terminated
Slave.the_remote_root_must_be_an_absolute_path=The remote root must be an absolute path.
Slave.Remote.Relative.Path.Warning=Are you sure you want to use a relative path for the FS root? Note that relative \
paths require that you can assure that the selected launcher provides a consistent current working directory. Using \
an absolute path is highly recommended.
Slave.UnableToLaunch=Unable to launch the slave agent for {0}{1}
Slave.UnixSlave=This is a Unix slave
Slave.WindowsSlave=This is a Windows slave
......
<div>
<p>
A slave needs to have a directory dedicated to Jenkins. Specify
the absolute path of this work directory on the slave, such as
'/var/jenkins' or 'c:\jenkins'. This should be a path local to the slave
machine. There's no need for this path to be visible from the master,
under normal circumstances.
the path of this work directory on the slave. It is best to use
an absolute path, such as '/var/jenkins' or 'c:\jenkins'. This
should be a path local to the slave machine. There's no need for
this path to be visible from the master, under normal circumstances.
<p>
Slaves do not maintain important data (other than active workspaces
of projects last built on it), so you can possibly set the slave
workspace to a temporary directory. The only downside of doing this
is that you may lose the up-to-date workspace if the slave is turned off.
<p>
If you use a relative path, such as './jenkins-slave', the path will
be relative to the current working directory that the launcher provides.
<ul>
<li>For launchers where Jenkins controls starting the slave process, such
as SSH, the current working directory will typically be consistent,
<i>e.g.</i> the user's home directory. This means that Jenkins will be able to
rely on the caching of tool installations and workspaces from previous
builds.
</li>
<li>For launchers where Jenkins has no control over starting the slave
process, such as JNLP when launched from either the command line or via
a web browser link, the current working directory may change between
launches of the slave and use of a relative path may prove problematic.
The principal issue encountered when using relative paths with launchers
like JNLP is the proliferation of stale workspaces and tool installation
on the slave machine. This can cause disk space issues.
<i>Note: there are some cloud providers that specifically use relative
paths with the JNLP launcher to allow for dynamically provisioned pools
of semi-heterogeneous slaves.</i></li>
</ul>
</div>
# The MIT License
#
# Copyright (c) 2011, Seiji Sogabe
# Copyright (c) 2011-2015, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -23,3 +23,4 @@
Name=\u540d\u524d
Save=\u4fdd\u5b58
title={0} \u306e\u8a2d\u5b9a
Description=\u8aac\u660e
\ No newline at end of file
<div>
Behaves exactly the same as Jenkins &lt;1.164. Namely, if you have the "admin" role,
you'll be granted full control over the system, and otherwise (including anonyomus
you'll be granted full control over the system, and otherwise (including anonymous
users) you'll only have the read access.
</div>
\ No newline at end of file
</div>
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi
#
#
# Copyright (c) 2015, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -20,6 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Build\ after\ other\ projects\ are\ built=\u4ed6\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30d3\u30eb\u30c9\u5f8c\u306b\u30d3\u30eb\u30c9
Project\ names=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u540d
Multiple\ projects\ can\ be\ specified\ like\ 'abc,\ def'=\u8907\u6570\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u6307\u5b9a\u3059\u308b\u306b\u306fabc, def\u306e\u3088\u3046\u306b\u30ab\u30f3\u30de\u3067\u533a\u5207\u308a\u307e\u3059
\ No newline at end of file
Log\ Records=\u30ed\u30b0\u30ec\u30b3\u30fc\u30c9
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
# Copyright (c) 2004-2015, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -24,3 +24,5 @@ Files\ to\ archive=\u4fdd\u5b58\u3059\u308b\u30d5\u30a1\u30a4\u30eb
Excludes=\u9664\u5916\u3059\u308b\u30d5\u30a1\u30a4\u30eb
allowEmptyArchive=\u6210\u679c\u7269\u304c\u4f55\u3082\u306a\u3044\u5834\u5408\u3067\u3082\u30d3\u30eb\u30c9\u3092\u5931\u6557\u306b\u3057\u306a\u3044
Fingerprint\ all\ archived\ artifacts=\u4fdd\u5b58\u3055\u308c\u305f\u6210\u679c\u7269\u306e\u6307\u7d0b\u3092\u8a18\u9332
onlyIfSuccessful=\u30d3\u30eb\u30c9\u304c\u6210\u529f\u3057\u305f\u5834\u5408\u306e\u307f\u4fdd\u5b58
defaultExcludes=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u5bfe\u8c61\u5916\u30d5\u30a1\u30a4\u30eb\u8a2d\u5b9a\u3092\u4f7f\u7528
\ No newline at end of file
......@@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
pending=\u4FDD\u7559
cancel\ this\ build=\u3053\u306E\u30D3\u30EB\u30C9\u3092\u4E2D\u6B62
pending=\u4fdd\u7559
cancel\ this\ build=\u3053\u306e\u30d3\u30eb\u30c9\u3092\u4e2d\u6b62
Expected\ build\ number=\u6b21\u30d3\u30eb\u30c9No
......@@ -21,4 +21,3 @@
# THE SOFTWARE.
expand=\u62e1\u5f35
collapse=\u9589\u3058\u308b
/*
* The MIT License
*
*
* Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Daniel Dyer, Erik Ramfelt, Richard Bair, id:cactusman
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
......@@ -32,7 +32,11 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.*;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Assume;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
......@@ -74,7 +78,7 @@ public class UtilTest {
assertEquals("asd$${AA}dd", Util.replaceMacro("asd$$$${AA}dd",m));
assertEquals("$", Util.replaceMacro("$$",m));
assertEquals("$$", Util.replaceMacro("$$$$",m));
// dots
assertEquals("a.B", Util.replaceMacro("$A.B", m));
assertEquals("a-b", Util.replaceMacro("${A.B}", m));
......@@ -136,7 +140,7 @@ public class UtilTest {
String encoded = Util.encode(urlWithSpaces);
assertEquals(encoded, "http://hudson/job/Hudson%20Job");
}
/**
* Test the rawEncode() method.
*/
......@@ -190,16 +194,16 @@ public class UtilTest {
System.err.println("log output: " + log);
assertEquals(buf.toString(),Util.resolveSymlink(new File(d,"x")));
// test linking from another directory
File anotherDir = new File(d,"anotherDir");
assertTrue("Couldn't create "+anotherDir,anotherDir.mkdir());
Util.createSymlink(d,"a","anotherDir/link",l);
assertEquals("a",Util.resolveSymlink(new File(d,"anotherDir/link")));
// JENKINS-12331: either a bug in createSymlink or this isn't supposed to work:
// JENKINS-12331: either a bug in createSymlink or this isn't supposed to work:
//assertTrue(Util.isSymlink(new File(d,"anotherDir/link")));
File external = File.createTempFile("something", "");
......@@ -213,11 +217,11 @@ public class UtilTest {
Util.deleteRecursive(d);
}
}
@Test
public void testIsSymlink() throws IOException, InterruptedException {
Assume.assumeTrue(!Functions.isWindows());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamTaskListener l = new StreamTaskListener(baos);
File d = tmp.getRoot();
......@@ -225,17 +229,17 @@ public class UtilTest {
new FilePath(new File(d, "original")).touch(0);
assertFalse(Util.isSymlink(new File(d, "original")));
Util.createSymlink(d,"original","link", l);
assertTrue(Util.isSymlink(new File(d, "link")));
// test linking to another directory
File dir = new File(d,"dir");
assertTrue("Couldn't create "+dir,dir.mkdir());
assertFalse(Util.isSymlink(new File(d,"dir")));
File anotherDir = new File(d,"anotherDir");
assertTrue("Couldn't create "+anotherDir,anotherDir.mkdir());
Util.createSymlink(d,"dir","anotherDir/symlinkDir",l);
// JENKINS-12331: either a bug in createSymlink or this isn't supposed to work:
// assertTrue(Util.isSymlink(new File(d,"anotherDir/symlinkDir")));
......@@ -276,7 +280,7 @@ public class UtilTest {
assertEquals("&#039;&quot;", Util.escape("'\""));
assertEquals("&nbsp; ", Util.escape(" "));
}
/**
* Compute 'known-correct' digests and see if I still get them when computed concurrently
* to another digest.
......@@ -286,19 +290,19 @@ public class UtilTest {
public void testDigestThreadSafety() throws InterruptedException {
String a = "abcdefgh";
String b = "123456789";
String digestA = Util.getDigestOf(a);
String digestB = Util.getDigestOf(b);
DigesterThread t1 = new DigesterThread(a, digestA);
DigesterThread t2 = new DigesterThread(b, digestB);
t1.start();
t2.start();
t1.join();
t2.join();
if (t1.error != null) {
fail(t1.error);
}
......@@ -306,18 +310,18 @@ public class UtilTest {
fail(t2.error);
}
}
private static class DigesterThread extends Thread {
private String string;
private String expectedDigest;
private String error;
public DigesterThread(String string, String expectedDigest) {
this.string = string;
this.expectedDigest = expectedDigest;
}
public void run() {
for (int i=0; i < 1000; i++) {
String digest = Util.getDigestOf(this.string);
......@@ -349,4 +353,56 @@ public class UtilTest {
assertEquals(p.toString(), "va.l.ue", p.get("k.e.y"));
assertEquals(p.toString(), 1, p.size());
}
@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 Util.isRelativePath((String) item);
}
@Override
public void describeTo(Description description) {
description.appendText("a relative path");
}
}
}
......@@ -176,7 +176,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>remoting</artifactId>
<version>2.49</version>
<version>2.50</version>
</dependency>
<dependency>
......
......@@ -96,7 +96,7 @@ class SlaveTest {
def d = j.jenkins.getDescriptorByType(DumbSlave.DescriptorImpl.class)
assert d.doCheckRemoteFS("c:\\")==FormValidation.ok();
assert d.doCheckRemoteFS("/tmp")==FormValidation.ok();
assert d.doCheckRemoteFS("relative/path").kind==ERROR;
assert d.doCheckRemoteFS("relative/path").kind==WARNING;
assert d.doCheckRemoteFS("/net/foo/bar/zot").kind==WARNING;
assert d.doCheckRemoteFS("\\\\machine\\folder\\foo").kind==WARNING;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册