Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
6f95e400
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
6f95e400
编写于
12月 01, 2017
作者:
J
Jesse Glick
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into surefire-mixup
上级
7cbc8f55
fdccc0e8
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
259 addition
and
64 deletion
+259
-64
core/src/main/java/hudson/FilePath.java
core/src/main/java/hudson/FilePath.java
+27
-3
core/src/main/java/hudson/Functions.java
core/src/main/java/hudson/Functions.java
+21
-10
core/src/main/java/hudson/Util.java
core/src/main/java/hudson/Util.java
+57
-0
core/src/main/java/hudson/model/AbstractItem.java
core/src/main/java/hudson/model/AbstractItem.java
+2
-19
core/src/main/java/hudson/model/BuildableItem.java
core/src/main/java/hudson/model/BuildableItem.java
+8
-2
core/src/main/java/hudson/model/Item.java
core/src/main/java/hudson/model/Item.java
+32
-5
core/src/main/java/hudson/util/IOUtils.java
core/src/main/java/hudson/util/IOUtils.java
+17
-2
core/src/main/java/jenkins/model/ParameterizedJobMixIn.java
core/src/main/java/jenkins/model/ParameterizedJobMixIn.java
+0
-18
core/src/test/java/hudson/FilePathTest.java
core/src/test/java/hudson/FilePathTest.java
+52
-1
core/src/test/java/hudson/UtilTest.java
core/src/test/java/hudson/UtilTest.java
+39
-0
core/src/test/java/hudson/util/io/TarArchiverTest.java
core/src/test/java/hudson/util/io/TarArchiverTest.java
+4
-4
未找到文件。
core/src/main/java/hudson/FilePath.java
浏览文件 @
6f95e400
...
@@ -79,6 +79,7 @@ import java.net.URL;
...
@@ -79,6 +79,7 @@ import java.net.URL;
import
java.net.URLConnection
;
import
java.net.URLConnection
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
import
java.nio.file.InvalidPathException
;
import
java.nio.file.InvalidPathException
;
import
java.nio.file.StandardCopyOption
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.Comparator
;
...
@@ -1582,6 +1583,11 @@ public final class FilePath implements Serializable {
...
@@ -1582,6 +1583,11 @@ public final class FilePath implements Serializable {
* <p>
* <p>
* please note mask is expected to be an octal if you use <a href="http://en.wikipedia.org/wiki/Chmod">chmod command line values</a>,
* please note mask is expected to be an octal if you use <a href="http://en.wikipedia.org/wiki/Chmod">chmod command line values</a>,
* so preceded by a '0' in java notation, ie <code>chmod(0644)</code>
* so preceded by a '0' in java notation, ie <code>chmod(0644)</code>
* <p>
* Only supports setting read, write, or execute permissions for the
* owner, group, or others, so the largest permissible value is 0777.
* Attempting to set larger values (i.e. the setgid, setuid, or sticky
* bits) will cause an IOException to be thrown.
*
*
* @since 1.303
* @since 1.303
* @see #mode()
* @see #mode()
...
@@ -1591,7 +1597,6 @@ public final class FilePath implements Serializable {
...
@@ -1591,7 +1597,6 @@ public final class FilePath implements Serializable {
act
(
new
SecureFileCallable
<
Void
>()
{
act
(
new
SecureFileCallable
<
Void
>()
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
final
long
serialVersionUID
=
1L
;
public
Void
invoke
(
File
f
,
VirtualChannel
channel
)
throws
IOException
{
public
Void
invoke
(
File
f
,
VirtualChannel
channel
)
throws
IOException
{
// TODO first check for Java 7+ and use PosixFileAttributeView
_chmod
(
writing
(
f
),
mask
);
_chmod
(
writing
(
f
),
mask
);
return
null
;
return
null
;
...
@@ -1600,14 +1605,18 @@ public final class FilePath implements Serializable {
...
@@ -1600,14 +1605,18 @@ public final class FilePath implements Serializable {
}
}
/**
/**
*
Run chmod via jnr-posix
*
Change permissions via NIO.
*/
*/
private
static
void
_chmod
(
File
f
,
int
mask
)
throws
IOException
{
private
static
void
_chmod
(
File
f
,
int
mask
)
throws
IOException
{
// TODO WindowsPosix actually does something here (WindowsLibC._wchmod); should we let it?
// TODO WindowsPosix actually does something here (WindowsLibC._wchmod); should we let it?
// Anyway the existing calls already skip this method if on Windows.
// Anyway the existing calls already skip this method if on Windows.
if
(
File
.
pathSeparatorChar
==
';'
)
return
;
// noop
if
(
File
.
pathSeparatorChar
==
';'
)
return
;
// noop
PosixAPI
.
jnr
().
chmod
(
f
.
getAbsolutePath
(),
mask
);
if
(
Util
.
NATIVE_CHMOD_MODE
)
{
PosixAPI
.
jnr
().
chmod
(
f
.
getAbsolutePath
(),
mask
);
}
else
{
Files
.
setPosixFilePermissions
(
Util
.
fileToPath
(
f
),
Util
.
modeToPermissions
(
mask
));
}
}
}
private
static
boolean
CHMOD_WARNED
=
false
;
private
static
boolean
CHMOD_WARNED
=
false
;
...
@@ -2008,6 +2017,21 @@ public final class FilePath implements Serializable {
...
@@ -2008,6 +2017,21 @@ public final class FilePath implements Serializable {
* @since 1.311
* @since 1.311
*/
*/
public
void
copyToWithPermission
(
FilePath
target
)
throws
IOException
,
InterruptedException
{
public
void
copyToWithPermission
(
FilePath
target
)
throws
IOException
,
InterruptedException
{
// Use NIO copy with StandardCopyOption.COPY_ATTRIBUTES when copying on the same machine.
if
(
this
.
channel
==
target
.
channel
)
{
act
(
new
SecureFileCallable
<
Void
>()
{
public
Void
invoke
(
File
f
,
VirtualChannel
channel
)
throws
IOException
{
File
targetFile
=
new
File
(
target
.
remote
);
File
targetDir
=
targetFile
.
getParentFile
();
filterNonNull
().
mkdirs
(
targetDir
);
Files
.
createDirectories
(
Util
.
fileToPath
(
targetDir
));
Files
.
copy
(
Util
.
fileToPath
(
reading
(
f
)),
Util
.
fileToPath
(
writing
(
targetFile
)),
StandardCopyOption
.
COPY_ATTRIBUTES
,
StandardCopyOption
.
REPLACE_EXISTING
);
return
null
;
}
});
return
;
}
copyTo
(
target
);
copyTo
(
target
);
// copy file permission
// copy file permission
target
.
chmod
(
mode
());
target
.
chmod
(
mode
());
...
...
core/src/main/java/hudson/Functions.java
浏览文件 @
6f95e400
...
@@ -125,6 +125,7 @@ import java.util.logging.Logger;
...
@@ -125,6 +125,7 @@ import java.util.logging.Logger;
import
java.util.logging.SimpleFormatter
;
import
java.util.logging.SimpleFormatter
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
javax.annotation.Nullable
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
...
@@ -1142,13 +1143,17 @@ public class Functions {
...
@@ -1142,13 +1143,17 @@ public class Functions {
* Gets the relative name or display name to the given item from the specified group.
* Gets the relative name or display name to the given item from the specified group.
*
*
* @since 1.515
* @since 1.515
* @param p the Item we want the relative display name
* @param p the Item we want the relative display name.
* @param g the ItemGroup used as point of reference for the item
* If {@code null}, a {@code null} will be returned by the method
* @param g the ItemGroup used as point of reference for the item.
* If the group is not specified, item's path will be used.
* @param useDisplayName if true, returns a display name, otherwise returns a name
* @param useDisplayName if true, returns a display name, otherwise returns a name
* @return
* @return
* String like "foo » bar"
* String like "foo » bar".
* {@code null} if item is null or if one of its parents is not an {@link Item}.
*/
*/
public
static
String
getRelativeNameFrom
(
Item
p
,
ItemGroup
g
,
boolean
useDisplayName
)
{
@Nullable
public
static
String
getRelativeNameFrom
(
@CheckForNull
Item
p
,
@CheckForNull
ItemGroup
g
,
boolean
useDisplayName
)
{
if
(
p
==
null
)
return
null
;
if
(
p
==
null
)
return
null
;
if
(
g
==
null
)
return
useDisplayName
?
p
.
getFullDisplayName
()
:
p
.
getFullName
();
if
(
g
==
null
)
return
useDisplayName
?
p
.
getFullDisplayName
()
:
p
.
getFullName
();
String
separationString
=
useDisplayName
?
" » "
:
"/"
;
String
separationString
=
useDisplayName
?
" » "
:
"/"
;
...
@@ -1182,7 +1187,7 @@ public class Functions {
...
@@ -1182,7 +1187,7 @@ public class Functions {
if
(
gr
instanceof
Item
)
if
(
gr
instanceof
Item
)
i
=
(
Item
)
gr
;
i
=
(
Item
)
gr
;
else
else
// Parent is a group, but not an item
return
null
;
return
null
;
}
}
}
}
...
@@ -1192,11 +1197,14 @@ public class Functions {
...
@@ -1192,11 +1197,14 @@ public class Functions {
*
*
* @since 1.515
* @since 1.515
* @param p the Item we want the relative display name
* @param p the Item we want the relative display name
* If {@code null}, the method will immediately return {@code null}.
* @param g the ItemGroup used as point of reference for the item
* @param g the ItemGroup used as point of reference for the item
* @return
* @return
* String like "foo/bar"
* String like "foo/bar".
* {@code null} if the item is {@code null} or if one of its parents is not an {@link Item}.
*/
*/
public
static
String
getRelativeNameFrom
(
Item
p
,
ItemGroup
g
)
{
@Nullable
public
static
String
getRelativeNameFrom
(
@CheckForNull
Item
p
,
@CheckForNull
ItemGroup
g
)
{
return
getRelativeNameFrom
(
p
,
g
,
false
);
return
getRelativeNameFrom
(
p
,
g
,
false
);
}
}
...
@@ -1205,12 +1213,15 @@ public class Functions {
...
@@ -1205,12 +1213,15 @@ public class Functions {
* Gets the relative display name to the given item from the specified group.
* Gets the relative display name to the given item from the specified group.
*
*
* @since 1.512
* @since 1.512
* @param p the Item we want the relative display name
* @param p the Item we want the relative display name.
* If {@code null}, the method will immediately return {@code null}.
* @param g the ItemGroup used as point of reference for the item
* @param g the ItemGroup used as point of reference for the item
* @return
* @return
* String like "Foo » Bar"
* String like "Foo » Bar".
* {@code null} if the item is {@code null} or if one of its parents is not an {@link Item}.
*/
*/
public
static
String
getRelativeDisplayNameFrom
(
Item
p
,
ItemGroup
g
)
{
@Nullable
public
static
String
getRelativeDisplayNameFrom
(
@CheckForNull
Item
p
,
@CheckForNull
ItemGroup
g
)
{
return
getRelativeNameFrom
(
p
,
g
,
true
);
return
getRelativeNameFrom
(
p
,
g
,
true
);
}
}
...
...
core/src/main/java/hudson/Util.java
浏览文件 @
6f95e400
...
@@ -68,6 +68,7 @@ import java.nio.file.LinkOption;
...
@@ -68,6 +68,7 @@ import java.nio.file.LinkOption;
import
java.nio.file.NoSuchFileException
;
import
java.nio.file.NoSuchFileException
;
import
java.nio.file.Path
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.Paths
;
import
java.nio.file.attribute.PosixFilePermission
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.nio.file.attribute.BasicFileAttributes
;
import
java.nio.file.attribute.DosFileAttributes
;
import
java.nio.file.attribute.DosFileAttributes
;
import
java.security.MessageDigest
;
import
java.security.MessageDigest
;
...
@@ -1597,6 +1598,51 @@ public class Util {
...
@@ -1597,6 +1598,51 @@ public class Util {
}
}
}
}
@Restricted
(
NoExternalUse
.
class
)
public
static
int
permissionsToMode
(
Set
<
PosixFilePermission
>
permissions
)
{
PosixFilePermission
[]
allPermissions
=
PosixFilePermission
.
values
();
int
result
=
0
;
for
(
int
i
=
0
;
i
<
allPermissions
.
length
;
i
++)
{
result
<<=
1
;
result
|=
permissions
.
contains
(
allPermissions
[
i
])
?
1
:
0
;
}
return
result
;
}
@Restricted
(
NoExternalUse
.
class
)
public
static
Set
<
PosixFilePermission
>
modeToPermissions
(
int
mode
)
throws
IOException
{
// Anything larger is a file type, not a permission.
int
PERMISSIONS_MASK
=
07777
;
// setgid/setuid/sticky are not supported.
int
MAX_SUPPORTED_MODE
=
0777
;
mode
=
mode
&
PERMISSIONS_MASK
;
if
((
mode
&
MAX_SUPPORTED_MODE
)
!=
mode
)
{
throw
new
IOException
(
"Invalid mode: "
+
mode
);
}
PosixFilePermission
[]
allPermissions
=
PosixFilePermission
.
values
();
Set
<
PosixFilePermission
>
result
=
EnumSet
.
noneOf
(
PosixFilePermission
.
class
);
for
(
int
i
=
0
;
i
<
allPermissions
.
length
;
i
++)
{
if
((
mode
&
1
)
==
1
)
{
result
.
add
(
allPermissions
[
allPermissions
.
length
-
i
-
1
]);
}
mode
>>=
1
;
}
return
result
;
}
/**
* Converts a {@link File} into a {@link Path} and checks runtime exceptions.
* @throws IOException if {@code f.toPath()} throws {@link InvalidPathException}.
*/
@Restricted
(
NoExternalUse
.
class
)
public
static
@Nonnull
Path
fileToPath
(
@Nonnull
File
file
)
throws
IOException
{
try
{
return
file
.
toPath
();
}
catch
(
InvalidPathException
e
)
{
throw
new
IOException
(
e
);
}
}
public
static
final
FastDateFormat
XS_DATETIME_FORMATTER
=
FastDateFormat
.
getInstance
(
"yyyy-MM-dd'T'HH:mm:ss'Z'"
,
new
SimpleTimeZone
(
0
,
"GMT"
));
public
static
final
FastDateFormat
XS_DATETIME_FORMATTER
=
FastDateFormat
.
getInstance
(
"yyyy-MM-dd'T'HH:mm:ss'Z'"
,
new
SimpleTimeZone
(
0
,
"GMT"
));
// Note: RFC822 dates must not be localized!
// Note: RFC822 dates must not be localized!
...
@@ -1664,4 +1710,15 @@ public class Util {
...
@@ -1664,4 +1710,15 @@ public class Util {
*/
*/
@Restricted
(
value
=
NoExternalUse
.
class
)
@Restricted
(
value
=
NoExternalUse
.
class
)
static
boolean
GC_AFTER_FAILED_DELETE
=
SystemProperties
.
getBoolean
(
Util
.
class
.
getName
()
+
".performGCOnFailedDelete"
);
static
boolean
GC_AFTER_FAILED_DELETE
=
SystemProperties
.
getBoolean
(
Util
.
class
.
getName
()
+
".performGCOnFailedDelete"
);
/**
* If this flag is true, native implementations of {@link FilePath#chmod}
* and {@link hudson.util.IOUtils#mode} are used instead of NIO.
* <p>
* This should only be enabled if the setgid/setuid/sticky bits are
* intentionally set on the Jenkins installation and they are being
* overwritten by Jenkins erroneously.
*/
@Restricted
(
value
=
NoExternalUse
.
class
)
public
static
boolean
NATIVE_CHMOD_MODE
=
SystemProperties
.
getBoolean
(
Util
.
class
.
getName
()
+
".useNativeChmodAndMode"
);
}
}
core/src/main/java/hudson/model/AbstractItem.java
浏览文件 @
6f95e400
...
@@ -381,21 +381,6 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
...
@@ -381,21 +381,6 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
return
getRelativeNameFrom
(
p
);
return
getRelativeNameFrom
(
p
);
}
}
/**
* @param p
* The ItemGroup instance used as context to evaluate the relative name of this AbstractItem
* @return
* The name of the current item, relative to p.
* Nested ItemGroups are separated by / character.
*/
public
String
getRelativeNameFrom
(
ItemGroup
p
)
{
return
Functions
.
getRelativeNameFrom
(
this
,
p
);
}
public
String
getRelativeNameFrom
(
Item
item
)
{
return
getRelativeNameFrom
(
item
.
getParent
());
}
/**
/**
* Called right after when a {@link Item} is loaded from disk.
* Called right after when a {@link Item} is loaded from disk.
* This is an opportunity to do a post load processing.
* This is an opportunity to do a post load processing.
...
@@ -470,12 +455,10 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
...
@@ -470,12 +455,10 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
return
getShortUrl
();
return
getShortUrl
();
}
}
@Override
@Exported
(
visibility
=
999
,
name
=
"url"
)
@Exported
(
visibility
=
999
,
name
=
"url"
)
public
final
String
getAbsoluteUrl
()
{
public
final
String
getAbsoluteUrl
()
{
String
r
=
Jenkins
.
getInstance
().
getRootUrl
();
return
Item
.
super
.
getAbsoluteUrl
();
if
(
r
==
null
)
throw
new
IllegalStateException
(
"Root URL isn't configured yet. Cannot compute absolute URL."
);
return
Util
.
encode
(
r
+
getUrl
());
}
}
/**
/**
...
...
core/src/main/java/hudson/model/BuildableItem.java
浏览文件 @
6f95e400
...
@@ -40,13 +40,19 @@ public interface BuildableItem extends Item, Task {
...
@@ -40,13 +40,19 @@ public interface BuildableItem extends Item, Task {
* Use {@link #scheduleBuild(Cause)}. Since 1.283
* Use {@link #scheduleBuild(Cause)}. Since 1.283
*/
*/
@Deprecated
@Deprecated
boolean
scheduleBuild
();
default
boolean
scheduleBuild
()
{
return
scheduleBuild
(
new
Cause
.
LegacyCodeCause
());
}
boolean
scheduleBuild
(
Cause
c
);
boolean
scheduleBuild
(
Cause
c
);
/**
/**
* @deprecated
* @deprecated
* Use {@link #scheduleBuild(int, Cause)}. Since 1.283
* Use {@link #scheduleBuild(int, Cause)}. Since 1.283
*/
*/
@Deprecated
@Deprecated
boolean
scheduleBuild
(
int
quietPeriod
);
default
boolean
scheduleBuild
(
int
quietPeriod
)
{
return
scheduleBuild
(
quietPeriod
,
new
Cause
.
LegacyCodeCause
());
}
boolean
scheduleBuild
(
int
quietPeriod
,
Cause
c
);
boolean
scheduleBuild
(
int
quietPeriod
,
Cause
c
);
}
}
core/src/main/java/hudson/model/Item.java
浏览文件 @
6f95e400
...
@@ -25,9 +25,12 @@
...
@@ -25,9 +25,12 @@
package
hudson.model
;
package
hudson.model
;
import
hudson.Functions
;
import
hudson.Functions
;
import
hudson.Util
;
import
jenkins.model.Jenkins
;
import
jenkins.util.SystemProperties
;
import
jenkins.util.SystemProperties
;
import
hudson.security.PermissionScope
;
import
hudson.security.PermissionScope
;
import
jenkins.util.io.OnMaster
;
import
jenkins.util.io.OnMaster
;
import
jline.internal.Nullable
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerRequest
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -39,6 +42,9 @@ import hudson.security.PermissionGroup;
...
@@ -39,6 +42,9 @@ import hudson.security.PermissionGroup;
import
hudson.security.AccessControlled
;
import
hudson.security.AccessControlled
;
import
hudson.util.Secret
;
import
hudson.util.Secret
;
import
javax.annotation.CheckForNull
;
import
javax.annotation.Nonnull
;
/**
/**
* Basic configuration unit in Hudson.
* Basic configuration unit in Hudson.
*
*
...
@@ -131,18 +137,32 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
...
@@ -131,18 +137,32 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
/**
/**
* Gets the relative name to this item from the specified group.
* Gets the relative name to this item from the specified group.
*
*
* @param g
* The {@link ItemGroup} instance used as context to evaluate the relative name of this item
* @return
* The name of the current item, relative to p. Nested {@link ItemGroup}s are separated by {@code /} character.
* @since 1.419
* @since 1.419
* @return
* @return
* String like "../foo/bar"
* String like "../foo/bar".
* {@code null} if one of item parents is not an {@link Item}.
*/
*/
String
getRelativeNameFrom
(
ItemGroup
g
);
@Nullable
default
String
getRelativeNameFrom
(
@CheckForNull
ItemGroup
g
)
{
return
Functions
.
getRelativeNameFrom
(
this
,
g
);
}
/**
/**
* Short for {@code getRelativeNameFrom(item.getParent())}
* Short for {@code getRelativeNameFrom(item.getParent())}
*
*
* @return String like "../foo/bar".
* {@code null} if one of item parents is not an {@link Item}.
* @since 1.419
* @since 1.419
*/
*/
String
getRelativeNameFrom
(
Item
item
);
@Nullable
default
String
getRelativeNameFrom
(
@Nonnull
Item
item
)
{
return
getRelativeNameFrom
(
item
.
getParent
());
}
/**
/**
* Returns the URL of this item relative to the context root of the application.
* Returns the URL of this item relative to the context root of the application.
...
@@ -180,7 +200,12 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
...
@@ -180,7 +200,12 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
* (even this won't work for the same reason, which should be fixed.)
* (even this won't work for the same reason, which should be fixed.)
*/
*/
@Deprecated
@Deprecated
String
getAbsoluteUrl
();
default
String
getAbsoluteUrl
()
{
String
r
=
Jenkins
.
getInstance
().
getRootUrl
();
if
(
r
==
null
)
throw
new
IllegalStateException
(
"Root URL isn't configured yet. Cannot compute absolute URL."
);
return
Util
.
encode
(
r
+
getUrl
());
}
/**
/**
* Called right after when a {@link Item} is loaded from disk.
* Called right after when a {@link Item} is loaded from disk.
...
@@ -207,7 +232,9 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
...
@@ -207,7 +232,9 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
*
*
* @since 1.374
* @since 1.374
*/
*/
default
void
onCreatedFromScratch
()
{}
default
void
onCreatedFromScratch
()
{
// do nothing by default
}
/**
/**
* Save the settings to a file.
* Save the settings to a file.
...
...
core/src/main/java/hudson/util/IOUtils.java
浏览文件 @
6f95e400
package
hudson.util
;
package
hudson.util
;
import
hudson.Functions
;
import
hudson.Functions
;
import
hudson.Util
;
import
hudson.os.PosixAPI
;
import
hudson.os.PosixAPI
;
import
hudson.os.PosixException
;
import
hudson.os.PosixException
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
...
@@ -119,13 +120,27 @@ public class IOUtils {
...
@@ -119,13 +120,27 @@ public class IOUtils {
/**
/**
* Gets the mode of a file/directory, if appropriate.
* Gets the mode of a file/directory, if appropriate. Only includes read, write, and
* execute permissions for the owner, group, and others, i.e. the max return value
* is 0777. Consider using {@link Files#getPosixFilePermissions} instead if you only
* care about access permissions.
*
* @return a file mode, or -1 if not on Unix
* @return a file mode, or -1 if not on Unix
* @throws PosixException if the file could not be statted, e.g. broken symlink
* @throws PosixException if the file could not be statted, e.g. broken symlink
*/
*/
public
static
int
mode
(
File
f
)
throws
PosixException
{
public
static
int
mode
(
File
f
)
throws
PosixException
{
if
(
Functions
.
isWindows
())
return
-
1
;
if
(
Functions
.
isWindows
())
return
-
1
;
return
PosixAPI
.
jnr
().
stat
(
f
.
getPath
()).
mode
();
try
{
if
(
Util
.
NATIVE_CHMOD_MODE
)
{
return
PosixAPI
.
jnr
().
stat
(
f
.
getPath
()).
mode
();
}
else
{
return
Util
.
permissionsToMode
(
Files
.
getPosixFilePermissions
(
Util
.
fileToPath
(
f
)));
}
}
catch
(
IOException
cause
)
{
PosixException
e
=
new
PosixException
(
"Unable to get file permissions"
,
null
);
e
.
initCause
(
cause
);
throw
e
;
}
}
}
/**
/**
...
...
core/src/main/java/jenkins/model/ParameterizedJobMixIn.java
浏览文件 @
6f95e400
...
@@ -377,29 +377,11 @@ public abstract class ParameterizedJobMixIn<JobT extends Job<JobT, RunT> & Param
...
@@ -377,29 +377,11 @@ public abstract class ParameterizedJobMixIn<JobT extends Job<JobT, RunT> & Param
*/
*/
Map
<
TriggerDescriptor
,
Trigger
<?>>
getTriggers
();
Map
<
TriggerDescriptor
,
Trigger
<?>>
getTriggers
();
/**
* @deprecated use {@link #scheduleBuild(Cause)}
*/
@Deprecated
@Override
default
boolean
scheduleBuild
()
{
return
getParameterizedJobMixIn
().
scheduleBuild
();
}
@Override
@Override
default
boolean
scheduleBuild
(
Cause
c
)
{
default
boolean
scheduleBuild
(
Cause
c
)
{
return
getParameterizedJobMixIn
().
scheduleBuild
(
c
);
return
getParameterizedJobMixIn
().
scheduleBuild
(
c
);
}
}
/**
* @deprecated use {@link #scheduleBuild(int, Cause)}
*/
@Deprecated
@Override
default
boolean
scheduleBuild
(
int
quietPeriod
)
{
return
getParameterizedJobMixIn
().
scheduleBuild
(
quietPeriod
);
}
@Override
@Override
default
boolean
scheduleBuild
(
int
quietPeriod
,
Cause
c
)
{
default
boolean
scheduleBuild
(
int
quietPeriod
,
Cause
c
)
{
return
getParameterizedJobMixIn
().
scheduleBuild
(
quietPeriod
,
c
);
return
getParameterizedJobMixIn
().
scheduleBuild
(
quietPeriod
,
c
);
...
...
core/src/test/java/hudson/FilePathTest.java
浏览文件 @
6f95e400
...
@@ -25,6 +25,7 @@ package hudson;
...
@@ -25,6 +25,7 @@ package hudson;
import
hudson.FilePath.TarCompression
;
import
hudson.FilePath.TarCompression
;
import
hudson.model.TaskListener
;
import
hudson.model.TaskListener
;
import
hudson.os.PosixAPI
;
import
hudson.remoting.VirtualChannel
;
import
hudson.remoting.VirtualChannel
;
import
hudson.util.NullStream
;
import
hudson.util.NullStream
;
import
hudson.util.StreamTaskListener
;
import
hudson.util.StreamTaskListener
;
...
@@ -245,7 +246,7 @@ public class FilePathTest {
...
@@ -245,7 +246,7 @@ public class FilePathTest {
throw
x
;
throw
x
;
}
}
}
finally
{
}
finally
{
toF
.
chmod
(
700
);
toF
.
chmod
(
0
700
);
}
}
}
}
...
@@ -471,6 +472,25 @@ public class FilePathTest {
...
@@ -471,6 +472,25 @@ public class FilePathTest {
}
}
}
}
@Test
public
void
copyToWithPermissionSpecialPermissions
()
throws
IOException
,
InterruptedException
{
assumeFalse
(
"Test uses POSIX-specific features"
,
Functions
.
isWindows
());
File
tmp
=
temp
.
getRoot
();
File
original
=
new
File
(
tmp
,
"original"
);
FilePath
originalP
=
new
FilePath
(
channels
.
french
,
original
.
getPath
());
originalP
.
touch
(
0
);
PosixAPI
.
jnr
().
chmod
(
original
.
getAbsolutePath
(),
02777
);
// Read/write/execute for everyone and setuid.
File
sameChannelCopy
=
new
File
(
tmp
,
"sameChannelCopy"
);
FilePath
sameChannelCopyP
=
new
FilePath
(
channels
.
french
,
sameChannelCopy
.
getPath
());
originalP
.
copyToWithPermission
(
sameChannelCopyP
);
assertEquals
(
"Special permissions should be copied on the same machine"
,
02777
,
PosixAPI
.
jnr
().
stat
(
sameChannelCopy
.
getAbsolutePath
()).
mode
()
&
07777
);
File
diffChannelCopy
=
new
File
(
tmp
,
"diffChannelCopy"
);
FilePath
diffChannelCopyP
=
new
FilePath
(
channels
.
british
,
diffChannelCopy
.
getPath
());
originalP
.
copyToWithPermission
(
diffChannelCopyP
);
assertEquals
(
"Special permissions should not be copied across machines"
,
00777
,
PosixAPI
.
jnr
().
stat
(
diffChannelCopy
.
getAbsolutePath
()).
mode
()
&
07777
);
}
@Test
public
void
symlinkInTar
()
throws
Exception
{
@Test
public
void
symlinkInTar
()
throws
Exception
{
assumeFalse
(
"can't test on Windows"
,
Functions
.
isWindows
());
assumeFalse
(
"can't test on Windows"
,
Functions
.
isWindows
());
...
@@ -739,7 +759,38 @@ public class FilePathTest {
...
@@ -739,7 +759,38 @@ public class FilePathTest {
// and now fail when flush is bad!
// and now fail when flush is bad!
tmpDirPath
.
child
(
"../"
+
archive
.
getName
()).
untar
(
outDir
,
TarCompression
.
NONE
);
tmpDirPath
.
child
(
"../"
+
archive
.
getName
()).
untar
(
outDir
,
TarCompression
.
NONE
);
}
}
@Test
public
void
chmod
()
throws
Exception
{
assumeFalse
(
Functions
.
isWindows
());
File
f
=
temp
.
newFile
(
"file"
);
FilePath
fp
=
new
FilePath
(
f
);
int
prevMode
=
fp
.
mode
();
assertEquals
(
0400
,
chmodAndMode
(
fp
,
0400
));
assertEquals
(
0412
,
chmodAndMode
(
fp
,
0412
));
assertEquals
(
0777
,
chmodAndMode
(
fp
,
0777
));
assertEquals
(
prevMode
,
chmodAndMode
(
fp
,
prevMode
));
}
@Test
public
void
chmodInvalidPermissions
()
throws
Exception
{
assumeFalse
(
Functions
.
isWindows
());
File
f
=
temp
.
newFolder
(
"folder"
);
FilePath
fp
=
new
FilePath
(
f
);
int
invalidMode
=
01770
;
// Full permissions for owner and group plus sticky bit.
try
{
chmodAndMode
(
fp
,
invalidMode
);
fail
(
"Setting sticky bit should fail"
);
}
catch
(
IOException
e
)
{
assertEquals
(
"Invalid mode: "
+
invalidMode
,
e
.
getMessage
());
}
}
private
int
chmodAndMode
(
FilePath
path
,
int
mode
)
throws
Exception
{
path
.
chmod
(
mode
);
return
path
.
mode
();
}
@Test
public
void
deleteRecursiveOnUnix
()
throws
Exception
{
@Test
public
void
deleteRecursiveOnUnix
()
throws
Exception
{
assumeFalse
(
"Uses Unix-specific features"
,
Functions
.
isWindows
());
assumeFalse
(
"Uses Unix-specific features"
,
Functions
.
isWindows
());
Path
targetDir
=
temp
.
newFolder
(
"target"
).
toPath
();
Path
targetDir
=
temp
.
newFolder
(
"target"
).
toPath
();
...
...
core/src/test/java/hudson/UtilTest.java
浏览文件 @
6f95e400
...
@@ -36,6 +36,7 @@ import java.io.File;
...
@@ -36,6 +36,7 @@ import java.io.File;
import
java.io.FileInputStream
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStream
;
import
java.nio.file.attribute.PosixFilePermissions
;
import
static
org
.
hamcrest
.
CoreMatchers
.
allOf
;
import
static
org
.
hamcrest
.
CoreMatchers
.
allOf
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
...
@@ -43,6 +44,7 @@ import static org.hamcrest.CoreMatchers.hasItem;
...
@@ -43,6 +44,7 @@ import static org.hamcrest.CoreMatchers.hasItem;
import
static
org
.
hamcrest
.
CoreMatchers
.
instanceOf
;
import
static
org
.
hamcrest
.
CoreMatchers
.
instanceOf
;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
hamcrest
.
CoreMatchers
.
is
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
hamcrest
.
CoreMatchers
.
startsWith
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
junit
.
Assert
.*;
import
org.apache.commons.io.FileUtils
;
import
org.apache.commons.io.FileUtils
;
...
@@ -724,4 +726,41 @@ public class UtilTest {
...
@@ -724,4 +726,41 @@ public class UtilTest {
assertTrue
(
Util
.
isDescendant
(
new
File
(
root
,
"."
),
new
File
(
new
File
(
root
,
"child"
),
"."
)));
assertTrue
(
Util
.
isDescendant
(
new
File
(
root
,
"."
),
new
File
(
new
File
(
root
,
"child"
),
"."
)));
}
}
@Test
public
void
testModeToPermissions
()
throws
Exception
{
assertEquals
(
PosixFilePermissions
.
fromString
(
"rwxrwxrwx"
),
Util
.
modeToPermissions
(
0777
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"rwxr-xrwx"
),
Util
.
modeToPermissions
(
0757
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"rwxr-x---"
),
Util
.
modeToPermissions
(
0750
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"r-xr-x---"
),
Util
.
modeToPermissions
(
0550
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"r-xr-----"
),
Util
.
modeToPermissions
(
0540
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"--xr-----"
),
Util
.
modeToPermissions
(
0140
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"--xr---w-"
),
Util
.
modeToPermissions
(
0142
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"--xr--rw-"
),
Util
.
modeToPermissions
(
0146
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"-wxr--rw-"
),
Util
.
modeToPermissions
(
0346
));
assertEquals
(
PosixFilePermissions
.
fromString
(
"---------"
),
Util
.
modeToPermissions
(
0000
));
assertEquals
(
"Non-permission bits should be ignored"
,
PosixFilePermissions
.
fromString
(
"r-xr-----"
),
Util
.
modeToPermissions
(
0100540
));
try
{
Util
.
modeToPermissions
(
01777
);
fail
(
"Did not detect invalid mode"
);
}
catch
(
IOException
e
)
{
assertThat
(
e
.
getMessage
(),
startsWith
(
"Invalid mode"
));
}
}
@Test
public
void
testPermissionsToMode
()
throws
Exception
{
assertEquals
(
0777
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"rwxrwxrwx"
)));
assertEquals
(
0757
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"rwxr-xrwx"
)));
assertEquals
(
0750
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"rwxr-x---"
)));
assertEquals
(
0550
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"r-xr-x---"
)));
assertEquals
(
0540
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"r-xr-----"
)));
assertEquals
(
0140
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"--xr-----"
)));
assertEquals
(
0142
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"--xr---w-"
)));
assertEquals
(
0146
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"--xr--rw-"
)));
assertEquals
(
0346
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"-wxr--rw-"
)));
assertEquals
(
0000
,
Util
.
permissionsToMode
(
PosixFilePermissions
.
fromString
(
"---------"
)));
}
}
}
core/src/test/java/hudson/util/io/TarArchiverTest.java
浏览文件 @
6f95e400
...
@@ -83,9 +83,9 @@ public class TarArchiverTest {
...
@@ -83,9 +83,9 @@ public class TarArchiverTest {
// extract via the tar command
// extract via the tar command
run
(
e
,
"tar"
,
"xvpf"
,
tar
.
getAbsolutePath
());
run
(
e
,
"tar"
,
"xvpf"
,
tar
.
getAbsolutePath
());
assertEquals
(
0
100
755
,
e
.
child
(
"a.txt"
).
mode
());
assertEquals
(
0755
,
e
.
child
(
"a.txt"
).
mode
());
assertEquals
(
dirMode
,
e
.
child
(
"subdir"
).
mode
());
assertEquals
(
dirMode
,
e
.
child
(
"subdir"
).
mode
());
assertEquals
(
0
100
644
,
e
.
child
(
"subdir/b.txt"
).
mode
());
assertEquals
(
0644
,
e
.
child
(
"subdir/b.txt"
).
mode
());
// extract via the zip command
// extract via the zip command
...
@@ -93,9 +93,9 @@ public class TarArchiverTest {
...
@@ -93,9 +93,9 @@ public class TarArchiverTest {
run
(
e
,
"unzip"
,
zip
.
getAbsolutePath
());
run
(
e
,
"unzip"
,
zip
.
getAbsolutePath
());
e
=
e
.
listDirectories
().
get
(
0
);
e
=
e
.
listDirectories
().
get
(
0
);
assertEquals
(
0
100
755
,
e
.
child
(
"a.txt"
).
mode
());
assertEquals
(
0755
,
e
.
child
(
"a.txt"
).
mode
());
assertEquals
(
dirMode
,
e
.
child
(
"subdir"
).
mode
());
assertEquals
(
dirMode
,
e
.
child
(
"subdir"
).
mode
());
assertEquals
(
0
100
644
,
e
.
child
(
"subdir/b.txt"
).
mode
());
assertEquals
(
0644
,
e
.
child
(
"subdir/b.txt"
).
mode
());
}
finally
{
}
finally
{
tar
.
delete
();
tar
.
delete
();
zip
.
delete
();
zip
.
delete
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录