user1445967
user1445967

Reputation: 1570

Gradle Copy Task up-to-date determination

I'm relatively new to gradle and trying to set up a backup task. I have a few examples, first I'll describe the goal:

I have a number of files in a directory (call it the "data directory"). When the contents of Any File in this data directory are modified, I want to create a new directory in a "backup location" and copy Every File in the data directory into the directory that was just created. The name of the directory created will contain the current date and time. For now, the data directory contains no subdirectories.

I had this working fine when the "data directory" contained one file and all I wanted to do was rename that file to include the date. Example:

task copyDocs(type: Copy) {
    from 'src/main/doc/testfile.html'
    into 'build/target/doc'

    rename { String fileName ->
        def date = new Date();
        date.format("YYYY-MM-dd--HH-mm-ss") + " " + fileName
    }
}

This worked great. I could run the task "copyDocs" as many times as I wanted, but it would only create a new file if I had actually modified the contents of testfile.html. Now, I wanted to expand this so that instead of creating a new file that got renamed, it would create a new directory and copy the source file into it.

task copyDocs(type: Copy) {

    def dateStr = (new Date()).format("YYYY-MM-dd--HH-mm-ss");
    from 'src/main/doc/testfile.html'
    into 'build/target/doc/' + dateStr

}

This did not work so great. While the directory that gets created has the name I wanted, the problem is that Every Time I run the task, it creates a new directory and copies testfile.html into it, regardless of whether this file was modified.

I know this has something to do with the 'task inputs' and such, and I have read the parts of the documentation that describe the initialization phase vs. the configuration phase and so on. What I have not found is anything specific enough to help me understand why the copy task believes it needs to be re-run in the second case but not in the first case.

Simply put, in both cases, the potential output file(s) change every time the task is run as a function of the date/time. The input file(s) Do Not Change in the case of either task. So why does the second task need to be re-run every time, but not the first task? Is there a straightforward way to "debug" gradle so that it explicitly tells me why this is?

Your time and help are greatly appreciated, I am interested in learning more about gradle as it seems like an effective and modern build system!

Upvotes: 2

Views: 1652

Answers (1)

Opal
Opal

Reputation: 84844

When it comes to copy task whether it will be executed is determined by task's inputs and outputs which are set during configuration phase (see here). Since at configuration phase output is different every time:

into 'build/target/doc/' + dateStr

(it depends on seconds, but if you trim to hours, days, months the effect will be the same but rarer) the file is copied every time the task is executed even though it hasn't changed. To fix the problem you need to alter the destination at the execution time which can be done in the following way:

task copyDocs(type: Copy) {

    def dest = 'build/target/doc/'
    from 'src/main/doc/testfile.html'
    into dest
    eachFile { fcp ->
        def dateStr = (new Date()).format("YYYY-MM-dd--HH-mm-ss");
        fcp.path = dest + dateStr
    }
}

This way task will be executed if and only if from input differs.

Upvotes: 3

Related Questions