mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 15:30:38 -05:00
Use Gradle Tooling API
This commit is contained in:
@@ -14,9 +14,17 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":model"))
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation(kotlin("reflect"))
|
||||
implementation("org.gradle:gradle-tooling-api:${gradle.gradleVersion}")
|
||||
implementation("com.github.ajalt:clikt:2.0.0")
|
||||
implementation("org.slf4j:slf4j-api:1.7.26")
|
||||
runtimeOnly("org.slf4j:slf4j-simple:1.7.26")
|
||||
implementation("com.squareup.moshi:moshi:1.8.0")
|
||||
implementation("com.squareup.moshi:moshi-adapters:1.8.0")
|
||||
implementation("com.squareup.moshi:moshi-kotlin:1.8.0")
|
||||
implementation("com.squareup.okio:okio:2.2.2")
|
||||
}
|
||||
|
||||
application {
|
||||
|
||||
16
app/gradle/dependency-locks/compileClasspath.lockfile
Normal file
16
app/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,16 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ajalt:clikt:2.0.0
|
||||
com.squareup.moshi:moshi-adapters:1.8.0
|
||||
com.squareup.moshi:moshi-kotlin:1.8.0
|
||||
com.squareup.moshi:moshi:1.8.0
|
||||
com.squareup.okio:okio:2.2.2
|
||||
org.gradle:gradle-tooling-api:5.4.1
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.31
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.31
|
||||
org.jetbrains:annotations:13.0
|
||||
org.slf4j:slf4j-api:1.7.26
|
||||
17
app/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
17
app/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,17 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ajalt:clikt:2.0.0
|
||||
com.squareup.moshi:moshi-adapters:1.8.0
|
||||
com.squareup.moshi:moshi-kotlin:1.8.0
|
||||
com.squareup.moshi:moshi:1.8.0
|
||||
com.squareup.okio:okio:2.2.2
|
||||
org.gradle:gradle-tooling-api:5.4.1
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.31
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.31
|
||||
org.jetbrains:annotations:13.0
|
||||
org.slf4j:slf4j-api:1.7.26
|
||||
org.slf4j:slf4j-simple:1.7.26
|
||||
16
app/gradle/dependency-locks/testCompileClasspath.lockfile
Normal file
16
app/gradle/dependency-locks/testCompileClasspath.lockfile
Normal file
@@ -0,0 +1,16 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ajalt:clikt:2.0.0
|
||||
com.squareup.moshi:moshi-adapters:1.8.0
|
||||
com.squareup.moshi:moshi-kotlin:1.8.0
|
||||
com.squareup.moshi:moshi:1.8.0
|
||||
com.squareup.okio:okio:2.2.2
|
||||
org.gradle:gradle-tooling-api:5.4.1
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.31
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.31
|
||||
org.jetbrains:annotations:13.0
|
||||
org.slf4j:slf4j-api:1.7.26
|
||||
17
app/gradle/dependency-locks/testRuntimeClasspath.lockfile
Normal file
17
app/gradle/dependency-locks/testRuntimeClasspath.lockfile
Normal file
@@ -0,0 +1,17 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.github.ajalt:clikt:2.0.0
|
||||
com.squareup.moshi:moshi-adapters:1.8.0
|
||||
com.squareup.moshi:moshi-kotlin:1.8.0
|
||||
com.squareup.moshi:moshi:1.8.0
|
||||
com.squareup.okio:okio:2.2.2
|
||||
org.gradle:gradle-tooling-api:5.4.1
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.31
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.3.31
|
||||
org.jetbrains:annotations:13.0
|
||||
org.slf4j:slf4j-api:1.7.26
|
||||
org.slf4j:slf4j-simple:1.7.26
|
||||
@@ -1,45 +1,40 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.tooling.GradleConnector
|
||||
import java.io.File
|
||||
import org.gradle.tooling.ProjectConnection
|
||||
|
||||
class GradleRunner(
|
||||
private val projectDir: File,
|
||||
private val useWrapper: Boolean,
|
||||
private val gradleVersion: String?,
|
||||
private val configurations: List<String>
|
||||
) {
|
||||
companion object {
|
||||
val initScript: String = System.getProperty("org.nixos.gradle2nix.initScript")
|
||||
private val initScript: String = System.getProperty("org.nixos.gradle2nix.initScript")
|
||||
|
||||
fun connect(config: Config): ProjectConnection =
|
||||
GradleConnector.newConnector()
|
||||
.apply {
|
||||
if (config.wrapper) {
|
||||
useBuildDistribution()
|
||||
} else if (config.gradleVersion != null) {
|
||||
useGradleVersion(config.gradleVersion)
|
||||
}
|
||||
}
|
||||
.forProjectDirectory(config.projectDir)
|
||||
.connect()
|
||||
|
||||
fun ProjectConnection.getBuildModel(config: Config, path: String): DefaultBuild {
|
||||
val arguments = mutableListOf(
|
||||
"--init-script=$initScript",
|
||||
"-Dorg.nixos.gradle2nix.configurations='${config.configurations.joinToString(",")}'"
|
||||
)
|
||||
|
||||
if (path.isNotEmpty()) {
|
||||
arguments += "--project-dir=$path"
|
||||
}
|
||||
|
||||
fun runGradle() {
|
||||
GradleConnector.newConnector()
|
||||
.apply {
|
||||
if (useWrapper) {
|
||||
useBuildDistribution()
|
||||
} else if (gradleVersion != null) {
|
||||
useGradleVersion(gradleVersion)
|
||||
}
|
||||
return model(Build::class.java)
|
||||
.withArguments(arguments)
|
||||
.apply {
|
||||
if (config.verbose) {
|
||||
setStandardOutput(System.out)
|
||||
setStandardError(System.err)
|
||||
}
|
||||
.forProjectDirectory(projectDir)
|
||||
.connect()
|
||||
.use { connection ->
|
||||
connection.newBuild()
|
||||
.withArguments("--init-script", initScript)
|
||||
.apply {
|
||||
if (configurations.isNotEmpty()) {
|
||||
withArguments(
|
||||
"-Dorg.nixos.gradle2nix.configurations=${configurations.joinToString(
|
||||
","
|
||||
)}"
|
||||
)
|
||||
}
|
||||
}
|
||||
.forTasks("nixGradleEnv")
|
||||
.setStandardOutput(System.out)
|
||||
.setStandardError(System.err)
|
||||
.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.get()
|
||||
.let { DefaultBuild(it) }
|
||||
}
|
||||
|
||||
19
app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt
Normal file
19
app/src/main/kotlin/org/nixos/gradle2nix/Logger.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import java.io.PrintStream
|
||||
|
||||
class Logger(
|
||||
val out: PrintStream = System.err,
|
||||
val verbose: Boolean) {
|
||||
|
||||
val log: (String) -> Unit = { if (verbose) out.println(it) }
|
||||
val warn: (String) -> Unit = { out.println("Warning: $it")}
|
||||
val error: (String) -> Unit = {
|
||||
out.println("Error: $it")
|
||||
System.exit(1)
|
||||
}
|
||||
|
||||
operator fun component1() = log
|
||||
operator fun component2() = warn
|
||||
operator fun component3() = error
|
||||
}
|
||||
@@ -1,25 +1,103 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.github.ajalt.clikt.completion.CompletionCandidates
|
||||
import com.github.ajalt.clikt.core.CliktCommand
|
||||
import com.github.ajalt.clikt.parameters.arguments.ProcessedArgument
|
||||
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||
import com.github.ajalt.clikt.parameters.arguments.defaultLazy
|
||||
import com.github.ajalt.clikt.parameters.options.flag
|
||||
import com.github.ajalt.clikt.parameters.options.multiple
|
||||
import com.github.ajalt.clikt.parameters.options.option
|
||||
import com.github.ajalt.clikt.parameters.arguments.convert
|
||||
import com.github.ajalt.clikt.parameters.arguments.default
|
||||
import com.github.ajalt.clikt.parameters.options.*
|
||||
import com.github.ajalt.clikt.parameters.types.file
|
||||
import com.squareup.moshi.Moshi
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import java.io.File
|
||||
|
||||
data class Config(
|
||||
val wrapper: Boolean,
|
||||
val gradleVersion: String?,
|
||||
val configurations: List<String>,
|
||||
val projectDir: File,
|
||||
val includes: List<File>,
|
||||
val buildSrc: Boolean,
|
||||
val verbose: Boolean
|
||||
) {
|
||||
val allProjects = listOf(projectDir) + includes
|
||||
}
|
||||
|
||||
class Main : CliktCommand() {
|
||||
val wrapper: Boolean by option(help = "Use the project's gradle wrapper for building").flag()
|
||||
val gradleVersion: String? by option(help = "Use a specific Gradle version")
|
||||
val wrapper: Boolean by option("--gradle-wrapper", "-w",
|
||||
help = "Use the project's gradle wrapper for building")
|
||||
.flag()
|
||||
|
||||
val gradleVersion: String? by option("--gradle-version", "-g",
|
||||
help = "Use a specific Gradle version")
|
||||
|
||||
val configurations: List<String> by option(help = "Project configuration(s)").multiple()
|
||||
|
||||
val projectDir: File by argument(help = "Path to the project root")
|
||||
.projectDir()
|
||||
.default(File("."))
|
||||
|
||||
val outputDir: File by option("--out", "-o",
|
||||
help = "Path to write Nix environment files")
|
||||
.file(fileOkay = false, folderOkay = true)
|
||||
.default(File("."))
|
||||
|
||||
val includes: List<File> by option("--include", "-i",
|
||||
help = "Path to included build(s)",
|
||||
metavar = "DIR")
|
||||
.file(exists = true, fileOkay = false, folderOkay = true, readable = true)
|
||||
.defaultLazy { File(".") }
|
||||
.multiple()
|
||||
.validate { files ->
|
||||
val failures = files.filterNot { it.isProjectRoot() }
|
||||
if (failures.isNotEmpty()) {
|
||||
val message = failures.joinToString("\n ")
|
||||
fail("Included builds are not Gradle projects:\n$message\n" +
|
||||
"Gradle projects must contain a settings.gradle or settings.gradle.kts script.")
|
||||
}
|
||||
}
|
||||
|
||||
val buildSrc: Boolean by option("--enableBuildSrc", help = "Include buildSrc project")
|
||||
.flag("--disableBuildSrc", default = true)
|
||||
|
||||
val verbose: Boolean by option("--verbose", "-v", help = "Enable verbose logging")
|
||||
.flag(default = false)
|
||||
|
||||
override fun run() {
|
||||
GradleRunner(projectDir, wrapper, gradleVersion, configurations).runGradle()
|
||||
val config = Config(wrapper, gradleVersion, configurations, projectDir, includes, buildSrc, verbose)
|
||||
val (log, warn, error) = Logger(verbose = config.verbose)
|
||||
|
||||
val json by lazy { Moshi.Builder().build().adapter(DefaultBuild::class.java).indent(" ") }
|
||||
val out by lazy { outputDir.also { it.mkdirs() }}
|
||||
|
||||
val paths = resolveProjects(config).map { p ->
|
||||
p.toRelativeString(config.projectDir)
|
||||
}
|
||||
|
||||
connect(config).use { connection ->
|
||||
for (project in paths) {
|
||||
log("Resolving project model: ${project.takeIf { it.isNotEmpty() } ?: "root project"}")
|
||||
val build = connection.getBuildModel(config, project)
|
||||
val filename = build.rootProject.name + ".json"
|
||||
val file = out.resolve(filename)
|
||||
file.sink().buffer().use { sink -> json.toJson(sink, build) }
|
||||
log(" --> $file")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) = Main().main(args)
|
||||
fun ProcessedArgument<String, String>.projectDir(): ProcessedArgument<File, File> {
|
||||
return convert(completionCandidates = CompletionCandidates.Path) {
|
||||
File(it).also { file ->
|
||||
if (!file.exists()) fail("Directory \"$file\" does not exist.")
|
||||
if (file.isFile) fail("Directory \"$file\" is a file.")
|
||||
if (!file.canRead()) fail("Directory \"$file\" is not readable.")
|
||||
if (!file.isProjectRoot()) fail("Directory \"$file\" is not a Gradle project.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) = Main().main(args)
|
||||
|
||||
|
||||
17
app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt
Normal file
17
app/src/main/kotlin/org/nixos/gradle2nix/Projects.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import java.io.File
|
||||
|
||||
fun resolveProjects(config: Config) = config.allProjects.run {
|
||||
if (config.buildSrc) {
|
||||
flatMap { listOfNotNull(it, it.findBuildSrc()) }
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
fun File.findBuildSrc(): File? =
|
||||
resolve("buildSrc").takeIf { it.isDirectory }
|
||||
|
||||
fun File.isProjectRoot(): Boolean =
|
||||
isDirectory && (resolve("settings.gradle").isFile || resolve("settings.gradle.kts").isFile)
|
||||
Reference in New Issue
Block a user