Generating multiple source files from a template

(Schalk Cronjé) #1

Normally when a applying a filter in a Copy task one would just have like a template file and then copy it whilst substituting using filter or expand. I would want to do something slighlty different.

In a specific code generation use case I have N source files and one template file. The source files actually contain data that becomes one property in the expansion of the template file. Let’s say my template file contains


The source files will contain the content that goes into prop1.

What I got so far in my Copy task is

task generator( type : Copy ) {
  from 'examples', {
   include '*.txt'

 into "${buildDir}/fooDir"

 rename /\.txt$/, '.foo'

 eachFile { fcd ->

I am stuck in the eachFile closure because somehow I need to figure out to open the source file and the template file and then substitute the content of the source file as a property for the template file.

Is it possible to edit a file while it is in-flight as part of a copy?
(Schalk Cronjé) #2

To answer my one question, one can do the following:

eachFile { fcd ->
  String sourceName = fcd.sourceName.replaceAll( /\.txt$/, '')
  String content = fcd.file.text
  fcd.filter {null}
  fcd.filter ConcatFilter, append : project.file('src/templates/my.template')
  fcd.filter ReplaceTokens, tokens : [
    token1 : content,
    token2 : sourceName

It is very importtant that no filters must have been added before String content = fcd.file.text is executed. This is due to Combining eachFile & filter results in failure. The only way of adding filters are within the eachFile and only after extracting the content of the data file.

(Lance Java) #3

I think it’d be easier to invoke project.copy() in a custom task rather than using the Copy task. Eg:

task generator() {
   def inFiles = fileTree('examples').matching {
      include "*.txt"
   def template = file("src/templates/my.template") 
   inputs.files inFiles
   inputs.file template
   outputs.dir "$buildDir/fooDir" 
   doLast {
      inFiles.files.each { inFile ->
         copy { 
            from template 
            filter ... 
            into "$buildDir/fooDir/$"

(Schalk Cronjé) #4

That would work too.