Gradle:即使将文件添加到目标目录,同步任务也会将项目视为最新的

时间:2013-12-15 10:26:07

标签: gradle

我正在使用这个简单的Gradle任务:

task syncTask(type: Sync) {
    from "src/"
    into "dest/"
}

根据docs,我希望将src复制到destsrc中不存在的任何文件都会从dest中删除。这基本上工作正常。但是,如果在同步后将文件添加到dest,则在任务再次运行时无法识别。该项目简单地被认为是UP-TO-DATE,不采取任何行动。

是否可以配置同步任务,以便检测目标目录中添加的文件并再次运行任务?

> gradle -v

------------------------------------------------------------
Gradle 1.9
------------------------------------------------------------

Build time:   2013-11-19 08:20:02 UTC
Build number: none
Revision:     7970ec3503b4f5767ee1c1c69f8b4186c4763e3d

Groovy:       1.8.6
Ant:          Apache Ant(TM) version 1.9.2 compiled on July 8 2013
Ivy:          2.2.0
JVM:          1.7.0_25 (Oracle Corporation 23.7-b01)
OS:           Linux 3.2.0-53-generic amd64

编辑1:以下是重现行为的步骤:

$ mkdir src
$ touch src/a
$ mkdir dest
$ gradle syncTask
:syncTask

BUILD SUCCESSFUL

Total time: 1.113 secs
$ ls dest/
a

到目前为止,一切都按预期工作。现在,文件b已添加到dest/文件夹:

$ touch dest/b
$ ls dest/
a  b
$ gradle syncTask
:syncTask UP-TO-DATE

BUILD SUCCESSFUL

Total time: 1.024 secs

我希望从b中移除dest/。但是,Sync任务似乎没有注意到它的输出已经改变,因此没有运行。

2 个答案:

答案 0 :(得分:2)

是的,似乎Sync任务有点坏了,在Gradle 1.10中也是如此。 为了解决这个问题,我很快就破解了一个自定义任务,只需将它放在脚本中。

class SyncDir extends DefaultTask {
    def inDir
    def outDir

    @TaskAction
    def run() {
        project.delete outDir
        project.copy { from inDir; into outDir }
    }

    def from(name) {
        inDir = new File(name)
    }

    def into(name) {
        outDir = new File(name)
    }
}

您可以像使用同步任务一样使用它。

task toto (type: SyncDir) {
    from 'toto'
    into 'tata/toto'
}

答案 1 :(得分:2)

据我所知,问题与此问题https://issues.gradle.org/browse/GRADLE-2270有关。如果所有输入文件都存在并且是最新的,则同步任务被视为最新,忽略任何其他文件。它在Gradle 1.0中报告过,但在Gradle 2.0中仍无效。

作为解决方法,我将以下块添加到我的同步任务

outputs.upToDateWhen {
    def Set<String> names = inputs.files.files.collect{ _ -> _.name }
    def Set<String> destDirContent = destinationDir.list().toList().toSet()
    def boolean good = names.containsAll(destDirContent)
    return good
}

在您的情况下,任务应该如下所示。

task syncTask(type: Sync) {
    from "src/"
    into "dest/" 
    outputs.upToDateWhen {
        def Set<String> names = inputs.files.files.collect{ _ -> _.name }
        def Set<String> destDirContent = destinationDir.list().toList().toSet()
        def boolean good = names.containsAll(destDirContent)
        return good
    }
}

但是当源目录为空时,它不起作用(即任务被认为是UP-TO-DATE),这可能是因为Gradle代码中的一些快捷方式。这对我来说不是问题,所以我没有试图找到更好的解决方案,只是要注意这个案例。