mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 23:40:37 -05:00
Use Gradle Tooling API
This commit is contained in:
@@ -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}";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user