问题描述
我有一个tar
文件,其中包含多个tar.gz
文件(一个Docker映像),我想从中提取一个文件。在shell脚本中执行此操作很简单,但是使用Gradle时似乎有些棘手。
这是我到目前为止所拥有的:
task extractOuter(type: copy) {
dependsOn jibBuildTar
from tarTree(file("${buildDir}/jib-image.tar"))
include "*.tar.gz"
into "${buildDir}/tgz"
}
task extractInner(type: copy) {
dependsOn extractOuter
from (filetree(dir: "${buildDir}/tgz").collect { tarTree(it) }) {
include "**/filename"
includeEmptyDirs = false
}
into "${buildDir}/files"
}
起初似乎可以正常运行,但事实证明它偶尔会失败:extractInner
任务找不到文件。也许我没有正确使用Gradle的惰性评估。
如何使其工作?还是有完全不同,更优雅的方式?
解决方法
在shell脚本中执行此操作很简单
您可以通过使用Exec
任务类型来继续使用Shell脚本。
但是使用Gradle时似乎有些棘手。
到目前为止,您拥有的是如何使用Gradle进行操作。 Gradle的优点是它不会执行已经发生的工作。有关更多详细信息,请参见Build Cache。
起初它似乎可以工作,但是事实证明它偶尔会失败:extractInner任务找不到该文件。也许我没有正确使用Gradle的惰性评估。
在上面的链接文档(重点是我的)中指出了这一点:
某些任务,例如Copy或Jar,通常使缓存变得没有意义,因为Gradle只是将文件从一个位置复制到另一个位置。使不产生输出或没有任务动作的任务可缓存也是没有意义的。
因此,您已经声明了任务,但尚未配置它们以产生可能会或可能不会导致问题的任何输出,因为您希望输出会出现在任务相关项中。
由于Copy
扩展了DefaultTask
,因此您可以使用outputs
来设置任务输出。
task extractOuter(type: Copy) {
dependsOn jibBuildTar
outputs.dir(file("$buildDir/tgz")
from tarTree(file("${buildDir}/jib-image.tar"))
include "*.tar.gz"
into "${buildDir}/tgz"
}
task extractInner(type: Copy) {
dependsOn extractOuter
outputs.dir(file("$buildDir/files")
from (fileTree(dir: "${buildDir}/tgz").collect { tarTree(it) }) {
include "**/filename"
includeEmptyDirs = false
}
into "${buildDir}/files"
}