Search code examples
gradlegradle-kotlin-dsl

Why copy task delete stale output on first build?


I have this kotlin gradle build script representing my use case. I am working with Gradle 6.7.

This is my kotlin gradle build file:

plugins {
    java
}

tasks.register("createFile"){

    doLast{
        projectDir.resolve("tmp.txt").createNewFile()
        projectDir.resolve("tmp.txt").writeText("tmp")
    }

    dependsOn("assemble")
}

tasks.register("createExecFile", Exec::class){

    workingDir(buildDir)
    commandLine("cmd", "/c", "mkdir destdir\\subdir")

    dependsOn("createFile")
}

tasks.register("copyBug", Copy::class){

    from(projectDir.resolve("tmp.txt"))
    into(buildDir.resolve("destDir"))

    dependsOn("createExecFile")
}

Now run gradle copyBug -i.

The first time this will give you this output:

> Task :copyBug Deleting stale output file: E:\repo\BugCOpy\build\destDir Caching disabled for task ':copyBug' because:   Build cache is disabled Task ':copyBug' is not up-to-date because:   No history is available.

The copy task deletes the file created by the previous exec task.

Now if you rerun this command the copy task won't delete stale file.

So what are those stale file? How can I prevent those file to be deleted? My first build and is different than the other build.

Should I file a bug?


Solution

  • In your createExecFile task you produce output files without telling Gradle about them. So Gradle doesn’t know that this task and the copyBug task use the same output directory. Instead, Gradle believes that copyBug is the only task producing outputs under build/destdir and hence it’s safer to assume that any existing files in that directory should not be there (and are “stale”).

    The solution is to tell Gradle that your createExecFile task outputs to build/destdir:

    tasks.register("createExecFile", Exec::class) {
    
        workingDir(buildDir)
        commandLine("cmd", "/c", "mkdir destdir\\subdir")
    
        // tell Gradle about the output directory
        outputs.dir(buildDir.resolve("destdir"))
    
        dependsOn("createFile")
    }
    

    See this release notes section for why this behavior was introduced and this explanation to a very similar issue if you want some more background information.