task originalInputs() {
    doLast {
        file('inputs').mkdir()
        file('inputs/1.txt').text = 'Content for file 1.'
        file('inputs/2.txt').text = 'Content for file 2.'
        file('inputs/3.txt').text = 'Content for file 3.'
    }
}

// tag::updated-inputs[]
task updateInputs() {
    doLast {
        file('inputs/1.txt').text = 'Changed content for existing file 1.'
        file('inputs/4.txt').text = 'Content for new file 4.'
    }
}
// end::updated-inputs[]

// tag::removed-input[]
task removeInput() {
    doLast {
        file('inputs/3.txt').delete()
    }
}
// end::removed-input[]

// tag::removed-output[]
task removeOutput() {
    doLast {
        file("$buildDir/outputs/1.txt").delete()
    }
}
// end::removed-output[]

// tag::reverse[]
task incrementalReverse(type: IncrementalReverseTask) {
    inputDir = file('inputs')
    outputDir = file("$buildDir/outputs")
    inputProperty = project.properties['taskInputProperty'] ?: 'original'
}
// end::reverse[]

// tag::incremental-task[]
abstract class IncrementalReverseTask extends DefaultTask {
    @Incremental
    @PathSensitive(PathSensitivity.NAME_ONLY)
    @InputDirectory
    abstract DirectoryProperty getInputDir()

    @OutputDirectory
    abstract DirectoryProperty getOutputDir()

    @Input
    abstract Property<String> getInputProperty()

    @TaskAction
    void execute(InputChanges inputChanges) {
        println(inputChanges.incremental
            ? 'Executing incrementally'
            : 'Executing non-incrementally'
        )

        // tag::process-file-changes[]
        inputChanges.getFileChanges(inputDir).each { change ->
            if (change.fileType == FileType.DIRECTORY) return

            println "${change.changeType}: ${change.normalizedPath}"
            def targetFile = outputDir.file(change.normalizedPath).get().asFile
            if (change.changeType == ChangeType.REMOVED) {
                targetFile.delete()
            } else {
                targetFile.text = change.file.text.reverse()
            }
        }
        // end::process-file-changes[]
    }
}
// end::incremental-task[]
