评估Gradle CopySpec.eachFile中的FileCopyDetails
我正在尝试做一件似乎相当简单的事情:使用Gradle评估Gradle CopySpec.eachFile中的FileCopyDetails,gradle,path,copy,evaluation,Gradle,Path,Copy,Evaluation,我正在尝试做一件似乎相当简单的事情:使用GradleCopy任务或方法显示我正在复制的文件的目标路径。 为此,我使用了CopySpec.eachFile方法,在该方法中,我使用了使用FileCopyDetails来访问目标路径,正如我在中所解释的那样 下面是一个使用Copy任务的示例(与Copy方法的行为相同): 问题在于:在每个文件中使用的基础FileCopyDetails对象的每个属性的计算结果都是相同的值: :copyTaskUsingEachFile ---- content of F
Copy
任务或方法显示我正在复制的文件的目标路径。为此,我使用了
CopySpec.eachFile
方法,在该方法中,我使用了使用FileCopyDetails
来访问目标路径,正如我在中所解释的那样
下面是一个使用Copy
任务的示例(与Copy
方法的行为相同):
问题在于:在每个文件中使用的基础FileCopyDetails
对象的每个属性的计算结果都是相同的值
:
:copyTaskUsingEachFile
---- content of FileCopyDetails object used in eachFile :
object toString = file 'C:\<some path>\resources\file-with-tokens.txt'
name = file-with-tokens.txt
path = file-with-tokens.txt
relativePath = file-with-tokens.txt
sourceName = file-with-tokens.txt
sourcePath = file-with-tokens.txt
task copyMultipleFilesDisplayTargetFolder(type: Copy) {
printTask 'copyMultipleFilesDisplayTargetFolder'
into 'generated'
//filter(ReplaceTokens, tokens: [sampleProp: 'Hello sample property!'])
eachFile {
println "file $it.name copied to $destinationDir/$it.path"
/* !!!! BEWARE !!!!
You can't use the below FileCopyDetails.getFile() when also using a filter operation.
Check https://discuss.gradle.org/t/combining-eachfile-filter-results-in-failure/14801/2
*/
println "Initial source path: ${it.getFile().getCanonicalPath()}"
println ''
}
from("$projectDir/resources/file-with-tokens.txt") {
into('subfolder')
}
from("$projectDir/resources2/file-with-tokens-2.txt") {
into('subfolder2')
}
from("$projectDir/resources3/file-with-tokens-3.txt") {
into('subfolder3')
}
}
这次我得到了以下结果:
:copyTaskUsingEachFileAndChildCopySpec
---- content of FileCopyDetails object used in eachFile :
object toString = file 'C:\<some path>\resources\file-with-tokens.txt'
name = file-with-tokens.txt
path = subfolder/file-with-tokens.txt
relativePath = subfolder/file-with-tokens.txt
sourceName = file-with-tokens.txt
sourcePath = file-with-tokens.txt
其中:
------------ TASK ------------ copyMultipleFilesDisplayTargetFolder
:copyMultipleFilesDisplayTargetFolder
file file-with-tokens.txt copied to C:\<some path>\generated/subfolder/file-with-tokens.txt
file file-with-tokens-2.txt copied to C:\<some path>\generated/subfolder2/file-with-tokens-2.txt
file file-with-tokens-3.txt copied to C:\<some path>\generated/subfolder3/file-with-tokens-3.txt
但是,在同时使用过滤器
操作时,不能使用FileCopyDetails.getFile()
这是一个神秘的Gradle bug,请在此处解释: 查看Gradle源代码时,
DefaultFileCopyDetails
类包含以下代码:
公共文件getFile(){
if(filterChain.hasFilters()){
抛出新的UnsupportedOperationException();
}否则{
返回fileDetails.getFile();
}
}
不幸的是,这解释了这个问题
无论如何,在任何其他情况下,我最初的两个问题有了新的答案,谢谢
更新3(最终版) 再次感谢吸血鬼(他专门为这个问题打开了一个Gradle案例),他为我们提供了前一个
过滤器
/getFile
bug的解决方案
有关详细信息,请参见his,但简单地说,为了避免出现问题,在同一CopySpec中,您只需在调用每个文件后调用过滤器
我确认它正在工作。如果你更彻底地阅读JavaDoc,你会在getPath()
和getRelativePath()
的第一句中找到解释,它们说返回此文件的路径,相对于复制目的地的根。
在第一个示例中,调用eachFile
方法的CopySpec
的复制目标是generated/subfolder
,因此目标文件的相对路径是file with tokens.txt
在第二个示例中,调用eachFile
方法的CopySpec
的复制目标是生成的,因此目标文件的相对路径是子文件夹/file with tokens.txt
将CopySpec
的复制目标与相对路径连接起来,您将获得目标文件的完整路径
如果你是e。G在调用eachFile
之前,添加一个rename
调用,比如rename{'foo-'+it}
,然后您会看到相对路径将变成foo file with tokens.txt
,而源路径仍然是file with tokens.txt
如果需要文件的源路径,只需使用FileCopyDetails
的file
属性即可。每个FileCopyDetails
也是一个filetreeeElement
(其超类),因此具有指向源文件的文件属性(file
对象)
请注意,filter
s可能存在干扰。如果在同一复制规范中以及在每个文件
之前有一个过滤器
,或者在执行每个文件
的父副本规范中有一个过滤器
,无论是在之前还是之后,都会得到一个不支持操作异常
。如果在同一复制规范中的每个文件
之后执行过滤器
,则它会工作。请参阅以了解更多信息。我更新了我的答案。;-)顺便说一句,您不需要从(“$projectDir/resources2/file-with-tokens-2.txt”)执行,只需从('resources2/file-with-tokens-2.txt')执行。相对路径的处理方式与给定给项目文件(对象…
的路径类似,因此与项目目录相对。关于过滤器问题,请参阅我的最新答案更新。:-)
task copyMultipleFilesDisplayTargetFolder(type: Copy) {
printTask 'copyMultipleFilesDisplayTargetFolder'
into 'generated'
filter(ReplaceTokens, tokens: [sampleProp: 'Hello sample property!'])
/* Here, we print the complete destination path of the copied files, BUT,
I don't know how to print their complete SOURCE path.
*/
eachFile {
println "file $it.name copied to $destinationDir/$it.path"
println ''
}
from("$projectDir/resources/file-with-tokens.txt") {
into('subfolder')
}
from("$projectDir/resources2/file-with-tokens-2.txt") {
into('subfolder2')
}
from("$projectDir/resources3/file-with-tokens-3.txt") {
into('subfolder3')
}
}
------------ TASK ------------ copyMultipleFilesDisplayTargetFolder
:copyMultipleFilesDisplayTargetFolder
file file-with-tokens.txt copied to C:\<some path>\generated/subfolder/file-with-tokens.txt
file file-with-tokens-2.txt copied to C:\<some path>\generated/subfolder2/file-with-tokens-2.txt
file file-with-tokens-3.txt copied to C:\<some path>\generated/subfolder3/file-with-tokens-3.txt
task copyMultipleFilesDisplayTargetFolder(type: Copy) {
printTask 'copyMultipleFilesDisplayTargetFolder'
into 'generated'
//filter(ReplaceTokens, tokens: [sampleProp: 'Hello sample property!'])
eachFile {
println "file $it.name copied to $destinationDir/$it.path"
/* !!!! BEWARE !!!!
You can't use the below FileCopyDetails.getFile() when also using a filter operation.
Check https://discuss.gradle.org/t/combining-eachfile-filter-results-in-failure/14801/2
*/
println "Initial source path: ${it.getFile().getCanonicalPath()}"
println ''
}
from("$projectDir/resources/file-with-tokens.txt") {
into('subfolder')
}
from("$projectDir/resources2/file-with-tokens-2.txt") {
into('subfolder2')
}
from("$projectDir/resources3/file-with-tokens-3.txt") {
into('subfolder3')
}
}