All-in-one env file

This commit is contained in:
Tad Fisher
2019-06-04 15:18:58 -07:00
parent 7b0e167335
commit 987c03604b
6 changed files with 2448 additions and 33 deletions

View File

@@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm")
kotlin("kapt")
application
}
@@ -24,6 +25,7 @@ dependencies {
implementation("com.squareup.moshi:moshi:latest.release")
implementation("com.squareup.moshi:moshi-adapters:latest.release")
implementation("com.squareup.moshi:moshi-kotlin:latest.release")
kapt("com.squareup.moshi:moshi-kotlin-codegen:latest.release")
implementation("com.squareup.okio:okio:latest.release")
}

View File

@@ -0,0 +1,77 @@
package org.nixos.gradle2nix
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class NixGradleEnv(
val project: String,
val pluginRepo: List<Dependency>,
val projectRepos: Map<String, List<Dependency>>
)
@JsonClass(generateAdapter = true)
data class Dependency(
val name: String,
val filename: String,
val path: String,
val urls: List<String>,
val sha256: String
)
fun buildEnv(builds: Map<String, DefaultBuild>): Map<String, NixGradleEnv> =
builds.mapValues { (path, build) ->
NixGradleEnv(
project = path,
pluginRepo = buildRepo(build.pluginDependencies).values.toList(),
projectRepos = mapOf(
"buildscript" to build.rootProject.collectDependencies(DefaultProject::buildscriptDependencies).values.toList(),
"project" to build.rootProject.collectDependencies(DefaultProject::projectDependencies).values.toList()
))
}
private fun DefaultProject.collectDependencies(chooser: DefaultProject.() -> DefaultDependencies): Map<DefaultArtifact, Dependency> {
val result = mutableMapOf<DefaultArtifact, Dependency>()
mergeRepo(result, buildRepo(chooser()))
for (child in children) {
mergeRepo(result, child.collectDependencies(chooser))
}
return result
}
private fun buildRepo(deps: DefaultDependencies): Map<DefaultArtifact, Dependency> =
deps.artifacts.associate { artifact ->
val name = with(artifact) {
buildString {
append("$groupId-$artifactId-$version")
if (classifier.isNotEmpty()) append("-$classifier")
append("-$extension")
replace(Regex("[^A-Za-z0-9+\\-._?=]"), "_")
}
}
val filename = with(artifact) {
buildString {
append("$artifactId-$version")
if (classifier.isNotEmpty()) append("-$classifier")
append(".$extension")
}
}
val path = with(artifact) { "${groupId.replace(".", "/")}/$artifactId/$version" }
val dep = Dependency(
name = name,
filename = filename,
path = path,
urls = deps.repositories.maven.flatMap { repo ->
repo.urls.map { "${it.removeSuffix("/")}/$path/$filename" }
},
sha256 = artifact.sha256
)
artifact to dep
}
private fun mergeRepo(base: MutableMap<DefaultArtifact, Dependency>, extra: Map<DefaultArtifact, Dependency>) {
extra.forEach { (artifact, dep) ->
base.merge(artifact, dep) { old, new ->
old.copy(urls = old.urls + (new.urls - old.urls))
}
}
}

View File

@@ -30,8 +30,8 @@ fun ProjectConnection.getBuildModel(config: Config, path: String): DefaultBuild
return model(Build::class.java)
.withArguments(arguments)
.apply {
if (config.verbose) {
setStandardOutput(System.out)
if (!config.quiet) {
setStandardOutput(System.err)
setStandardError(System.err)
}
}

View File

@@ -2,6 +2,8 @@ package org.nixos.gradle2nix
import com.github.ajalt.clikt.completion.CompletionCandidates
import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.context
import com.github.ajalt.clikt.output.CliktHelpFormatter
import com.github.ajalt.clikt.parameters.arguments.ProcessedArgument
import com.github.ajalt.clikt.parameters.arguments.argument
import com.github.ajalt.clikt.parameters.arguments.convert
@@ -9,6 +11,7 @@ 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 com.squareup.moshi.Types
import okio.buffer
import okio.sink
import java.io.File
@@ -20,33 +23,30 @@ data class Config(
val projectDir: File,
val includes: List<File>,
val buildSrc: Boolean,
val verbose: Boolean
val quiet: Boolean
) {
val allProjects = listOf(projectDir) + includes
}
class Main : CliktCommand() {
class Main : CliktCommand(
name = "gradle2nix"
) {
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",
metavar = "VERSION",
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 configurations: List<String> by option("--configuration", "-c",
metavar = "NAME",
help = "Add a configuration to resolve (default: all configurations)")
.multiple()
val includes: List<File> by option("--include", "-i",
help = "Path to included build(s)",
metavar = "DIR")
metavar = "DIR",
help = "Add an additional project to include")
.file(exists = true, fileOkay = false, folderOkay = true, readable = true)
.multiple()
.validate { files ->
@@ -58,33 +58,63 @@ class Main : CliktCommand() {
}
}
val buildSrc: Boolean by option("--enableBuildSrc", help = "Include buildSrc project")
.flag("--disableBuildSrc", default = true)
val outDir: File? by option("--out-dir", "-o",
metavar = "DIR",
help = "Path to write generated files (default: PROJECT-DIR)")
.file(fileOkay = false, folderOkay = true)
val verbose: Boolean by option("--verbose", "-v", help = "Enable verbose logging")
val envFile: String by option("--env", "-e",
metavar = "FILENAME",
help = "Name of the environment file")
.default("gradle-env.json")
val buildSrc: Boolean by option("--build-src", "-b", help = "Include buildSrc project (default: true)")
.flag("--no-build-src", "-nb", default = true)
val quiet: Boolean by option("--quiet", "-q", help = "Disable logging")
.flag(default = false)
override fun run() {
val config = Config(wrapper, gradleVersion, configurations, projectDir, includes, buildSrc, verbose)
val (log, warn, error) = Logger(verbose = config.verbose)
val projectDir: File by argument("PROJECT-DIR", help = "Path to the project root (default: .)")
.projectDir()
.default(File("."))
val json by lazy { Moshi.Builder().build().adapter(DefaultBuild::class.java).indent(" ") }
val out by lazy { outputDir.also { it.mkdirs() }}
init {
context {
helpFormatter = CliktHelpFormatter(showDefaultValues = true)
}
}
override fun run() {
val config = Config(wrapper, gradleVersion, configurations, projectDir, includes, buildSrc, quiet)
val (log, _, _) = Logger(verbose = !config.quiet)
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")
val models = connect(config).use { connection ->
paths.associate { project ->
log("Resolving project model: ${project.takeIf { it.isNotEmpty() } ?: "root project"}...")
project to connection.getBuildModel(config, project)
}
}
log("Building environment...")
val nixGradleEnv = buildEnv(models)
val outDir = outDir ?: projectDir
val envFile = outDir.resolve(envFile)
log("Writing environment to $envFile")
envFile.sink().buffer().use { out ->
Moshi.Builder().build()
.adapter<Map<String, NixGradleEnv>>(
Types.newParameterizedType(Map::class.java, String::class.java, NixGradleEnv::class.java)
)
.indent(" ")
.toJson(out, nixGradleEnv)
out.flush()
}
}
}

View File

@@ -1,7 +1,6 @@
plugins {
base
idea
id("com.github.ben-manes.versions") version "0.21.0"
kotlin("jvm") version embeddedKotlinVersion apply false
kotlin("kapt") version embeddedKotlinVersion apply false
id("com.github.johnrengelman.shadow") version "5.0.0" apply false

2307
gradle-env.json Normal file

File diff suppressed because it is too large Load Diff