Postponing destination directory calculation for zip task

I can ‘dynamically’ calculate destination folder for copying files like this:

task copyFromStaticFolderToDynmicLocation() {
    doLast {
        copy {
            from ‘./build/generatedByXXX.war’ {
                include ‘WEB-INF/lib/a.jar’
                include ‘WEB-INF/lib/b.jar’
                include ‘WEB-INF/lib/c.jar’
            }
            into dynamicallyCalculatedDestinationDir()
        }
    }
}

def dynamicallyCalculatedDestinationDir() {
    Directory DirPath = layout.buildDirectory.dir…

    ... some destination folder calculations...

    return files.getFiles().first().absolutePath
}

but how can I do it in case of the ZIP task?

There is a copy method in the Project

WorkResult copy(@DelegatesTo(CopySpec.class) Closure closure);

unfortunately there is not an analogic zip method

Is there for the rebundleZip task any way to postpone destination directory calculation to the execution phase?

task rebundleZip(type: Zip) {
    from('./build/generatedByXXX') {
        into dynamicallyCalculatedDestinationDir() // this evaluation fails during configuration phase
    }
    duplicatesStrategy = "FAIL"
}

Thank you for re-editing the code blocks and my entire post. (I have not seen a preview button )

If you switch to the markdown mode, you have the preview on the right.
If you are not in the markdown mode, it is WYSIWYG. :slight_smile:

1 Like

It’s a bit hard to say due to the left-outs, but what you want is probably something like into(layout.buildDirectory.map { ... }).

Besides that there are some other bad practices you should most probably not do.
For exmaple you do not leverage task-configuration avoidance for those tasks, so configure them for each build invocation even if they are not executed.
Your first task also does not define its inputs and outputs, so it can never be up-to-date.
Also that one should most probably better be a Copy task instead.
And accessing the war by path is most probably also a bad idea as you miss the implicit task dependency on the task that produces that war, instead you should always wire task outputs to task inputs.

And a personal recommendation, I strongly recommend switching to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and amazingly better IDE support if you use a good IDE like IntelliJ IDEA or Android Studio. :slight_smile:

1 Like

Hi Björn,
thank you for your notes. I will study them carefully.

But this statement caught my attention:

Does that mean that the state of the task (up-to-dateness) must be determine during configuration phase? Why?
Is that fundamental Gradle assumption or a side effect?
I understand that determining task state at runtime/execution would require synchronization and a kind of locking the resources’ states for a while … but for the other hand determining states at configuration snapshot moment is not flexible or profitable.
In this approach the “task” is treated not like a procedure to be run on data(given at runtime/execution) but like a procedure closely linked to the specific statically defined data.
Though it limits thinking of tasks as recipes there must be some pros … what are they?

Of course the inputs and outputs are looked at right before the task is executed, not at configuration time, that would not make much sense, because for example other tasks outputs could be inputs for the task.

But that has nothing to do with what I said actually.

No matter when the inputs and outputs are fingerprinted, you do not define any inputs or outputs, so there is nothing that could be fingerprinted, no matter at what time.

1 Like