考虑添加文件对输出目录的增量构建支持

Incremental build support for output directory considering added files

Gradle documentation 告诉我们:

Note that if a task has an output directory specified, any files added to that directory since the last time it was executed are ignored and will NOT cause the task to be out of date. This is so unrelated tasks may share an output directory without interfering with each other. If this is not the behaviour you want for some reason, consider using TaskOutputs.upToDateWhen(groovy.lang.Closure)

问题:使用 upToDateWhen 的解决方案看起来如何(以便考虑添加的文件)。主要问题是必须访问构建缓存以检索上次任务 运行.

的输出目录内容哈希

不确定我是否正确理解了问题或者你为什么提到构建缓存。我假设您不知道添加了 upToDateWhen() 的谓词被认为是 除了 之外的任何其他最新检查,例如添加了 TaskOutputs.dir() 的谓词?

执行以下示例任务:

task foo {
    def outDir = file('out')
    outputs.dir(outDir)
    outputs.upToDateWhen { outDir.listFiles().length == 1 }
    doLast {
       new File(outDir, 'foo.txt') << 'whatever'
    }
}

只要输出目录中只有一个文件(通过upToDateWhen配置)任务生成的文件(out/foo.txt) 在任务 运行 后没有更改,任务将是最新的。如果您 change/remove 任务在输出目录中创建的文件,或者如果您向输出目录添加更多文件,则任务将再次 运行。


根据评论中更新的问题更新答案:

task foo {
    def outDir = file('out')

    /* sample task action: */
    doFirst {
        def numOutFiles = new Random().nextInt(5)
        for (int i = 1; i <= numOutFiles; i++) {
            new File(outDir, "foo${i}.txt") << 'whatever'
        }
    }

    /* up-to-date checking configuration: */
    def counterFile = new File(buildDir, 'counterFile.txt')
    outputs.dir(outDir)
    outputs.upToDateWhen {
        counterFile.isFile() \
          && counterFile.text as Integer == countFiles(outDir)
    }
    doLast {
        counterFile.text = countFiles(outDir)
    }
}

def countFiles(def dir) {
    def result = 0
    def files = dir.listFiles()
    if (files != null) {
        files.each {
            result++
            if (it.isDirectory()) {
                result += countFiles(it)
            }
        }
    }
    result
}