Gradle任务:如何等待文件操作完成

时间:2016-05-14 02:21:33

标签: file-io gradle groovy unzip

这是我想要做的事情:

  1. 将存档(zip)从buildscript依赖项复制到临时目录
  2. 将存档解压缩到build
  3. 中的另一个目录

    复制档案(作品)

    的任务
    task copyTpcds(type: Copy) {  
        file('build/zip').mkdirs()
        from buildscript.configurations.classpath
        include 'tpcds*'
        into 'build/zip'
    }
    

    解压缩然后删除存档的任务

    task extractTpcds(type: Copy) {  
        def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
        def outDir = file('build/cmd/tpcds')
        outDir.mkdirs() // make sure the directory exists
        from zipTree(file(names[0])) // generates error when 
        into outDir
        // now remove copied zip file
        //zipFile.delete() // deletes file before the extractions completes?
    }
    

    以下是几种情况:

    1. 如果我将两个任务都放入build.gradle并尝试运行任何内容,即使只是gradle tasks,那么我会在任务#2的代码中收到此错误:Neither path nor baseDir may be null or empty string. path='null' basedir='C:\dev\code\td\pdo\tpcds-tpg':{{1 }}
    2. 如果我在第二个任务中注释掉代码,则第一个任务将运行并将zip文件复制到file(names[0])
    3. 现在我可以取消注释第二个任务中的代码(删除除外)并执行build/zip它将运行并提取存档
    4. 所以在我看来

      1. 无论执行哪些任务,都会对所有任务评估文件操作
      2. 如果我有一个复制文件的代码,其中包含一些试图对正在复制的文件进行操作的后续代码,那么该代码将不会等待复制过程完成,并且因为文件不存在而失败
      3. 我对如何处理此事感到失望,并非常感谢您的建议

2 个答案:

答案 0 :(得分:3)

以下适用于我,使用Gradle 2.12(假设zip文件位于files):

buildscript {
    configurations {
        classpath
    }

    dependencies {
        classpath files("files/tpcds.zip")
    }
}

def copyFiles = { ->
    ant.mkdir(dir: "build/zip")
    buildscript.configurations.classpath.each { def thisFile ->
        if (thisFile.name ==~ /tpcds.*/) {
            ant.copy(file: thisFile.absolutePath, todir: "build/zip")
        }
    }
}

tasks.whenTaskAdded { task ->
    if (task.name == "extractTpcds") {
        copyFiles()
    }
}

task copyTpcds << {  
    copyFiles()
}

task extractTpcds(type: Copy) {  
    def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
    def outDir = file('build/cmd/tpcds')
    outDir.mkdirs() // make sure the directory exists
    from zipTree(file(names[0])) // generates error when 
    into outDir
    // now remove copied zip file
    //zipFile.delete() // deletes file before the extractions completes?
}

原件问题涉及与ICE规则的阻抗不匹配:初始化阶段,配置阶段和执行阶段。特别是,Copy任务的规范处于Configuration阶段;通常,在执行阶段强制执行任务依赖(例如dependsOn)。在配置阶段期间,extractTpcds任务依赖于其他代码。

在我的例子中,有两种情况:

  • gradle copyTpcds将在执行阶段调用copyFiles方法。 <<表示“在执行阶段执行此操作”。
  • gradle tasks将在配置阶段触发whenTaskAdded中的代码,并致电copyFiles。同样适用于gradle extractTpcds

另一种方法是在两个任务中使用AntBuilder,完全避免使用Type: Copy,如下所示:

buildscript {
    configurations {
        classpath
    }
    dependencies {
        classpath files("files/tpcds.zip")
    }
}

task copyTpcds << {  
    ant.mkdir(dir: "build/zip")
    buildscript.configurations.classpath.each { def thisFile ->
        if (thisFile.name ==~ /tpcds.*/) {
            ant.copy(file: thisFile.absolutePath, todir: "build/zip")
        }
    }
}

task extractTpcds(dependsOn: 'copyTpcds') << {  
    def outDir = "build/cmd/tpcds"
    ant.mkdir(dir: outDir)
    def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
    names.eachWithIndex { zipFile, index ->
        if (index == 0) {
            ant.unzip(src: zipFile, dest: outDir)
        }
    }
}

答案 1 :(得分:0)

这样的东西应该有效,但为什么你需要删除拉链?使用dependsOn链接任务意味着您只需运行第二个任务,copyTpcds将自动运行,除非输入或输出已更改(已删除)

task extractTpcds(type: Copy) {

dependsOn(copyTpcds) //make this execute after

def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when 
into outDir
// now remove copied zip file
doLast { zipFile.delete() }// deletes file after the extractions completes

}