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:
12
README.org
Normal file
12
README.org
Normal file
@@ -0,0 +1,12 @@
|
||||
* gradle2nix
|
||||
|
||||
Application and Gradle plugin to generate Nix build scripts for Gradle-based
|
||||
projects.
|
||||
|
||||
** Installation
|
||||
|
||||
|
||||
** Usage
|
||||
|
||||
|
||||
** License
|
||||
@@ -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)
|
||||
@@ -5,7 +5,36 @@ plugins {
|
||||
kotlin("jvm") version embeddedKotlinVersion apply false
|
||||
kotlin("kapt") version embeddedKotlinVersion apply false
|
||||
id("com.github.johnrengelman.shadow") version "5.0.0" apply false
|
||||
id("org.ysb33r.gradletest") version "2.0-rc.4" apply false
|
||||
id("org.ajoberstar.stutter") version "0.5.0" apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
plugins.withType<JavaBasePlugin> {
|
||||
this@allprojects.withConvention(JavaPluginConvention::class) {
|
||||
sourceSets.all {
|
||||
configurations {
|
||||
named(compileClasspathConfigurationName) {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
named(runtimeClasspathConfigurationName) {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("lock") {
|
||||
doFirst {
|
||||
assert(gradle.startParameter.isWriteDependencyLocks)
|
||||
}
|
||||
doLast {
|
||||
sourceSets.all {
|
||||
configurations[compileClasspathConfigurationName].resolve()
|
||||
configurations[runtimeClasspathConfigurationName].resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
15
model/build.gradle.kts
Normal file
15
model/build.gradle.kts
Normal file
@@ -0,0 +1,15 @@
|
||||
plugins {
|
||||
`embedded-kotlin`
|
||||
kotlin("kapt")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = uri("https://repo.gradle.org/gradle/libs-releases") }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("com.squareup.moshi:moshi:1.8.0")
|
||||
compileOnly("com.squareup.okio:okio:2.2.2")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:1.8.0")
|
||||
}
|
||||
10
model/gradle/dependency-locks/compileClasspath.lockfile
Normal file
10
model/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,10 @@
|
||||
# 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.squareup.moshi:moshi:1.8.0
|
||||
com.squareup.okio:okio:2.2.2
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
3
model/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
3
model/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,3 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,8 @@
|
||||
# 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.
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
@@ -0,0 +1,8 @@
|
||||
# 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.
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
117
model/src/main/kotlin/org/nixos/gradle2nix/Impl.kt
Normal file
117
model/src/main/kotlin/org/nixos/gradle2nix/Impl.kt
Normal file
@@ -0,0 +1,117 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import java.io.Serializable
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultBuild(
|
||||
override val gradle: DefaultGradle,
|
||||
override val pluginDependencies: DefaultDependencies,
|
||||
override val rootProject: DefaultProject,
|
||||
override val includedBuilds: List<DefaultIncludedBuild>
|
||||
) : Build, Serializable {
|
||||
constructor(model: Build) : this(
|
||||
DefaultGradle(model.gradle),
|
||||
DefaultDependencies(model.pluginDependencies),
|
||||
DefaultProject(model.rootProject),
|
||||
model.includedBuilds.map { DefaultIncludedBuild(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultIncludedBuild(
|
||||
override val name: String,
|
||||
override val projectDir: String
|
||||
) : IncludedBuild, Serializable {
|
||||
constructor(model: IncludedBuild) : this(
|
||||
model.name,
|
||||
model.projectDir
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultGradle(
|
||||
override val version: String,
|
||||
override val type: String,
|
||||
override val url: String,
|
||||
override val sha256: String,
|
||||
override val nativeVersion: String
|
||||
) : Gradle, Serializable {
|
||||
constructor(model: Gradle) : this(
|
||||
model.version,
|
||||
model.type,
|
||||
model.url,
|
||||
model.sha256,
|
||||
model.nativeVersion
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultProject(
|
||||
override val name: String,
|
||||
override val path: String,
|
||||
override val projectDir: String,
|
||||
override val buildscriptDependencies: DefaultDependencies,
|
||||
override val projectDependencies: DefaultDependencies,
|
||||
override val children: List<DefaultProject>
|
||||
) : Project, Serializable {
|
||||
constructor(model: Project) : this(
|
||||
model.name,
|
||||
model.path,
|
||||
model.projectDir,
|
||||
DefaultDependencies(model.buildscriptDependencies),
|
||||
DefaultDependencies(model.projectDependencies),
|
||||
model.children.map { DefaultProject(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultDependencies(
|
||||
override val repositories: DefaultRepositories,
|
||||
override val artifacts: List<DefaultArtifact>
|
||||
) : Dependencies, Serializable {
|
||||
constructor(model: Dependencies) : this(
|
||||
DefaultRepositories(model.repositories),
|
||||
model.artifacts.map { DefaultArtifact(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultRepositories(
|
||||
override val maven: List<DefaultMaven>
|
||||
) : Repositories, Serializable {
|
||||
constructor(model: Repositories) : this(
|
||||
model.maven.map { DefaultMaven(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultMaven(
|
||||
override val urls: List<String>
|
||||
) : Maven, Serializable {
|
||||
constructor(model: Maven) : this(
|
||||
model.urls.toList()
|
||||
)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class DefaultArtifact(
|
||||
override val groupId: String,
|
||||
override val artifactId: String,
|
||||
override val version: String,
|
||||
override val classifier: String,
|
||||
override val extension: String,
|
||||
override val sha256: String
|
||||
) : Artifact, Comparable<DefaultArtifact>, Serializable {
|
||||
constructor(model: Artifact) : this(
|
||||
model.groupId,
|
||||
model.artifactId,
|
||||
model.version,
|
||||
model.classifier,
|
||||
model.extension,
|
||||
model.sha256
|
||||
)
|
||||
|
||||
override fun toString() = "$groupId:$artifactId:$version:$classifier:$extension"
|
||||
override fun compareTo(other: DefaultArtifact): Int = toString().compareTo(other.toString())
|
||||
}
|
||||
52
model/src/main/kotlin/org/nixos/gradle2nix/Model.kt
Normal file
52
model/src/main/kotlin/org/nixos/gradle2nix/Model.kt
Normal file
@@ -0,0 +1,52 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
interface Build {
|
||||
val gradle: Gradle
|
||||
val pluginDependencies: Dependencies
|
||||
val rootProject: Project
|
||||
val includedBuilds: List<IncludedBuild>
|
||||
}
|
||||
|
||||
interface IncludedBuild {
|
||||
val name: String
|
||||
val projectDir: String
|
||||
}
|
||||
|
||||
interface Gradle {
|
||||
val version: String
|
||||
val type: String
|
||||
val url: String
|
||||
val sha256: String
|
||||
val nativeVersion: String
|
||||
}
|
||||
|
||||
interface Project {
|
||||
val name: String
|
||||
val path: String
|
||||
val projectDir: String
|
||||
val buildscriptDependencies: Dependencies
|
||||
val projectDependencies: Dependencies
|
||||
val children: List<Project>
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
val repositories: Repositories
|
||||
val artifacts: List<Artifact>
|
||||
}
|
||||
|
||||
interface Repositories {
|
||||
val maven: List<Maven>
|
||||
}
|
||||
|
||||
interface Maven {
|
||||
val urls: List<String>
|
||||
}
|
||||
|
||||
interface Artifact {
|
||||
val groupId: String
|
||||
val artifactId: String
|
||||
val version: String
|
||||
val classifier: String
|
||||
val extension: String
|
||||
val sha256: String
|
||||
}
|
||||
12
plugin/.stutter/java8.lock
Normal file
12
plugin/.stutter/java8.lock
Normal file
@@ -0,0 +1,12 @@
|
||||
# DO NOT MODIFY: Generated by Stutter plugin.
|
||||
4.5.1
|
||||
4.6
|
||||
4.7
|
||||
4.8.1
|
||||
4.9
|
||||
4.10.3
|
||||
5.0
|
||||
5.1.1
|
||||
5.2.1
|
||||
5.3.1
|
||||
5.4.1
|
||||
@@ -1,26 +1,43 @@
|
||||
buildscript {
|
||||
configurations.classpath {
|
||||
resolutionStrategy.activateDependencyLocking()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
`java-gradle-plugin`
|
||||
`kotlin-dsl`
|
||||
`maven-publish`
|
||||
kotlin("kapt")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("org.ysb33r.gradletest")
|
||||
id("org.ajoberstar.stutter")
|
||||
}
|
||||
apply {
|
||||
plugin("kotlin")
|
||||
}
|
||||
|
||||
group = "org.nixos"
|
||||
version = "1.0.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url = uri("https://repo.gradle.org/gradle/libs-releases") }
|
||||
}
|
||||
|
||||
dependencyLocking {
|
||||
lockAllConfigurations()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("org.apache.maven:maven-model:3.6.1")
|
||||
implementation("org.apache.maven:maven-model-builder:3.6.1")
|
||||
implementation("com.squareup.okio:okio:2.2.2")
|
||||
implementation("com.squareup.moshi:moshi:1.8.0")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:1.8.0")
|
||||
implementation(project(":model"))
|
||||
compileOnly("org.gradle:gradle-tooling-api:${gradle.gradleVersion}")
|
||||
implementation("org.apache.maven:maven-model:latest.release")
|
||||
implementation("org.apache.maven:maven-model-builder:latest.release")
|
||||
implementation("com.squareup.okio:okio:latest.release")
|
||||
|
||||
compatTestImplementation(embeddedKotlin("stdlib-jdk8"))
|
||||
compatTestImplementation(embeddedKotlin("test-junit5"))
|
||||
compatTestImplementation("org.junit.jupiter:junit-jupiter-api:5.4+")
|
||||
compatTestRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.4+")
|
||||
compatTestImplementation(gradleTestKit())
|
||||
compatTestImplementation(project(":model"))
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
@@ -28,37 +45,46 @@ gradlePlugin {
|
||||
register("gradle2nix") {
|
||||
id = "org.nixos.gradle2nix"
|
||||
displayName = "gradle2nix"
|
||||
description = "Create Nix configurations suitable for reproducible packaging"
|
||||
description = "Expose Gradle tooling model for the gradle2nix tool"
|
||||
implementationClass = "org.nixos.gradle2nix.Gradle2NixPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
gradleTest {
|
||||
versions("5.0", "5.1.1", "5.2.1", "5.3.1", "5.4.1")
|
||||
kotlinDsl = true
|
||||
kotlinDslPluginOptions {
|
||||
experimentalWarning.set(false)
|
||||
}
|
||||
|
||||
stutter {
|
||||
java(8) {
|
||||
compatibleRange("4.5")
|
||||
}
|
||||
|
||||
gradleTestGenerator {
|
||||
dependsOn(shadowJar)
|
||||
doLast {
|
||||
file(gradleTest.get().initScript).bufferedWriter().use { out ->
|
||||
out.appendln("""
|
||||
initscript {
|
||||
dependencies {
|
||||
classpath fileTree('file:${buildDir.absolutePath}/libs'.toURI()) {
|
||||
include '*.jar'
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
out.appendln("""
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
java(11) {
|
||||
compatibleRange("5.0")
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<Test> {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// gradleTestGenerator {
|
||||
// dependsOn(shadowJar)
|
||||
// doLast {
|
||||
// file(gradleTest.get().initScript).bufferedWriter().use { out ->
|
||||
// out.append("""
|
||||
// initscript {
|
||||
// dependencies {
|
||||
// classpath fileTree('file:${buildDir.absolutePath}/libs'.toURI()) {
|
||||
// include '*.jar'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin
|
||||
// """.trimIndent())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 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.
|
||||
org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:1.2.6
|
||||
org.gradle.kotlin:plugins:1.2.6
|
||||
org.jetbrains.intellij.deps:trove4j:1.0.20181211
|
||||
org.jetbrains.kotlin:kotlin-android-extensions:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-build-common:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-compiler-runner:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-daemon-client:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-api:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-native-utils:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-sam-with-receiver:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-script-runtime:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
@@ -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.
|
||||
org.apiguardian:apiguardian-api:1.0.0
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.21
|
||||
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.21
|
||||
org.jetbrains.kotlin:kotlin-test-annotations-common:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test-common:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test-junit5:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test:1.3.21
|
||||
org.jetbrains:annotations:13.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.4.2
|
||||
org.junit.platform:junit-platform-commons:1.4.2
|
||||
org.opentest4j:opentest4j:1.1.1
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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.
|
||||
org.apiguardian:apiguardian-api:1.0.0
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.21
|
||||
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.21
|
||||
org.jetbrains.kotlin:kotlin-test-annotations-common:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test-common:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test-junit5:1.3.21
|
||||
org.jetbrains.kotlin:kotlin-test:1.3.21
|
||||
org.jetbrains:annotations:13.0
|
||||
org.junit.jupiter:junit-jupiter-api:5.4.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.4.2
|
||||
org.junit.platform:junit-platform-commons:1.4.2
|
||||
org.junit.platform:junit-platform-engine:1.4.2
|
||||
org.opentest4j:opentest4j:1.1.1
|
||||
18
plugin/gradle/dependency-locks/compileClasspath.lockfile
Normal file
18
plugin/gradle/dependency-locks/compileClasspath.lockfile
Normal file
@@ -0,0 +1,18 @@
|
||||
# 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.squareup.okio:okio:2.2.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.maven:maven-artifact:3.6.1
|
||||
org.apache.maven:maven-builder-support:3.6.1
|
||||
org.apache.maven:maven-model-builder:3.6.1
|
||||
org.apache.maven:maven-model:3.6.1
|
||||
org.codehaus.plexus:plexus-component-annotations:1.7.1
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.0
|
||||
org.gradle:gradle-tooling-api:5.4.1
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
15
plugin/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
15
plugin/gradle/dependency-locks/runtimeClasspath.lockfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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.squareup.okio:okio:2.2.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.maven:maven-artifact:3.6.1
|
||||
org.apache.maven:maven-builder-support:3.6.1
|
||||
org.apache.maven:maven-model-builder:3.6.1
|
||||
org.apache.maven:maven-model:3.6.1
|
||||
org.codehaus.plexus:plexus-component-annotations:1.7.1
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.0
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.60
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.2.60
|
||||
org.jetbrains:annotations:13.0
|
||||
17
plugin/gradle/dependency-locks/testCompileClasspath.lockfile
Normal file
17
plugin/gradle/dependency-locks/testCompileClasspath.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.squareup.okio:okio:2.2.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.maven:maven-artifact:3.6.1
|
||||
org.apache.maven:maven-builder-support:3.6.1
|
||||
org.apache.maven:maven-model-builder:3.6.1
|
||||
org.apache.maven:maven-model:3.6.1
|
||||
org.codehaus.plexus:plexus-component-annotations:1.7.1
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.0
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
17
plugin/gradle/dependency-locks/testRuntimeClasspath.lockfile
Normal file
17
plugin/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.squareup.okio:okio:2.2.2
|
||||
org.apache.commons:commons-lang3:3.8.1
|
||||
org.apache.maven:maven-artifact:3.6.1
|
||||
org.apache.maven:maven-builder-support:3.6.1
|
||||
org.apache.maven:maven-model-builder:3.6.1
|
||||
org.apache.maven:maven-model:3.6.1
|
||||
org.codehaus.plexus:plexus-component-annotations:1.7.1
|
||||
org.codehaus.plexus:plexus-interpolation:1.25
|
||||
org.codehaus.plexus:plexus-utils:3.2.0
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.3.21
|
||||
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.21
|
||||
org.jetbrains:annotations:13.0
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.internal.classpath.DefaultClassPath
|
||||
import org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading
|
||||
import org.gradle.tooling.GradleConnector
|
||||
import org.gradle.tooling.internal.consumer.DefaultModelBuilder
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.io.File
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
class BasicTest {
|
||||
companion object {
|
||||
@JvmStatic @TempDir lateinit var projectDir: File
|
||||
|
||||
val initScript: File by lazy {
|
||||
projectDir.resolve("init.gradle").also {
|
||||
it.writer().use { out ->
|
||||
// val classpath = DefaultClassPath.of(PluginUnderTestMetadataReading.readImplementationClasspath())
|
||||
// .asFiles.joinToString(prefix = "'", postfix = "'")
|
||||
// out.appendln("""
|
||||
// initscript {
|
||||
// dependencies {
|
||||
// classpath files($classpath)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin
|
||||
// """.trimIndent())
|
||||
out.appendln("apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `builds basic project with kotlin dsl`() {
|
||||
projectDir.resolve("build.gradle.kts").writeText("""
|
||||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.squareup.okio:okio:2.2.2")
|
||||
implementation("com.squareup.moshi:moshi:1.8.0")
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
val connection = GradleConnector.newConnector()
|
||||
.useGradleVersion(System.getProperty("compat.gradle.version"))
|
||||
.forProjectDirectory(projectDir)
|
||||
.connect()
|
||||
|
||||
val model = (connection.model(Build::class.java) as DefaultModelBuilder<Build>)
|
||||
.withArguments(
|
||||
"--init-script=$initScript",
|
||||
"--stacktrace"
|
||||
)
|
||||
.withInjectedClassPath(DefaultClassPath.of(PluginUnderTestMetadataReading.readImplementationClasspath()))
|
||||
.setStandardOutput(System.out)
|
||||
.setStandardError(System.out)
|
||||
.get()
|
||||
|
||||
assertEquals(model.gradle.version, System.getProperty("compat.gradle.version"))
|
||||
|
||||
with(model.rootProject.projectDependencies) {
|
||||
with(repositories) {
|
||||
assertEquals(1, maven.size)
|
||||
assertEquals(maven[0].urls[0], "https://jcenter.bintray.com/")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,27 +15,28 @@ import org.gradle.api.artifacts.component.ModuleComponentIdentifier
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.maven.MavenModule
|
||||
import org.gradle.maven.MavenPomArtifact
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.net.URI
|
||||
|
||||
internal class Resolver(
|
||||
internal class DependencyResolver(
|
||||
private val configurations: ConfigurationContainer,
|
||||
private val dependencies: DependencyHandler,
|
||||
private val logger: Logger
|
||||
private val logger: Logger = Logging.getLogger(DependencyResolver::class.simpleName)
|
||||
) {
|
||||
private val mavenPomResolver = MavenPomResolver(configurations, dependencies)
|
||||
|
||||
fun resolveDependencies(configuration: Configuration): Set<Artifact> {
|
||||
fun resolveDependencies(configuration: Configuration): Set<DefaultArtifact> {
|
||||
if (!configuration.isCanBeResolved) {
|
||||
logger.warn("Cannot resolve configuration ${configuration.name}; ignoring.")
|
||||
return emptySet()
|
||||
}
|
||||
return configuration.resolvedConfiguration.resolvedArtifacts.mapTo(sortedSetOf()) {
|
||||
with (it) {
|
||||
Artifact(
|
||||
DefaultArtifact(
|
||||
groupId = moduleVersion.id.group,
|
||||
artifactId = moduleVersion.id.name,
|
||||
version = moduleVersion.id.version,
|
||||
@@ -50,13 +51,13 @@ internal class Resolver(
|
||||
fun resolveDependencies(
|
||||
dependencies: Collection<Dependency>,
|
||||
includeTransitive: Boolean = false
|
||||
): Set<Artifact> {
|
||||
): Set<DefaultArtifact> {
|
||||
val configuration = configurations.detachedConfiguration(*(dependencies.toTypedArray()))
|
||||
configuration.isTransitive = includeTransitive
|
||||
return resolveDependencies(configuration)
|
||||
}
|
||||
|
||||
fun resolvePoms(configuration: Configuration): Set<Artifact> {
|
||||
fun resolvePoms(configuration: Configuration): Set<DefaultArtifact> {
|
||||
return dependencies.createArtifactResolutionQuery()
|
||||
.forComponents(configuration.incoming.resolutionResult.allComponents.map { it.id })
|
||||
.withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java)
|
||||
@@ -73,7 +74,7 @@ internal class Resolver(
|
||||
}
|
||||
}
|
||||
.flatMapTo(sortedSetOf()) { (id, artifact) ->
|
||||
sequenceOf(Artifact(
|
||||
sequenceOf(DefaultArtifact(
|
||||
groupId = id.group,
|
||||
artifactId = id.module,
|
||||
version = id.version,
|
||||
@@ -87,7 +88,7 @@ internal class Resolver(
|
||||
fun resolvePoms(
|
||||
dependencies: Collection<Dependency>,
|
||||
includeTransitive: Boolean = false
|
||||
): Set<Artifact> {
|
||||
): Set<DefaultArtifact> {
|
||||
val configuration = configurations.detachedConfiguration(*(dependencies.toTypedArray()))
|
||||
configuration.isTransitive = includeTransitive
|
||||
return resolvePoms(configuration)
|
||||
@@ -99,10 +100,10 @@ private class MavenPomResolver(
|
||||
private val dependencies: DependencyHandler
|
||||
) : ModelResolver {
|
||||
private val modelBuilder = DefaultModelBuilderFactory().newInstance()
|
||||
private val resolvedDependencies = mutableSetOf<Artifact>()
|
||||
private val resolvedDependencies = mutableSetOf<DefaultArtifact>()
|
||||
|
||||
@Synchronized
|
||||
fun resolve(pom: File): Set<Artifact> {
|
||||
fun resolve(pom: File): Set<DefaultArtifact> {
|
||||
resolvedDependencies.clear()
|
||||
modelBuilder.build(
|
||||
DefaultModelBuildingRequest()
|
||||
@@ -124,7 +125,7 @@ private class MavenPomResolver(
|
||||
val file = configurations
|
||||
.detachedConfiguration(dependencies.create("$groupId:$artifactId:$version@pom"))
|
||||
.singleFile
|
||||
resolvedDependencies.add(Artifact(
|
||||
resolvedDependencies.add(DefaultArtifact(
|
||||
groupId = groupId,
|
||||
artifactId = artifactId,
|
||||
version = version,
|
||||
@@ -1,21 +1,25 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
import org.gradle.api.invocation.Gradle
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.wrapper.Wrapper
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.newInstance
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.gradle.plugin.management.PluginRequest
|
||||
import java.io.File
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilder
|
||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import org.nixos.gradle2nix.Gradle as NixGradle
|
||||
import org.nixos.gradle2nix.Project as NixProject
|
||||
|
||||
@Suppress("unused")
|
||||
open class Gradle2NixPlugin : Plugin<Gradle> {
|
||||
override fun apply(gradle: Gradle) {
|
||||
val configurationNames: List<String> =
|
||||
@@ -24,52 +28,8 @@ open class Gradle2NixPlugin : Plugin<Gradle> {
|
||||
val pluginRequests = collectPlugins(gradle)
|
||||
|
||||
gradle.projectsLoaded {
|
||||
val extension = rootProject.extensions.create<Gradle2NixExtension>(
|
||||
"gradle2nix",
|
||||
rootProject,
|
||||
configurationNames
|
||||
)
|
||||
|
||||
val gradleEnv = rootProject.tasks.register("nixGradleEnv", NixGradleEnv::class) {
|
||||
outputDir.set(extension.outputDir)
|
||||
}
|
||||
|
||||
val buildSrcDir = rootProject.projectDir.resolve("buildSrc")
|
||||
if (buildSrcDir.exists() && buildSrcDir.isDirectory) {
|
||||
val buildSrcEnv =
|
||||
rootProject.tasks.register("nixBuildSrcEnv", NixBuildSrcEnv::class) {
|
||||
dir = buildSrcDir
|
||||
val buildFile = buildSrcDir.listFiles().let { files ->
|
||||
files.find { it.name == "build.gradle.kts" } ?:
|
||||
files.find { it.name == "build.gradle" }
|
||||
}
|
||||
if (buildFile != null) this.buildFile = buildFile
|
||||
}
|
||||
gradleEnv.configure {
|
||||
dependsOn(buildSrcEnv)
|
||||
}
|
||||
}
|
||||
|
||||
val pluginEnv =
|
||||
rootProject.tasks.register("nixPluginEnv", NixPluginEnv::class, pluginRequests)
|
||||
gradleEnv.configure {
|
||||
inputEnvs.from(pluginEnv)
|
||||
}
|
||||
|
||||
allprojects {
|
||||
val buildscriptEnv = tasks.register("nixBuildscriptEnv", NixBuildscriptEnv::class) {
|
||||
pluginEnvFile.set(pluginEnv.flatMap { it.outputFile })
|
||||
}
|
||||
val projectEnv = tasks.register("nixProjectEnv", NixProjectEnv::class) {
|
||||
configurations.addAll(extension.configurations)
|
||||
}
|
||||
gradleEnv.configure {
|
||||
inputEnvs.from(buildscriptEnv)
|
||||
inputEnvs.from(projectEnv)
|
||||
}
|
||||
}
|
||||
|
||||
resolveGradleDist(gradle, extension, gradleEnv)
|
||||
rootProject.serviceOf<ToolingModelBuilderRegistry>()
|
||||
.register(NixToolingModelBuilder(configurationNames, pluginRequests))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,54 +44,98 @@ open class Gradle2NixPlugin : Plugin<Gradle> {
|
||||
}
|
||||
return pluginRequests
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveGradleDist(
|
||||
gradle: Gradle,
|
||||
extension: Gradle2NixExtension,
|
||||
gradleEnv: TaskProvider<NixGradleEnv>
|
||||
) {
|
||||
gradle.projectsEvaluated {
|
||||
val gradleDist = rootProject.tasks.named("wrapper", Wrapper::class).map {
|
||||
GradleDist(
|
||||
version = it.gradleVersion,
|
||||
type = it.distributionType.name.toLowerCase(Locale.US),
|
||||
url = it.distributionUrl,
|
||||
sha256 = it.distributionSha256Sum ?: fetchDistSha256(it.distributionUrl),
|
||||
nativeVersion = gradle.gradleHomeDir?.resolve("lib")?.listFiles()
|
||||
?.firstOrNull { f -> f.name.matches(nativePlatformJarRegex) }?.let { nf ->
|
||||
nativePlatformJarRegex.find(nf.name)?.groupValues?.get(1)
|
||||
}
|
||||
?: throw IllegalStateException("""
|
||||
private class NixToolingModelBuilder(
|
||||
private val explicitConfigurations: List<String>,
|
||||
private val pluginRequests: List<PluginRequest>
|
||||
) : ToolingModelBuilder {
|
||||
override fun canBuild(modelName: String): Boolean {
|
||||
return modelName == "org.nixos.gradle2nix.Build"
|
||||
}
|
||||
|
||||
override fun buildAll(modelName: String, project: Project): Build = project.run {
|
||||
val plugins = buildPlugins(pluginRequests)
|
||||
DefaultBuild(
|
||||
gradle = buildGradle(),
|
||||
pluginDependencies = plugins,
|
||||
rootProject = buildProject(explicitConfigurations, plugins),
|
||||
includedBuilds = includedBuilds()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.buildGradle(): DefaultGradle =
|
||||
with(tasks.named<Wrapper>("wrapper").get()) {
|
||||
DefaultGradle(
|
||||
version = gradleVersion,
|
||||
type = distributionType.name.toLowerCase(Locale.US),
|
||||
url = distributionUrl,
|
||||
sha256 = distributionSha256Sum ?: fetchDistSha256(distributionUrl),
|
||||
nativeVersion = gradle.gradleHomeDir?.resolve("lib")?.listFiles()
|
||||
?.firstOrNull { f -> nativePlatformJarRegex matches f.name }?.let { nf ->
|
||||
nativePlatformJarRegex.find(nf.name)?.groupValues?.get(1)
|
||||
}
|
||||
?: throw IllegalStateException(
|
||||
"""
|
||||
Failed to find native-platform jar in ${gradle.gradleHomeDir}.
|
||||
|
||||
Ask Tad to fix this.
|
||||
""".trimIndent())
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
val gradleDistTask =
|
||||
gradle.rootProject.tasks.register("nixGradleDist", NixGradleDist::class) {
|
||||
this.gradleDist.set(gradleDist)
|
||||
outputDir.set(extension.outputDir)
|
||||
}
|
||||
gradleEnv.configure {
|
||||
dependsOn(gradleDistTask)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun Project.buildPlugins(pluginRequests: List<PluginRequest>): DefaultDependencies =
|
||||
with(objects.newInstance<PluginResolver>(pluginRequests)) {
|
||||
DefaultDependencies(repositories.repositories(), artifacts())
|
||||
}
|
||||
|
||||
private fun Project.includedBuilds(): List<DefaultIncludedBuild> =
|
||||
gradle.includedBuilds.map {
|
||||
DefaultIncludedBuild(it.name, it.projectDir.toRelativeString(project.projectDir))
|
||||
}
|
||||
|
||||
private fun Project.buildProject(
|
||||
explicitConfigurations: List<String>,
|
||||
plugins: DefaultDependencies
|
||||
): DefaultProject =
|
||||
DefaultProject(
|
||||
name = name,
|
||||
path = path,
|
||||
projectDir = projectDir.toRelativeString(rootProject.projectDir),
|
||||
buildscriptDependencies = buildscriptDependencies(plugins),
|
||||
projectDependencies = projectDependencies(explicitConfigurations),
|
||||
children = childProjects.values.map { it.buildProject(explicitConfigurations, plugins) }
|
||||
)
|
||||
|
||||
private fun Project.buildscriptDependencies(plugins: DefaultDependencies): DefaultDependencies =
|
||||
with(DependencyResolver(buildscript.configurations, buildscript.dependencies)) {
|
||||
DefaultDependencies(
|
||||
repositories = buildscript.repositories.repositories(),
|
||||
artifacts = buildscript.configurations
|
||||
.filter { it.isCanBeResolved }
|
||||
.flatMap { resolveDependencies(it) + resolvePoms(it) }
|
||||
.minus(plugins.artifacts)
|
||||
.distinct()
|
||||
)
|
||||
}
|
||||
|
||||
private fun Project.projectDependencies(explicitConfigurations: List<String>): DefaultDependencies =
|
||||
with(DependencyResolver(configurations, dependencies)) {
|
||||
val toResolve = if (explicitConfigurations.isEmpty()) {
|
||||
configurations.filter { it.isCanBeResolved }
|
||||
} else {
|
||||
configurations.filter { it.name in explicitConfigurations }
|
||||
}
|
||||
|
||||
DefaultDependencies(
|
||||
repositories = repositories.repositories(),
|
||||
artifacts = toResolve.flatMap { resolveDependencies(it) + resolvePoms(it) }
|
||||
.sorted()
|
||||
.distinct()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal val pluginJar by lazy {
|
||||
File(Gradle2NixPlugin::class.java.protectionDomain.codeSource.location.toURI()).absoluteFile
|
||||
}
|
||||
|
||||
internal val moshi by lazy { Moshi.Builder().build() }
|
||||
|
||||
open class Gradle2NixExtension(project: Project, defaultConfigurations: List<String>) {
|
||||
var outputDir: File = project.projectDir.resolve("gradle/nix")
|
||||
var configurations: MutableList<String> = mutableListOf<String>().apply {
|
||||
addAll(defaultConfigurations)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchDistSha256(url: String): String {
|
||||
return URL("$url.sha256").openConnection().run {
|
||||
@@ -142,5 +146,12 @@ private fun fetchDistSha256(url: String): String {
|
||||
}
|
||||
}
|
||||
|
||||
private val nativePlatformJarRegex = Regex("""native-platform-(\d\.\d+)\.jar""")
|
||||
private val nativePlatformJarRegex = Regex("""native-platform-([\d.]+)\.jar""")
|
||||
|
||||
internal fun RepositoryHandler.repositories() = DefaultRepositories(
|
||||
maven = filterIsInstance<MavenArtifactRepository>()
|
||||
.filterNot { it.name == "Embedded Kotlin Repository" }
|
||||
.map { repo ->
|
||||
DefaultMaven(listOf(repo.url.toString()) + repo.artifactUrls.map { it.toString() })
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
private fun versionAtLeast(version: String): Boolean =
|
||||
GradleVersion.current() >= GradleVersion.version(version)
|
||||
|
||||
internal fun <T> Property<T>.conventionCompat(value: T): Property<T> {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(value)
|
||||
} else {
|
||||
apply { set(value) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> Property<T>.conventionCompat(valueProvider: Provider<out T>): Property<T> {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(valueProvider)
|
||||
} else {
|
||||
apply { set(valueProvider) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun DirectoryProperty.conventionCompat(
|
||||
value: Directory
|
||||
): DirectoryProperty {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(value)
|
||||
} else {
|
||||
apply { set(value) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun DirectoryProperty.conventionCompat(
|
||||
valueProvider: Provider<out Directory>
|
||||
): DirectoryProperty {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(valueProvider)
|
||||
} else {
|
||||
apply { set(valueProvider) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> ListProperty<T>.conventionCompat(
|
||||
elements: Iterable<T>
|
||||
): ListProperty<T> {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(elements)
|
||||
} else {
|
||||
apply { set(elements) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T> ListProperty<T>.conventionCompat(
|
||||
provider: Provider<out Iterable<T>>
|
||||
): ListProperty<T> {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(provider)
|
||||
} else {
|
||||
apply { set(provider) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal fun RegularFileProperty.conventionCompat(
|
||||
value: RegularFile
|
||||
): RegularFileProperty {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(value)
|
||||
} else {
|
||||
apply { set(value) }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RegularFileProperty.conventionCompat(
|
||||
valueProvider: Provider<out RegularFile>
|
||||
): RegularFileProperty {
|
||||
return if (versionAtLeast("5.1")) {
|
||||
convention(valueProvider)
|
||||
} else {
|
||||
apply { set(valueProvider) }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
internal fun Project.directoryPropertyCompat(): DirectoryProperty {
|
||||
return if (versionAtLeast("5.0")) {
|
||||
objects.directoryProperty()
|
||||
} else {
|
||||
layout.directoryProperty()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
internal fun Project.filePropertyCompat(): RegularFileProperty {
|
||||
return if (versionAtLeast("5.0")) {
|
||||
objects.fileProperty()
|
||||
} else {
|
||||
layout.fileProperty()
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.api.tasks.GradleBuild
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import java.io.File
|
||||
|
||||
open class NixBuildSrcEnv : GradleBuild() {
|
||||
init {
|
||||
configure {
|
||||
tasks = listOf("nixGradleEnv")
|
||||
startParameter.addInitScript(writeInitScriptTo(dir.resolve("build/nix/init.gradle")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeInitScriptTo(dest: File): File {
|
||||
dest.parentFile.mkdirs()
|
||||
dest.writeText("""
|
||||
initscript {
|
||||
dependencies {
|
||||
classpath files("$pluginJar")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin
|
||||
""".trimIndent())
|
||||
return dest
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import java.net.URI
|
||||
|
||||
open class NixBuildscriptEnv : NixEnv() {
|
||||
@InputFile
|
||||
val pluginEnvFile = project.filePropertyCompat()
|
||||
|
||||
private val pluginEnv: BuildEnv by lazy {
|
||||
pluginEnvFile.get().asFile.source().buffer().use { src ->
|
||||
moshi.adapter(BuildEnv::class.java).fromJson(src)
|
||||
?: throw IllegalStateException(
|
||||
"Cannot load plugin env from ${pluginEnvFile.get().asFile.path}")
|
||||
}
|
||||
}
|
||||
|
||||
private val resolver by lazy {
|
||||
Resolver(project.buildscript.configurations,
|
||||
project.buildscript.dependencies,
|
||||
logger
|
||||
)
|
||||
}
|
||||
|
||||
override fun environment(): String = "buildscript"
|
||||
|
||||
override fun repositories(): List<String> =
|
||||
project.buildscript.repositories.flatMap { it.repositoryUrls() }.map(URI::toString)
|
||||
|
||||
override fun artifacts(): List<Artifact> {
|
||||
return project.buildscript.configurations
|
||||
.filter { it.isCanBeResolved }
|
||||
.flatMap { resolver.resolveDependencies(it) + resolver.resolvePoms(it) }
|
||||
.minus(pluginEnv.artifacts)
|
||||
.sorted()
|
||||
.distinct()
|
||||
}
|
||||
|
||||
override fun filename(): String = "buildscript.json"
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.repositories.ArtifactRepository
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.net.URI
|
||||
|
||||
abstract class NixEnv: DefaultTask() {
|
||||
abstract fun environment(): String
|
||||
abstract fun repositories(): List<String>
|
||||
abstract fun artifacts(): List<Artifact>
|
||||
abstract fun filename(): String
|
||||
|
||||
@Internal
|
||||
val outputDir = project.directoryPropertyCompat()
|
||||
.conventionCompat(project.layout.buildDirectory.dir("nix"))
|
||||
|
||||
@OutputFile
|
||||
val outputFile = project.filePropertyCompat()
|
||||
.conventionCompat(outputDir.map { it.file(filename()) })
|
||||
|
||||
@TaskAction
|
||||
open fun run() {
|
||||
val outFile = outputFile.get().asFile
|
||||
outFile.parentFile.mkdirs()
|
||||
|
||||
val buildEnv = BuildEnv(project.path, environment(), repositories(), artifacts())
|
||||
outFile.sink().buffer().use { out ->
|
||||
moshi.adapter(BuildEnv::class.java)
|
||||
.indent(" ")
|
||||
.toJson(out, buildEnv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class BuildEnv(
|
||||
val path: String,
|
||||
val env: String,
|
||||
val repositories: List<String>,
|
||||
val artifacts: List<Artifact>
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Artifact(
|
||||
val groupId: String,
|
||||
val artifactId: String,
|
||||
val version: String,
|
||||
val classifier: String,
|
||||
val extension: String,
|
||||
val sha256: String
|
||||
) : Comparable<Artifact> {
|
||||
override fun toString() = "$groupId:$artifactId:$version:$classifier:$extension"
|
||||
|
||||
override fun compareTo(other: Artifact): Int {
|
||||
return toString().compareTo(other.toString())
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ArtifactRepository.repositoryUrls(): Set<URI> {
|
||||
return when (this) {
|
||||
is MavenArtifactRepository -> setOf(url) + artifactUrls
|
||||
else -> emptySet()
|
||||
}.filterNotTo(mutableSetOf()) { it.scheme == "file" }
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import java.io.Serializable
|
||||
|
||||
open class NixGradleDist : DefaultTask() {
|
||||
@Input
|
||||
internal val gradleDist = project.objects.property<GradleDist>()
|
||||
|
||||
@OutputDirectory
|
||||
val outputDir = project.directoryPropertyCompat()
|
||||
|
||||
@OutputFile
|
||||
val outputFile = project.filePropertyCompat()
|
||||
.conventionCompat(outputDir.file("gradle-dist.json"))
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
if (gradleDist.isPresent) {
|
||||
outputFile.asFile.get().also { it.parentFile.mkdirs() }.sink().buffer().use { out ->
|
||||
moshi.adapter(GradleDist::class.java)
|
||||
.indent(" ")
|
||||
.toJson(out, gradleDist.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
internal data class GradleDist(
|
||||
val version: String,
|
||||
val type: String,
|
||||
val url: String,
|
||||
val sha256: String,
|
||||
val nativeVersion: String
|
||||
) : Serializable
|
||||
@@ -1,58 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.JsonWriter
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.source
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import javax.inject.Inject
|
||||
|
||||
open class NixGradleEnv @Inject constructor(
|
||||
objects: ObjectFactory
|
||||
) : DefaultTask() {
|
||||
|
||||
@InputFiles
|
||||
val inputEnvs = project.files()
|
||||
|
||||
@Internal
|
||||
val outputDir = objects.directoryProperty()
|
||||
|
||||
@OutputFile
|
||||
val outputFile = objects.fileProperty()
|
||||
.conventionCompat(outputDir.file("gradle-env.json"))
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val envsByPath = inputEnvs.map { file ->
|
||||
file.source().buffer().use {
|
||||
moshi.adapter(BuildEnv::class.java).fromJson(it)
|
||||
?: throw IllegalStateException(
|
||||
"Failed to load build env from ${file.path}."
|
||||
)
|
||||
}
|
||||
}.groupBy(BuildEnv::path)
|
||||
|
||||
val outFile = outputFile.get().asFile.also { it.parentFile.mkdirs() }
|
||||
|
||||
JsonWriter.of(outFile.sink().buffer()).use { writer ->
|
||||
val adapter = moshi.adapter(BuildEnv::class.java).indent(" ")
|
||||
writer.indent = " "
|
||||
writer.beginObject()
|
||||
for ((path, envs) in envsByPath) {
|
||||
writer.name(path)
|
||||
writer.beginObject()
|
||||
for (env in envs) {
|
||||
writer.name(env.env)
|
||||
adapter.toJson(writer, env)
|
||||
}
|
||||
writer.endObject()
|
||||
}
|
||||
writer.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.kotlin.dsl.listProperty
|
||||
import java.net.URI
|
||||
|
||||
open class NixProjectEnv : NixEnv() {
|
||||
@Input @Optional
|
||||
val configurations = project.objects.listProperty<String>().conventionCompat(emptyList())
|
||||
|
||||
private val resolveConfigurations by lazy {
|
||||
val configs = configurations.get()
|
||||
if (configs.isEmpty()) {
|
||||
project.configurations.filter { it.isCanBeResolved }
|
||||
} else {
|
||||
project.configurations.filter { it.name in configs }
|
||||
}
|
||||
}
|
||||
|
||||
private val resolver by lazy {
|
||||
Resolver(project.configurations,
|
||||
project.dependencies,
|
||||
logger
|
||||
)
|
||||
}
|
||||
|
||||
override fun environment(): String = "project"
|
||||
|
||||
override fun repositories(): List<String> =
|
||||
project.repositories.flatMap { it.repositoryUrls() }.map(URI::toString)
|
||||
|
||||
override fun artifacts(): List<Artifact> {
|
||||
return resolveConfigurations
|
||||
.flatMap { resolver.resolveDependencies(it) + resolver.resolvePoms(it) }
|
||||
.sorted()
|
||||
.distinct()
|
||||
}
|
||||
|
||||
override fun filename(): String = "project.json"
|
||||
}
|
||||
@@ -11,15 +11,14 @@ import org.gradle.plugin.use.resolve.internal.ArtifactRepositoriesPluginResolver
|
||||
import org.gradle.plugin.use.resolve.internal.PluginResolution
|
||||
import org.gradle.plugin.use.resolve.internal.PluginResolutionResult
|
||||
import org.gradle.plugin.use.resolve.internal.PluginResolveContext
|
||||
import java.net.URI
|
||||
import javax.inject.Inject
|
||||
|
||||
open class NixPluginEnv @Inject constructor(
|
||||
open class PluginResolver @Inject constructor(
|
||||
private val pluginDependencyResolutionServices: PluginDependencyResolutionServices,
|
||||
versionSelectorScheme: VersionSelectorScheme,
|
||||
private val pluginRequests: Collection<PluginRequest>
|
||||
) : NixEnv() {
|
||||
private val repositories by lazy {
|
||||
) {
|
||||
val repositories by lazy {
|
||||
pluginDependencyResolutionServices.resolveRepositoryHandler
|
||||
}
|
||||
|
||||
@@ -29,10 +28,9 @@ open class NixPluginEnv @Inject constructor(
|
||||
)
|
||||
|
||||
private val resolver by lazy {
|
||||
Resolver(
|
||||
DependencyResolver(
|
||||
pluginDependencyResolutionServices.configurationContainer,
|
||||
pluginDependencyResolutionServices.dependencyHandler,
|
||||
logger
|
||||
pluginDependencyResolutionServices.dependencyHandler
|
||||
)
|
||||
}
|
||||
|
||||
@@ -50,61 +48,53 @@ open class NixPluginEnv @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun environment(): String = "plugins"
|
||||
|
||||
override fun repositories(): List<String> {
|
||||
return repositories.flatMap { it.repositoryUrls() }.map(URI::toString) +
|
||||
pluginContext.repositories.toList()
|
||||
}
|
||||
|
||||
override fun artifacts(): List<Artifact> {
|
||||
fun artifacts(): List<DefaultArtifact> {
|
||||
return (resolver.resolveDependencies(pluginContext.dependencies, true) +
|
||||
resolver.resolvePoms(pluginContext.dependencies, true))
|
||||
.sorted()
|
||||
.distinct()
|
||||
}
|
||||
|
||||
override fun filename(): String = "plugins.json"
|
||||
}
|
||||
private class PluginResult : PluginResolutionResult {
|
||||
val found = mutableSetOf<PluginResolution>()
|
||||
|
||||
private class PluginResult : PluginResolutionResult {
|
||||
val found = mutableSetOf<PluginResolution>()
|
||||
override fun notFound(sourceDescription: String?, notFoundMessage: String?) {}
|
||||
|
||||
override fun notFound(sourceDescription: String?, notFoundMessage: String?) {}
|
||||
override fun notFound(
|
||||
sourceDescription: String?,
|
||||
notFoundMessage: String?,
|
||||
notFoundDetail: String?
|
||||
) {
|
||||
}
|
||||
|
||||
override fun notFound(
|
||||
sourceDescription: String?,
|
||||
notFoundMessage: String?,
|
||||
notFoundDetail: String?
|
||||
) {
|
||||
override fun isFound(): Boolean = true
|
||||
|
||||
override fun found(sourceDescription: String, pluginResolution: PluginResolution) {
|
||||
found.add(pluginResolution)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isFound(): Boolean = true
|
||||
private class PluginContext : PluginResolveContext {
|
||||
val dependencies = mutableSetOf<ExternalModuleDependency>()
|
||||
val repositories = mutableSetOf<String>()
|
||||
|
||||
override fun found(sourceDescription: String, pluginResolution: PluginResolution) {
|
||||
found.add(pluginResolution)
|
||||
}
|
||||
}
|
||||
override fun add(plugin: PluginImplementation<*>) {
|
||||
println("add: $plugin")
|
||||
}
|
||||
|
||||
private class PluginContext : PluginResolveContext {
|
||||
val dependencies = mutableSetOf<ExternalModuleDependency>()
|
||||
val repositories = mutableSetOf<String>()
|
||||
override fun addFromDifferentLoader(plugin: PluginImplementation<*>) {
|
||||
println("addFromDifferentLoader: $plugin")
|
||||
}
|
||||
|
||||
override fun add(plugin: PluginImplementation<*>) {
|
||||
println("add: $plugin")
|
||||
}
|
||||
override fun addLegacy(pluginId: PluginId, m2RepoUrl: String, dependencyNotation: Any) {
|
||||
repositories.add(m2RepoUrl)
|
||||
}
|
||||
|
||||
override fun addFromDifferentLoader(plugin: PluginImplementation<*>) {
|
||||
println("addFromDifferentLoader: $plugin")
|
||||
}
|
||||
|
||||
override fun addLegacy(pluginId: PluginId, m2RepoUrl: String, dependencyNotation: Any) {
|
||||
repositories.add(m2RepoUrl)
|
||||
}
|
||||
|
||||
override fun addLegacy(pluginId: PluginId, dependencyNotation: Any) {
|
||||
if (dependencyNotation is ExternalModuleDependency) {
|
||||
dependencies.add(dependencyNotation)
|
||||
override fun addLegacy(pluginId: PluginId, dependencyNotation: Any) {
|
||||
if (dependencyNotation is ExternalModuleDependency) {
|
||||
dependencies.add(dependencyNotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ let
|
||||
mkFilename = artifact: with artifact;
|
||||
"${artifactId}-${version}${lib.optionalString (classifier != "") "-${classifier}"}.${extension}";
|
||||
|
||||
mkMavenUrls = repo: artifact:
|
||||
|
||||
|
||||
mkArtifactUrl = base: artifact:
|
||||
"${lib.removeSuffix "/" base}/${mkPath artifact}/${mkFilename artifact}";
|
||||
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
include(":app")
|
||||
include(":plugin")
|
||||
include(":app", ":model", ":plugin")
|
||||
|
||||
Reference in New Issue
Block a user