Replace File in Gradle Build

I am trying to replace a file in my resource folder (src/main/resources) with a new file generated by the Gradle build script. I'm having trouble doing this; the exclusion seems to be remembered, and preventing the addition of my new file.

Here's a short example that illustrates the behavior.

Project Structure:

TestProject
-- src/main/java
---- entry
------ EntryPoint.java
---- run
------ HelloWorldTest.java
-- src/main/resources
---- test.properties // FILE TO REPLACE

test.properties contents in src/main/resources:

Wrong File with extra text to make it obvious which one is being put into the jar based on size

build.gradle:

apply plugin: 'java'

task makeProp {
    def propDir = new File(buildDir, "props")
    ext.propFile = new File(propDir, "test.properties")
    outputs.file propFile

    doLast {
        propDir.mkdirs()
        propFile.createNewFile()
        propFile.withWriter('utf-8') { writer ->
            writer.writeLine 'Right File'
        }
    }
}

jar {
    dependsOn('makeProp')

    if (project.hasProperty('testExclude')) {
        sourceSets {
            exclude('test.properties')
        }
    }

    from (makeProp.propFile) {
        into '/'
    }
}

JAR contents of ./gradlew build (both files included):

Archive:  TestProject.jar
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  08-07-15 14:27   META-INF/
       25  08-07-15 14:27   META-INF/MANIFEST.MF
        0  08-07-15 13:50   run/
      499  08-07-15 13:50   run/HelloWorldTest.class
        0  08-07-15 13:50   entry/
     1413  08-07-15 13:50   entry/EntryPoint.class
       95  08-07-15 14:27   test.properties
       11  08-07-15 14:03   test.properties
 --------                   -------
     2043                   8 files

JAR contents of ./gradlew build -PtestExclude (neither file included):

Archive:  TestProject.jar
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  08-07-15 14:29   META-INF/
       25  08-07-15 14:29   META-INF/MANIFEST.MF
        0  08-07-15 13:50   run/
      499  08-07-15 13:50   run/HelloWorldTest.class
        0  08-07-15 13:50   entry/
     1413  08-07-15 13:50   entry/EntryPoint.class
 --------                   -------
     1937                   6 files

Answers


I have done something very similar and this is what worked for me. The main objective is to make sure the task runs before your jar is created and your files are processed. Try this out.

    // create a properties file add it to folder preprocessing
    task propertiesFile << {
        // 
        description 'Dynamically creates a properties file.'

        // needed for the first pass
        def folder = project.file('src/main/resources');
        if(!folder.exists()){
            folder.mkdirs()
        }

        //write it to a propertiess file
        def props = project.file('src/main/resources/test.properties')
        props.delete()
        props << 'write this to my file!!!!'

    }

    processResources.dependsOn propertiesFile

The thing is that the exclusion patterns for the gradle SourceSet apply to all included paths and not only to specific paths. Therefore in your example above all files named test.properties will be excluded, regardless on their location.

What you can do is to have the default test.properties located somewhere else and make the build copy/generate the relevant version based on the scenario.


The solution I went with in the end was similar to what was posted by Pumphouse, but instead of deleting the file, I renamed it to a temp name, excluded that temp name, and renamed it once I was done (I needed to preserve the file contents and position after the build was complete).

Modified build.gradle:

apply plugin: 'java'

def props = project.file('src/main/resources/test.properties')
def temp = project.file('src/main/resources/temp.properties')

task makeProp {
    ... // Unchanged
}

jar {
    dependsOn('makeProp')

    // Move the properties file to a temp location
    props.renameTo(temp) // This returns a boolean; can perform conditional checks.

    // Exclude the temp file
    if (project.hasProperty('testExclude')) {
        sourceSets {
            exclude('temp.properties')
        }
    }

    // Insert the right prop file
    from (makeProp.propFile) {
        into '/'
    }
}
jar << {
    // Restore the temp file
    temp.renameTo(props)
}

Need Your Help

What are the `exact` differences between .NET dll and a normal dll?

.net dll assemblies

I want to know what are the exact differences between .NET dll and a normal dll.

What's the fastest way to update an owner drawn control?

windows winapi graphics gdi ownerdrawn

I have an owner drawn control which displays data. The data changes over time. I need to find a fast way to continuously update the control.