Kaustubh Trivedi
Kaustubh Trivedi

Reputation: 408

Execute a task only if a particular task is run

I want the task setupDB to execute if and only if the task fatJar or slimJar is run.

But after adding gradle.taskGraph.whenReady, commandLine './scripts/configureSQLiteDB.sh' is never running for any task.

Here is my code for the setupDB task:

//download bigg.sqlite if not present
task setupDB {
    gradle.taskGraph.whenReady { graph ->
        if (!project.file("resources/edu/ucsd/sbrg/bigg/bigg.sqlite").exists() 
                && (graph.hasTask(slimJar)|| graph.hasTask(fatJar))) {
            doFirst { 
                exec {
                    println "Setup DB"
                    commandLine './scripts/configureSQLiteDB.sh'
                } 
            }
        } 
    }
}

You can also view the build.gradle file:

apply plugin: "java"

defaultTasks "clean", "fatJar"
// Java versions for compilation and output
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
archivesBaseName = "ModelPolisher"

version = "1.7"

sourceSets {
    main.java.srcDirs = ["src"]
    main.resources.srcDirs = ["resources"]
    main.resources.excludes = ["**/bigg.zip"]
    test.java.srcDirs = ["test"]
}

repositories {
    mavenCentral()
    maven { url "http://www.ebi.ac.uk/~maven/m2repo" }
    maven { url "http://jsbml.sourceforge.net/m2repo/" }
    // local dependencies
    flatDir {
        dirs "lib/de/zbit/SysBio/1390"
    }
}

dependencies {
    compile "org.sbml.jsbml:jsbml:1.4"
    compile "de.zbit:SysBio:1390"
    compile "org.xerial:sqlite-jdbc:3.21.0"
    compile "org.postgresql:postgresql:42.2.2"
    compile "org.biojava:biojava-ontology:5.0.0"
    compile "com.diffplug.matsim:matfilerw:3.0.1"
    compile "com.fasterxml.jackson.core:jackson-core:2.9.9"
    compile "com.fasterxml.jackson.core:jackson-databind:2.9.9"
    testCompile "org.junit.jupiter:junit-jupiter-engine:5.1.0"
}

// config for all jar tasks
tasks.withType(Jar) {
    dependsOn test
    destinationDir = file("$rootDir/target")
    manifest {
        attributes(
                "Version": version,
                "Implementation-Title": "ModelPolisher",
                "Implementation-Version": version,
                "Specification-Vendor": "University of California, San Diego",
                "Specification-Title": "ModelPolisher",
                "Implementation-Vendor-Id": "edu.ucsd.sbrg",
                "Implementation-Vendor": "University of California, San Diego",
                "Main-Class": "edu.ucsd.sbrg.bigg.ModelPolisher"
        )
    }
}

// with dependencies
task fatJar(type: Jar) {
    baseName = project.name + "-fat"
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    with jar
}

//with dependencies, without bigg.sqlite
task lightJar(type: Jar) {
    exclude("**/bigg.sqlite")
    baseName = project.name + "-noDB"
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    with jar
}

// without dependencies and bigg.sqlite
task bareJar(type: Jar) {
    exclude("**/bigg.sqlite")
    baseName = project.name + "-slim-noDB"
    with jar
}

// without dependencies, bigg.sqlite included
// not included in release
task slimJar(type: Jar) {
    baseName = project.name + "-slim"
    with jar
}


// zip lib folder for release
task zipLibs(type: Zip) {
    from "lib"
    into "lib"
    include "**/**"
    archiveName = "lib.zip"
    destinationDir = file("target/")
}

// zip script files for release
task zipScripts(type: Zip) {
    from "scripts"
    into "scripts"
    include "**/**"
    archiveName = "scripts.zip"
    destinationDir = file("target/")
}

// create all three jars for release
task release() {
    dependsOn fatJar
    dependsOn bareJar
    dependsOn lightJar
    dependsOn tasks["zipLibs"]
    dependsOn tasks["zipScripts"]
    // necessary, as order is not defined by dependsOn
    bareJar.mustRunAfter classes
    // slimJar.mustRunAfter bareJar
    lightJar.mustRunAfter slimJar
    fatJar.mustRunAfter lightJar
}

// clean up target directory
clean.doFirst {
    file(".gradle").deleteDir()
    file("target").deleteDir()
}

//download bigg.sqlite if not present
task setupDB {
    gradle.taskGraph.whenReady { graph ->
        if (!project.file("resources/edu/ucsd/sbrg/bigg/bigg.sqlite").exists() 
                && (graph.hasTask(slimJar)|| graph.hasTask(fatJar))) {
            doFirst { 
                exec {
                    println "Setup DB"
                    commandLine './scripts/configureSQLiteDB.sh'
                } 
            }
        } 
    }
}

// bump jar version in travis.yml
if (project.file(".travis.yml").exists()) {
    task bumpVersionTravis() {
        replaceVersion(".travis.yml")
    }
    processResources.dependsOn bumpVersionTravis
}

// bump jar version in ModelPolisher.sh
if (project.file("./scripts/ModelPolisher.sh").exists()) {
    task bumpVersionMP() {
        replaceVersion("./scripts/ModelPolisher.sh")
    }
    processResources.dependsOn bumpVersionMP
}

def replaceVersion(path) {
    ArrayList<String> content = new ArrayList<>()
    File travisFile = new File(path)
    String MPVersion = /ModelPolisher.*\d{1,2}(.\d{1,2}){1,2}.jar/

    travisFile.eachLine {
        line ->
            content.add(line.replaceAll(MPVersion, "ModelPolisher-fat-" +
                    "${version}.jar"))
    }
    BufferedWriter writer = new BufferedWriter(new FileWriter(travisFile))
    content.each {
        line -> writer.writeLine(line)
    }
    writer.close()
}

Upvotes: 0

Views: 1326

Answers (1)

lance-java
lance-java

Reputation: 28099

You seem to have the wrong idea about gradle configuration. You shouldn't be changing task behavior based on inputs. You should be configuring dependencies between tasks and also configuring task inputs/outputs to control the "up-to-date" behaviour.

Eg:

task slimJar(type:Jar) {
   dependsOn 'setupDB' 
   ... 
} 
task fatJar(type:Jar) {
   dependsOn 'setupDB' 
   ... 
} 
task setupDB {
    outputs.upToDateWhen { file("resources/edu/ucsd/sbrg/bigg/bigg.sqlite").exists() } 
    doFirst { 
        println "Setup DB"
        exec {           
            commandLine './scripts/configureSQLiteDB.sh' 
        }
    }
}

The following is also bad practice

if (project.file(".travis.yml").exists()) {
    task bumpVersionTravis() {
        replaceVersion(".travis.yml")
    }
    processResources.dependsOn bumpVersionTravis
}

The available tasks should NOT change based on files in your file system. They should always be there, regardless of your file system. You should instead set the "enabled" flag (or use task outputs) to control if the task executes or is skipped

Eg:

task bumpVersionTravis {
    enabled = project.file(".travis.yml").exists()
    doLast {
       replaceVersion(".travis.yml")
    } 
}
processResources.dependsOn bumpVersionTravis

Upvotes: 1

Related Questions