diff --git a/README.org b/README.org index e1fe787..d55c339 100644 --- a/README.org +++ b/README.org @@ -2,7 +2,8 @@ [[./assets/gradle2nix.png]] -Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradle.org/][Gradle]]-based projects. +Generate [[https://nixos.org/nix/][Nix]] expressions which build +[[https://gradle.org/][Gradle]]-based projects. ** Table of contents @@ -13,6 +14,10 @@ Generate [[https://nixos.org/nix/][Nix]] expressions which build [[https://gradl - [[#usage][Usage]] - [[#for-packagers][For packagers]] - [[#specifying-the-gradle-installation][Specifying the Gradle installation]] +- [[#reference][Reference]] + - [[#buildGradlePackage][=buildGradlePackage=]] + - [[#buildMavenRepo][=buildMavenRepo=]] + - [[#gradleSetupHook][=gradleSetupHook=]] - [[#contributing][Contributing]] - [[#license][License]] #+END_QUOTE @@ -25,7 +30,8 @@ is that it is purely functional; a "package" is a function which accepts inputs (source code, configuration, etc) and produces an output (binaries, a Java JAR, documentation, really anything). -One benefit of a functional build system is [[https://reproducible-builds.org/][reproducibility]]. If you +One benefit of a functional build system is +[[https://reproducible-builds.org/][reproducibility]]. If you specify your inputs precisely, and take care not to introduce impurities—such as files retrieved over a network without tracking their content—you will receive, byte-for-byte, the exact output as @@ -42,31 +48,33 @@ inputs, including: - Environment variables and command-line options - Artifacts cached on the system hosting the build -=gradle2nix= helps to solve this problem by leveraging Nix to control -the most common inputs to a Gradle build. When run on a project, it -will record all dependencies for both the build environment (including -=plugins= and =buildscript= blocks) and the project, and provide a Nix -expression to run the build given these dependencies. The build itself -is then run in a sandbox, where only content-tracked network requests -are allowed to fetch dependencies, and a local Maven repository is -created on-the-fly to host the dependency artifacts somewhere Gradle -can resolve them without a network. +=gradle2nix= helps to solve this problem by leveraging Nix to +control the most common inputs to a Gradle build. When run on a +project, it will record all dependencies for both the build +environment (including =plugins= and =buildscript= blocks) and the +project, and provide a Nix expression to run the build given these +dependencies. The build itself is then run in a sandbox, where only +content-tracked network requests are allowed to fetch dependencies, +and a local Maven repository is created on-the-fly to host the +dependency artifacts somewhere Gradle can resolve them without a +network. This tool is useful for both development and packaging. You can use =gradle2nix= to: -- Create isolated and reproducible development environments that work - anywhere Nix itself can run; +- Create isolated and reproducible development environments that + work anywhere Nix itself can run. - Reduce or eliminate flakiness and maintenance headaches from CI/CD - pipelines + pipelines. - Distribute a recipe which can reliably build a Gradle project in - repositories such as the [[https://nixos.org/nixpkgs/][Nix Package Collection]]. + repositories such as the [[https://nixos.org/nixpkgs/][Nix Package + Collection]]. ** Installation -A [[./gradle.nix][Nix expression]] (generated by =gradle2nix= itself) is provided for -convenience. The following expression will fetch and build the latest -version of this package: +A [[./gradle.nix][Nix expression]] (generated by =gradle2nix= +itself) is provided for convenience. The following expression will +fetch and build the latest version of this package: #+begin_src nix import (fetchTarball "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz") {} @@ -93,8 +101,9 @@ nix-env -if "https://github.com/tadfisher/gradle2nix/archive/master.tar.gz" =gradle2nix= is not yet packaged in =nixpkgs= itself, but work is [[https://github.com/NixOS/nixpkgs/pull/77422][in progress]]. -The [[./gradle.nix][buildGradlePackage]] function is provided via the -=gradle2nix.passthru.buildGradlePackage= attribute. +The [[./nix/build-gradle-package.nix][buildGradlePackage]] function +is provided via the =gradle2nix.passthru.buildGradlePackage= +attribute. #+begin_src nix { pkgs ? import {} }: @@ -106,23 +115,24 @@ gradle2nix.buildGradlePackage { pname = "my-package"; version = "1.0"; lockFile = ./gradle.lock; - gradleFlags = [ "installDist" ]; + gradleInstallFlags = [ "installDist" ]; # ... } #+end_src *** Flake -A [[./flake.nix][flake.nix]] is provided for those using [[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the -following will build and run =gradle2nix= with the arguments provided -after =--=: +A [[./flake.nix][flake.nix]] is provided for those using +[[https://nixos.wiki/wiki/Flakes][Nix flakes]]. For example, the +following will build and run =gradle2nix= with the arguments +provided after =--=: #+begin_example nix run github:tadfisher/gradle2nix -- --help #+end_example -The [[./gradle.nix][buildGradlePackage]] function is provided via the -=builders= output. +The [[./nix/build-gradle-package.nix][buildGradlePackage]] function +is provided via the =builders= output. #+begin_src nix { @@ -134,7 +144,7 @@ The [[./gradle.nix][buildGradlePackage]] function is provided via the pname = "my-package"; version = "1.0"; lockFile = ./gradle.lock; - gradleFlags = [ "installDist" ]; + gradleInstallFlags = [ "installDist" ]; # ... }; }; @@ -169,12 +179,12 @@ Arguments: Extra arguments to pass to Gradle #+end_example -Simply running =gradle2nix= in the root directory of a project should -be enough for most projects. This will produce two files, by default -called =gradle.lock= and =gradle.nix=, which contain the -pinned dependencies for the project and a standard build expression -which can be imported or called by other Nix expressions. An example -of such an expression can be found in this project's [[./gradle2nix.nix][gradle2nix.nix]]. +Simply running =gradle2nix= in the root directory of a project +should be enough for most projects. This will produce a lock file, +by default called =gradle.lock=, which contains the pinned +dependencies for the project. An example of a build expression using +this lock file can be found in this project's +[[./default.nix][default.nix]]. *** For packagers @@ -211,16 +221,203 @@ gradle2nix --gradle-home=`nix eval nixpkgs#gradle.outPath`/lib/gradle gradle2nix --gradle-wrapper=8.7 #+end_example +** Reference + +*** =buildGradlePackage= + +This function is a convenience wrapper around =stdenv.mkDerivation= +that simplifies building Gradle projects with the lock files +produced by =gradle2nix=. It performs the following: + +1. Applies [[#gradleSetupHook][=gradleSetupHook=]], overriding the + required =gradle= package if specified. +2. Builds the offline Maven repository with + [[#buildMavenRepo][=buildMavenRepo=]]. +3. Sets the JDK used to run Gradle if specified. +4. Applies the offline repo to the Gradle build using an + initialization script. + +- Source: + [[./nix/build-gradle-package.nix][build-gradle-package.nix]] +- Location: + - Nix :: =gradle2nix.passthru.buildGradlePackage= + - Flake :: =builders.${system}.buildGradlePackage= + +**** Arguments to =buildGradlePackage= + +- =lockFile= :: Path to the lock file generated by =gradle2nix= + (e.g. =gradle.lock=). +- =gradlePackage= :: The Gradle package to use. Default is + =pkgs.gradle=. +- =buildJdk= :: Override the default JDK used to run Gradle itself. +- =fetchers= :: Override functions which fetch dependency + artifacts. + + See [[#fetchers][detailed documentation]] below. +- =overrides= :: Override artifacts in the offline Maven repository. + + See [[#override][detailed documentation]] below. + +In addition, this function accepts: +- All arguments to =stdenv.mkDerivation=. +- Arguments specific to =gradleSetupHook= (see + [[#gradleSetupHook][below]]). + +*** =buildMavenRepo= + +This function takes a lock file and produces a derivation which +downloads all dependencies into a Maven local repository. The +derivation provides a passthru =gradleInitScript= attribute, which +is a Gradle initialization script that can be applied using =gradle +--init-script== or placed in =$GRADLE_USER_HOME/init.d=. The init +script replaces all repositories referenced in the project with the +local repository. + +- Source: [[./nix/build-maven-repo.nix][build-maven-repo.nix]] +- Location: + - Nix :: =gradle2nix.passthru.buildMavenRepo= + - Flake :: =builders.${system}.buildMavenRepo= + +**** Arguments to =buildMavenRepo= +- =lockFile= :: Path to the lock file generated by gradle2nix (e.g. + =gradle.lock=). +- =fetchers= :: Override functions which fetch dependency + artifacts. + + See [[#fetchers][detailed documentation]] below. +- =overrides= :: Override artifacts in the offline Maven repository. + + See [[#override][detailed documentation]] below. + +*** =gradleSetupHook= + +A +[[https://nixos.org/manual/nixpkgs/unstable/#ssec-setup-hooks][setup +hook]] to simplify building Gradle packages. Overrides the default +configure, build, check, and install phases. + +To use, add =gradleSetupHook= to a derivation's =nativeBuildInputs=. + +- Source: [[./nix/setup-hook.sh][setup-hook.sh]] +- Location: + - Nix :: =gradle2nix.passthru.gradleSetupHook= + - Flake :: =packages.${system}.gradleSetupHook= + +**** Variables controlling =gradleSetupHook= +- =gradleInitScript= :: Path to an + [[https://docs.gradle.org/current/userguide/init_scripts.html][initialization + script]] used by =gradle= during all phases. +- =gradleFlags= :: Controls the arguments passed to =gradle= during + all phases. +- =gradleBuildFlags= :: Controls the arguments passed to =gradle= + during the build phase. The build phase is skipped if this is + unset. +- =gradleCheckFlags= :: Controls the arguments passed to =gradle= + during the check phase. The check phase is skipped if this is + unset. +- =gradleInstallFlags= :: Controls the arguments passed to =gradle= + during the install phase. This install phase is skipped if this is + unset. +- =dontUseGradleConfigure= :: When set to true, don't use the + predefined =gradleConfigurePhase=. This will also disable the use + of =gradleInitScript=. +- =dontUseGradleCheck= :: When set to true, don't use the predefined + =gradleCheckPhase=. +- =dontUseGradleInstall= :: When set to true, don't use the + predefined =gradleInstallPhase=. + +**** Honored variables + +The following variables commonly used by =stdenv.mkDerivation= are +honored by =gradleSetupHook=. + +- =enableParallelBuilding= +- =enableParallelChecking= +- =enableParallelInstalling= + +*** Common arguments +**** =fetchers= + +Names in this set are URL schemes such as "https" or "s3". Values +are functions which take an artifact in the form ={ url, hash }= +and fetches it into the Nix store. For example: + +#+begin_src nix +{ + s3 = { name, url, hash }: fetchs3 { + s3url = url; + # TODO This doesn't work without patching fetchs3 to accept SRI hashes + inherit name hash; + region = "us-west-2"; + credentials = { + access_key_id = "foo"; + secret_access_key = "bar"; + }; + }; +} +#+end_src + +**** =overrides= + +This is an attrset of the form: + +#+begin_src nix +{ + "${group}:${module}:${version}" = { + "${filename}" = ; + } +} +#+end_src + +The override function takes the original derivation from 'fetchers' +(e.g. the result of 'fetchurl') and produces a new derivation to +replace it. + +- Replace a dependency's JAR artifact: + + #+begin_src nix + { + "com.squareup.okio:okio:3.9.0"."okio-3.9.0.jar" = _: fetchurl { + url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; + hash = "..."; + downloadToTemp = true; + postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" + }; + } + #+end_src + +- Patch a JAR containing native binaries: + + #+begin_src nix + { + "com.android.tools.build:aapt2:8.5.0-rc02-11315950" = { + "aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name { + nativeBuildInputs = [ jdk autoPatchelfHook ]; + dontAutoPatchelf = true; + } '' + cp ${src} aapt2.jar + jar xf aapt2.jar aapt2 + chmod +x aapt2 + autoPatchelf aapt2 + jar uf aapt2.jar aapt2 + cp aapt2.jar $out + ''; + } + } + #+end_src + ** Contributing Bug reports and feature requests are encouraged. -[[https://github.com/tadfisher/gradle2nix/issues/new][Create an issue]] +[[https://github.com/tadfisher/gradle2nix/issues/new][Create an +issue]] Code contributions are also encouraged. Please review the test cases -in the [[./fixtures][fixtures]] directory and create a new one to reproduce any fixes -or test new features. See the [[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing tests]] -for examples of testing with these fixtures. +in the [[./fixtures][fixtures]] directory and create a new one to +reproduce any fixes or test new features. See the +[[./app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt][existing +tests]] for examples of testing with these fixtures. ** License diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt b/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt index 59d8e99..399e604 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt @@ -16,7 +16,8 @@ fun connect( config: Config, projectDir: File = config.projectDir, ): ProjectConnection = - GradleConnector.newConnector() + GradleConnector + .newConnector() .apply { when (val source = config.gradleSource) { is GradleSource.Distribution -> useDistribution(source.uri) @@ -24,8 +25,7 @@ fun connect( GradleSource.Project -> useBuildDistribution() is GradleSource.Wrapper -> useGradleVersion(source.version) } - } - .forProjectDirectory(projectDir) + }.forProjectDirectory(projectDir) .connect() suspend fun ProjectConnection.buildModel(): GradleBuild = @@ -67,8 +67,7 @@ suspend fun ProjectConnection.build( "--refresh-dependencies", "--gradle-user-home=${config.gradleHome}", "--init-script=${config.appHome}/init.gradle", - ) - .apply { + ).apply { if (config.logger.stacktrace) { addArguments("--stacktrace") } @@ -80,12 +79,14 @@ suspend fun ProjectConnection.build( withSystemProperties( mapOf( "org.gradle.internal.operations.trace" to - config.outDir.toPath().resolve("debug").absolutePathString(), + config.outDir + .toPath() + .resolve("debug") + .absolutePathString(), ), ) } - } - .run( + }.run( object : ResultHandler { override fun onComplete(result: DependencySet) { continuation.resume(result) diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt index 4f0f3e0..56a8da8 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Main.kt @@ -48,13 +48,19 @@ val JsonFormat = } sealed interface GradleSource { - data class Distribution(val uri: URI) : GradleSource + data class Distribution( + val uri: URI, + ) : GradleSource - data class Path(val path: File) : GradleSource + data class Path( + val path: File, + ) : GradleSource data object Project : GradleSource - data class Wrapper(val version: String) : GradleSource + data class Wrapper( + val version: String, + ) : GradleSource } enum class LogLevel { @@ -64,9 +70,10 @@ enum class LogLevel { ERROR, } -class Gradle2Nix : CliktCommand( - name = "gradle2nix", -) { +class Gradle2Nix : + CliktCommand( + name = "gradle2nix", + ) { private val tasks: List by option( "--task", "-t", @@ -93,8 +100,7 @@ class Gradle2Nix : CliktCommand( "-o", metavar = "DIR", help = "Path to write generated files", - ) - .file(canBeFile = false, canBeDir = true) + ).file(canBeFile = false, canBeDir = true) .defaultLazy("") { projectDir } internal val lockFile: String by option( @@ -133,8 +139,7 @@ class Gradle2Nix : CliktCommand( private val logLevel: LogLevel by option( "--log", help = "Print messages with this priority or higher", - ) - .enum(key = { it.name.lowercase() }) + ).enum(key = { it.name.lowercase() }) .default(LogLevel.INFO, "info") private val dumpEvents: Boolean by option( @@ -192,7 +197,9 @@ class Gradle2Nix : CliktCommand( addAll(root.editableBuilds) } builds.mapNotNull { build -> - build.rootProject.projectDirectory.resolve("buildSrc").takeIf { it.exists() } + build.rootProject.projectDirectory + .resolve("buildSrc") + .takeIf { it.exists() } } } diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt index 3e1f62f..229eef0 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Process.kt @@ -8,8 +8,8 @@ import kotlin.io.encoding.ExperimentalEncodingApi fun processDependencies( config: Config, dependencySets: Iterable, -): Env { - return buildMap> { +): Env = + buildMap> { for (dependencySet in dependencySets) { val env = dependencySet.toEnv() @@ -40,16 +40,14 @@ fun processDependencies( artifacts.toSortedMap() }.toSortedMap(coordinatesComparator) .mapKeys { (coordinates, _) -> coordinates.id } -} -private fun DependencySet.toEnv(): Map> { - return dependencies.associate { dep -> +private fun DependencySet.toEnv(): Map> = + dependencies.associate { dep -> dep.coordinates to dep.artifacts.associate { it.name to Artifact(it.url, it.hash.toSri()) } } -} @OptIn(ExperimentalEncodingApi::class, ExperimentalStdlibApi::class) internal fun String.toSri(): String = diff --git a/app/src/main/kotlin/org/nixos/gradle2nix/Version.kt b/app/src/main/kotlin/org/nixos/gradle2nix/Version.kt index 89df247..a898884 100644 --- a/app/src/main/kotlin/org/nixos/gradle2nix/Version.kt +++ b/app/src/main/kotlin/org/nixos/gradle2nix/Version.kt @@ -2,7 +2,11 @@ package org.nixos.gradle2nix import java.util.concurrent.ConcurrentHashMap -class Version(val source: String, val parts: List, base: Version?) : Comparable { +class Version( + val source: String, + val parts: List, + base: Version?, +) : Comparable { private val base: Version val numericParts: List diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt b/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt index e07c275..a8975ee 100644 --- a/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt +++ b/app/src/test/kotlin/org/nixos/gradle2nix/GoldenTest.kt @@ -3,45 +3,46 @@ package org.nixos.gradle2nix import io.kotest.core.extensions.install import io.kotest.core.spec.style.FunSpec -class GoldenTest : FunSpec({ - install(MavenRepo) +class GoldenTest : + FunSpec({ + install(MavenRepo) - context("basic") { - golden("basic/basic-java-project") - golden("basic/basic-kotlin-project") - } - context("buildsrc") { - golden("buildsrc/plugin-in-buildsrc") - } - context("dependency") { - golden("dependency/classifier") - golden("dependency/maven-bom") - golden("dependency/snapshot") - golden("dependency/snapshot-dynamic") - golden("dependency/snapshot-redirect") - } - context("included-build") { - golden("included-build") - } - context("integration") { - golden("integration/settings-buildscript") - } - context("ivy") { - golden("ivy/basic") - } - context("plugin") { - golden("plugin/resolves-from-default-repo") - } - // FIXME Need s3mock or similar to generate golden data. - xcontext("s3") { - golden("s3/maven") - golden("s3/maven-snapshot") - } - context("settings") { - golden("settings/buildscript") - golden("settings/dependency-resolution-management") - } - context("subprojects") { - golden("subprojects/multi-module") - } -}) + context("basic") { + golden("basic/basic-java-project") + golden("basic/basic-kotlin-project") + } + context("buildsrc") { + golden("buildsrc/plugin-in-buildsrc") + } + context("dependency") { + golden("dependency/classifier") + golden("dependency/maven-bom") + golden("dependency/snapshot") + golden("dependency/snapshot-dynamic") + golden("dependency/snapshot-redirect") + } + context("included-build") { + golden("included-build") + } + context("integration") { + golden("integration/settings-buildscript") + } + context("ivy") { + golden("ivy/basic") + } + context("plugin") { + golden("plugin/resolves-from-default-repo") + } + // FIXME Need s3mock or similar to generate golden data. + xcontext("s3") { + golden("s3/maven") + golden("s3/maven-snapshot") + } + context("settings") { + golden("settings/buildscript") + golden("settings/dependency-resolution-management") + } + context("subprojects") { + golden("subprojects/multi-module") + } + }) diff --git a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt index c92b456..2f55b52 100644 --- a/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt +++ b/app/src/test/kotlin/org/nixos/gradle2nix/TestUtil.kt @@ -47,9 +47,7 @@ private val json = val testLogger = Logger(logLevel = LogLevel.DEBUG, stacktrace = true) -fun fixture(path: String): File { - return Paths.get("../fixtures", path).toFile() -} +fun fixture(path: String): File = Paths.get("../fixtures", path).toFile() @OptIn(ExperimentalKotest::class, ExperimentalSerializationApi::class, KotestInternal::class) suspend fun TestScope.fixture( @@ -60,7 +58,8 @@ suspend fun TestScope.fixture( val tmp = Paths.get("build/tmp/gradle2nix").apply { toFile().mkdirs() } val baseDir = Paths.get("../fixtures/projects", project).toFile() val children = - baseDir.listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") }) + baseDir + .listFiles(FileFilter { it.isDirectory && (it.name == "groovy" || it.name == "kotlin") }) ?.toList() val cases = if (children.isNullOrEmpty()) { @@ -175,8 +174,8 @@ object MavenRepo : MountableExtension, return tryStart(3).also { this.server = it } } - private fun tryStart(attempts: Int): NettyApplicationEngine { - return try { + private fun tryStart(attempts: Int): NettyApplicationEngine = + try { val p = config.port ?: Random.nextInt(10000, 65000) val s = embeddedServer(Netty, port = p, host = config.host) { @@ -202,7 +201,6 @@ object MavenRepo : MountableExtension, } catch (e: Throwable) { if (config.port == null && attempts > 0) tryStart(attempts - 1) else throw e } - } override suspend fun afterSpec(spec: Spec) { server?.stop() diff --git a/default.nix b/default.nix index 4151b21..f5a1b7e 100644 --- a/default.nix +++ b/default.nix @@ -5,9 +5,16 @@ with pkgs; let - buildMavenRepo = callPackage ./maven-repo.nix { }; + buildMavenRepo = callPackage ./nix/build-maven-repo.nix { }; - buildGradlePackage = callPackage ./gradle.nix { inherit buildMavenRepo; }; + gradleSetupHook = makeSetupHook { + name = "gradle-setup-hook"; + propagatedBuildInputs = [ gradle ]; + } ./nix/setup-hook.sh; + + buildGradlePackage = callPackage ./nix/build-gradle-package.nix { + inherit buildMavenRepo gradleSetupHook; + }; gradle2nix = buildGradlePackage { pname = "gradle2nix"; @@ -30,9 +37,9 @@ let }; }; - gradleFlags = [ "installDist" ]; + gradleInstallFlags = [ ":app:installDist" ]; - installPhase = '' + postInstall = '' mkdir -p $out/{bin,/lib/gradle2nix} cp -r app/build/install/gradle2nix/* $out/lib/gradle2nix/ rm $out/lib/gradle2nix/bin/gradle2nix.bat @@ -40,7 +47,7 @@ let ''; passthru = { - inherit buildGradlePackage buildMavenRepo; + inherit buildGradlePackage buildMavenRepo gradleSetupHook; }; meta = with lib; { diff --git a/flake.lock b/flake.lock index 9336b3f..31d4b67 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1716769173, - "narHash": "sha256-7EXDb5WBw+d004Agt+JHC/Oyh/KTUglOaQ4MNjBbo5w=", + "lastModified": 1718160348, + "narHash": "sha256-9YrUjdztqi4Gz8n3mBuqvCkMo4ojrA6nASwyIKWMpus=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9ca3f649614213b2aaf5f1e16ec06952fe4c2632", + "rev": "57d6973abba7ea108bac64ae7629e7431e0199b6", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 06633ff..c3b78bf 100644 --- a/flake.nix +++ b/flake.nix @@ -20,15 +20,15 @@ inherit (nixpkgs) lib; in { - builders = rec { - buildMavenRepo = pkgs.callPackage ./maven-repo.nix { }; - buildGradlePackage = pkgs.callPackage ./gradle.nix { inherit buildMavenRepo; }; - default = buildGradlePackage; + builders = { + inherit (self.packages.${system}.gradle2nix) buildGradlePackage buildMavenRepo; + default = self.packages.${system}.buildGradlePackage; }; - packages = rec { + packages = { + inherit (self.packages.${system}.gradle2nix) gradleSetupHook; gradle2nix = pkgs.callPackage ./default.nix { }; - default = gradle2nix; + default = self.packages.${system}.gradle2nix; }; apps = rec { diff --git a/gradle.nix b/gradle.nix deleted file mode 100644 index b505770..0000000 --- a/gradle.nix +++ /dev/null @@ -1,238 +0,0 @@ -# This file is generated by gradle2nix. -# -# Example usage (e.g. in default.nix): -# -# with (import {}); -# let -# buildGradle = callPackage ./gradle.nix {}; -# in -# buildGradle { -# lockFile = ./gradle.lock; -# -# src = ./.; -# -# gradleFlags = [ "installDist" ]; -# -# installPhase = '' -# mkdir -p $out -# cp -r app/build/install/myproject $out -# ''; -# } - -{ - lib, - stdenv, - gradle, - buildMavenRepo, - writeText, -}: - -let - defaultGradle = gradle; -in - -{ - # Path to the lockfile generated by gradle2nix (e.g. gradle.lock). - lockFile ? null, - pname ? "project", - version ? null, - enableParallelBuilding ? true, - # The Gradle package to use. Default is 'pkgs.gradle'. - gradle ? defaultGradle, - # Arguments to Gradle used to build the project in buildPhase. - gradleFlags ? [ "build" ], - # Enable debugging for the Gradle build; this will cause Gradle to run - # a debug server and wait for a JVM debugging client to attach. - enableDebug ? false, - # Additional code to run in the Gradle init script (init.gradle). - extraInit ? "", - # Override the default JDK used to run Gradle itself. - buildJdk ? null, - # Override functions which fetch dependency artifacts. - # Keys in this set are URL schemes such as "https" or "s3". - # Values are functions which take a dependency in the form - # `{ urls, hash }` and fetch into the Nix store. For example: - # - # { - # s3 = { name, urls, hash }: fetchs3 { - # s3url = builtins.head urls; - # # TODO This doesn't work without patching fetchs3 to accept SRI hashes - # inherit name hash; - # region = "us-west-2"; - # credentials = { - # access_key_id = "foo"; - # secret_access_key = "bar"; - # }; - # }; - # } - fetchers ? { }, - # Overlays for dependencies in the offline Maven repository. - # - # Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset - # containing dependencies to merge into the final set. - # - # The attrset is of the form: - # - # { - # "${group}:${module}:${version}" = ; - # # ... - # } - # - # A dependency derivation unpacks multiple source files into a single Maven-style directory named - # "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot - # characters ('.') replaced by the path separator ('/'). - # - # Examples: - # - # 1. Add or replace a dependency with a single JAR file: - # - # (_: { - # "com.squareup.okio:okio:3.9.0" = fetchurl { - # url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; - # hash = "..."; - # downloadToTemmp = true; - # postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" - # }; - # }) - # - # 2. Remove a dependency entirely: - # - # # This works because the result is filtered for values that are derivations. - # (_: { - # "org.apache.log4j:core:2.23.1" = null; - # }) - overlays ? [ ], - ... -}@args: - -let - inherit (builtins) removeAttrs; - - inherit (lib) versionAtLeast versionOlder; - - offlineRepo = buildMavenRepo { - inherit - lockFile - pname - version - fetchers - overlays - ; - }; - - initScript = writeText "init.gradle" '' - import org.gradle.util.GradleVersion - - static boolean versionAtLeast(String version) { - return GradleVersion.current() >= GradleVersion.version(version) - } - - static void configureRepos(RepositoryHandler repositories) { - repositories.configureEach { ArtifactRepository repo -> - if (repo instanceof MavenArtifactRepository) { - repo.setArtifactUrls(new HashSet()) - repo.url 'file:${offlineRepo}' - repo.metadataSources { - gradleMetadata() - mavenPom() - artifact() - } - } else if (repo instanceof IvyArtifactRepository) { - repo.url 'file:${offlineRepo}' - repo.layout('maven') - repo.metadataSources { - gradleMetadata() - ivyDescriptor() - artifact() - } - } else if (repo instanceof UrlArtifactRepository) { - repo.url 'file:/homeless-shelter' - } - } - } - - beforeSettings { settings -> - configureRepos(settings.pluginManagement.repositories) - configureRepos(settings.buildscript.repositories) - if (versionAtLeast("6.8")) { - configureRepos(settings.dependencyResolutionManagement.repositories) - } - } - - beforeProject { project -> - configureRepos(project.buildscript.repositories) - configureRepos(project.repositories) - } - - ${extraInit} - ''; - - buildGradlePackage = stdenv.mkDerivation ( - finalAttrs: - { - - inherit - buildJdk - enableParallelBuilding - enableDebug - gradle - gradleFlags - pname - version - ; - - dontStrip = true; - - nativeBuildInputs = [ finalAttrs.gradle ]; - - buildPhase = - let - finalGradleFlags = - [ - "--console=plain" - "--no-build-cache" - "--no-configuration-cache" - "--no-daemon" - "--no-watch-fs" - "--offline" - ] - ++ lib.optional (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}" - ++ lib.optional finalAttrs.enableDebug "-Dorg.gradle.debug=true" - ++ lib.optional finalAttrs.enableParallelBuilding "--parallel" - ++ lib.optional (versionAtLeast finalAttrs.gradle.version "8.0") "--init-script=${initScript}" - ++ finalAttrs.gradleFlags; - in - '' - runHook preBuild - - ( - set -eux - - export NIX_OFFLINE_REPO='${offlineRepo}' - export GRADLE_USER_HOME="$(mktemp -d)" - - ${lib.optionalString (versionOlder finalAttrs.gradle.version "8.0") '' - # Work around https://github.com/gradle/gradle/issues/1055 - mkdir -p "$GRADLE_USER_HOME/init.d" - ln -s ${initScript} "$GRADLE_USER_HOME/init.d/nix-init.gradle" - ''} - - gradle ${builtins.toString finalGradleFlags} - ) - - runHook postBuild - ''; - - passthru = { - inherit offlineRepo; - }; - } - // removeAttrs args [ - "lockFile" - "extraInit" - "fetchers" - "overlays" - ] - ); -in -buildGradlePackage diff --git a/nix/build-gradle-package.nix b/nix/build-gradle-package.nix new file mode 100644 index 0000000..a2e0ce0 --- /dev/null +++ b/nix/build-gradle-package.nix @@ -0,0 +1,145 @@ +# This file is generated by gradle2nix. +# +# Example usage (e.g. in default.nix): +# +# with (import {}); +# let +# buildGradle = callPackage ./gradle.nix {}; +# in +# buildGradle { +# lockFile = ./gradle.lock; +# +# src = ./.; +# +# gradleFlags = [ "installDist" ]; +# +# installPhase = '' +# mkdir -p $out +# cp -r app/build/install/myproject $out +# ''; +# } + +{ + lib, + stdenv, + gradle, + buildMavenRepo, + gradleSetupHook, + writeText, +}: + +{ + # Path to the lockfile generated by gradle2nix (e.g. gradle.lock). + lockFile ? null, + pname ? "project", + version ? null, + # The Gradle package to use. Default is 'pkgs.gradle'. + gradlePackage ? gradle, + # Override the default JDK used to run Gradle itself. + buildJdk ? null, + # Override functions which fetch dependency artifacts. + # Names in this set are URL schemes such as "https" or "s3". + # Values are functions which take a dependency in the form + # `{ urls, hash }` and fetch into the Nix store. For example: + # + # { + # s3 = { name, urls, hash }: fetchs3 { + # s3url = builtins.head urls; + # # TODO This doesn't work without patching fetchs3 to accept SRI hashes + # inherit name hash; + # region = "us-west-2"; + # credentials = { + # access_key_id = "foo"; + # secret_access_key = "bar"; + # }; + # }; + # } + fetchers ? { }, + # Override artifacts in the offline Maven repository. + # + # This is an attrset is of the form: + # + # { + # "${group}:${module}:${version}" = { + # "${filename}" = ; + # } + # } + # + # The override function takes the original derivation from 'fetchers' (e.g. the result of + # 'fetchurl') and produces a new derivation to replace it. + # + # Examples: + # + # 1. Replace a dependency's JAR artifact: + # + # { + # "com.squareup.okio:okio:3.9.0"."okio-3.9.0.jar" = _: fetchurl { + # url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; + # hash = "..."; + # downloadToTemp = true; + # postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" + # }; + # } + # + # 2. Patch a JAR containing native binaries: + # + # { + # "com.android.tools.build:aapt2:8.5.0-rc02-11315950" = { + # "aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name { + # nativeBuildInputs = [ jdk autoPatchelfHook ]; + # dontAutoPatchelf = true; + # } '' + # cp ${src} aapt2.jar + # jar xf aapt2.jar aapt2 + # chmod +x aapt2 + # autoPatchelf aapt2 + # jar uf aapt2.jar aapt2 + # cp aapt2.jar $out + # ''; + # } + # } + overrides ? { }, + ... +}@args: + +let + inherit (builtins) removeAttrs; + + gradleSetupHook' = gradleSetupHook.overrideAttrs (_: { + propagatedBuildInputs = [ gradlePackage ]; + }); + + offlineRepo = + if lockFile != null then buildMavenRepo { inherit lockFile fetchers overrides; } else null; + + buildGradlePackage = stdenv.mkDerivation ( + finalAttrs: + { + + inherit buildJdk pname version; + + inherit (offlineRepo) gradleInitScript; + + dontStrip = true; + + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ gradleSetupHook' ]; + + gradleFlags = + [ "--console=plain" ] + ++ lib.optional (finalAttrs.buildJdk != null) "-Dorg.gradle.java.home=${finalAttrs.buildJdk.home}"; + + passthru = + lib.optionalAttrs (offlineRepo != null) { inherit offlineRepo; } // (args.passthru or { }); + } + // removeAttrs args [ + "gradle" + "gradleInitScript" + "lockFile" + "fetchers" + "nativeBuildInputs" + "overlays" + "passthru" + ] + ); +in +buildGradlePackage diff --git a/maven-repo.nix b/nix/build-maven-repo.nix similarity index 56% rename from maven-repo.nix rename to nix/build-maven-repo.nix index 2a13615..cdf184b 100644 --- a/maven-repo.nix +++ b/nix/build-maven-repo.nix @@ -2,16 +2,15 @@ lib, stdenv, fetchurl, + substitute, symlinkJoin, }: { # Path to the lockfile generated by gradle2nix (e.g. gradle.lock). lockFile, - pname ? "project", - version ? null, # Override functions which fetch dependency artifacts. - # Keys in this set are URL schemes such as "https" or "s3". + # Names in this set are URL schemes such as "https" or "s3". # Values are functions which take a dependency in the form # `{ urls, hash }` and fetch into the Nix store. For example: # @@ -28,42 +27,50 @@ # }; # } fetchers ? { }, - # Overlays for dependencies in the offline Maven repository. + # Override artifacts in the offline Maven repository. # - # Acceps an attrset of dependencies (usually parsed from 'lockFile'), and produces an attrset - # containing dependencies to merge into the final set. - # - # The attrset is of the form: + # This is an attrset is of the form: # # { - # "${group}:${module}:${version}" = ; - # # ... + # "${group}:${module}:${version}" = { + # "${filename}" = ; + # } # } # - # A dependency derivation unpacks multiple source files into a single Maven-style directory named - # "${out}/${groupPath}/${module}/${version}/", where 'groupPath' is the dependency group ID with dot - # characters ('.') replaced by the path separator ('/'). + # The override function takes the original derivation from 'fetchers' (e.g. the result of + # 'fetchurl') and produces a new derivation to replace it. # # Examples: # - # 1. Add or replace a dependency with a single JAR file: + # 1. Replace a dependency's JAR artifact: # - # (_: { - # "com.squareup.okio:okio:3.9.0" = fetchurl { + # { + # "com.squareup.okio:okio:3.9.0"."okio-3.9.0.jar" = _: fetchurl { # url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; # hash = "..."; - # downloadToTemmp = true; + # downloadToTemp = true; # postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" # }; - # }) + # } # - # 2. Remove a dependency entirely: + # 2. Patch a JAR containing native binaries: # - # # This works because the result is filtered for values that are derivations. - # (_: { - # "org.apache.log4j:core:2.23.1" = null; - # }) - overlays ? [ ], + # { + # "com.android.tools.build:aapt2:8.5.0-rc02-11315950" = { + # "aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name { + # nativeBuildInputs = [ jdk autoPatchelfHook ]; + # dontAutoPatchelf = true; + # } '' + # cp ${src} aapt2.jar + # jar xf aapt2.jar aapt2 + # chmod +x aapt2 + # autoPatchelf aapt2 + # jar uf aapt2.jar aapt2 + # cp aapt2.jar $out + # ''; + # } + # } + overrides ? { }, }: let @@ -116,25 +123,28 @@ let } // fetchers; fetch = - name: + coords: overrides: name: { url, hash }: let scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url); fetch' = getAttr scheme fetchers'; + artifact = fetch' { inherit url hash; }; + override = overrides.name or lib.id; in - fetch' { inherit url hash; }; + override artifact; mkModule = id: artifacts: let coords = toCoordinates id; modulePath = "${replaceStrings [ "." ] [ "/" ] coords.group}/${coords.module}/${coords.version}"; + moduleOverrides = overrides.${id} or { }; in stdenv.mkDerivation { pname = sanitizeDerivationName "${coords.group}-${coords.module}"; version = coords.uniqueVersion; - srcs = mapAttrsToList fetch artifacts; + srcs = mapAttrsToList (fetch coords moduleOverrides) artifacts; dontPatch = true; dontConfigure = true; @@ -156,34 +166,24 @@ let allowSubstitutes = false; }; - # Intermediate dependency spec. - # - # We want to allow overriding dependencies via the 'dependencies' function, - # so we pass an intermediate set that maps each Maven coordinate to the - # derivation created with 'mkModule'. This allows users extra flexibility - # to do things like patching native libraries with patchelf or replacing - # artifacts entirely. - lockedDependencies = - final: - if lockFile == null then - { } - else - let - lockedDependencySpecs = fromJSON (readFile lockFile); - in - mapAttrs mkModule lockedDependencySpecs; - - finalDependencies = + modulePaths = let - composedExtension = lib.composeManyExtensions overlays; - extended = lib.extends composedExtension lockedDependencies; - fixed = lib.fix extended; + dependencies = fromJSON (readFile lockFile); + modules = mapAttrs mkModule dependencies; in - filter lib.isDerivation (attrValues fixed); + filter lib.isDerivation (attrValues modules); - offlineRepo = symlinkJoin { - name = if version != null then "${pname}-${version}-gradle-repo" else "${pname}-gradle-repo"; - paths = finalDependencies; + mavenRepo = symlinkJoin { + name = "gradle-maven-repo"; + paths = modulePaths; + passthru.gradleInitScript = substitute { + src = ./init.gradle; + substitutions = [ + "--replace" + "@mavenRepo@" + "${mavenRepo}" + ]; + }; }; in -offlineRepo +mavenRepo diff --git a/nix/init.gradle b/nix/init.gradle new file mode 100644 index 0000000..737a7a7 --- /dev/null +++ b/nix/init.gradle @@ -0,0 +1,42 @@ +import org.gradle.util.GradleVersion + +static boolean versionAtLeast(String version) { + return GradleVersion.current() >= GradleVersion.version(version) +} + +static void configureRepos(RepositoryHandler repositories) { + repositories.configureEach { ArtifactRepository repo -> + if (repo instanceof MavenArtifactRepository) { + repo.setArtifactUrls(new HashSet()) + repo.url 'file:@mavenRepo@' + repo.metadataSources { + gradleMetadata() + mavenPom() + artifact() + } + } else if (repo instanceof IvyArtifactRepository) { + repo.url 'file:@mavenRepo@' + repo.layout('maven') + repo.metadataSources { + gradleMetadata() + ivyDescriptor() + artifact() + } + } else if (repo instanceof UrlArtifactRepository) { + repo.url 'file:/homeless-shelter' + } + } +} + +beforeSettings { settings -> + configureRepos(settings.pluginManagement.repositories) + configureRepos(settings.buildscript.repositories) + if (versionAtLeast("6.8")) { + configureRepos(settings.dependencyResolutionManagement.repositories) + } +} + +beforeProject { project -> + configureRepos(project.buildscript.repositories) + configureRepos(project.repositories) +} diff --git a/nix/setup-hook.sh b/nix/setup-hook.sh new file mode 100644 index 0000000..c16d28e --- /dev/null +++ b/nix/setup-hook.sh @@ -0,0 +1,125 @@ +# shellcheck shell=bash disable=SC2206,SC2155 + +gradleConfigurePhase() { + runHook preConfigure + + if ! [[ -v enableParallelBuilding ]]; then + enableParallelBuilding=1 + echo "gradle: enabled parallel building" + fi + + if ! [[ -v enableParallelChecking ]]; then + enableParallelChecking=1 + echo "gradle: enabled parallel checking" + fi + + if ! [[ -v enableParallelInstalling ]]; then + enableParallelInstalling=1 + echo "gradle: enabled parallel installing" + fi + + export GRADLE_USER_HOME="$(mktemp -d)" + + if [ -n "$gradleInitScript" ]; then + if [ ! -f "$gradleInitScript" ]; then + echo "gradleInitScript is not a file path: $gradleInitScript" + exit 1 + fi + mkdir -p "$GRADLE_USER_HOME/init.d" + ln -s "$gradleInitScript" "$GRADLE_USER_HOME/init.d" + fi + + runHook postConfigure +} + +gradleBuildPhase() { + runHook preBuild + + if [ -z "${gradleBuildFlags:-}" ] && [ -z "${gradleBuildFlagsArray[*]}" ]; then + echo "gradleBuildFlags is not set, doing nothing" + else + local flagsArray=( + $gradleFlags "${gradleFlagsArray[@]}" + $gradleBuildFlags "${gradleBuildFlagsArray[@]}" + ) + + if [ -n "$enableParallelBuilding" ]; then + flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES}) + else + flagsArray+=(--no-parallel) + fi + + echoCmd 'gradleBuildPhase flags' "${flagsArray[@]}" + + gradle "${flagsArray[@]}" + fi + + runHook postBuild +} + +gradleCheckPhase() { + runHook preCheck + + if [ -z "${gradleCheckFlags:-}" ] && [ -z "${gradleCheckFlagsArray[*]}" ]; then + echo "gradleCheckFlags is not set, doing nothing" + else + local flagsArray=( + $gradleFlags "${gradleFlagsArray[@]}" + $gradleCheckFlags "${gradleCheckFlagsArray[@]}" + ${gradleCheckTasks:-check} + ) + + if [ -n "$enableParallelChecking" ]; then + flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES}) + else + flagsArray+=(--no-parallel) + fi + + echoCmd 'gradleCheckPhase flags' "${flagsArray[@]}" + + gradle "${flagsArray[@]}" + fi + + runHook postCheck +} + +gradleInstallPhase() { + runHook preInstall + + if [ -z "${gradleInstallFlags:-}" ] && [ -z "${gradleInstallFlagsArray[*]}" ]; then + echo "gradleInstallFlags is not set, doing nothing" + else + local flagsArray=( + $gradleFlags "${gradleFlagsArray[@]}" + $gradleInstallFlags "${gradleInstallFlagsArray[@]}" + ) + + if [ -n "$enableParallelInstalling" ]; then + flagsArray+=(--parallel --max-workers ${NIX_BUILD_CORES}) + else + flagsArray+=(--no-parallel) + fi + + echoCmd 'gradleInstallPhase flags' "${flagsArray[@]}" + + gradle "${flagsArray[@]}" + fi + + runHook postInstall +} + +if [ -z "${dontUseGradleConfigure-}" ] && [ -z "${configurePhase-}" ]; then + configurePhase=gradleConfigurePhase +fi + +if [ -z "${dontUseGradleBuild-}" ] && [ -z "${buildPhase-}" ]; then + buildPhase=gradleBuildPhase +fi + +if [ -z "${dontUseGradleCheck-}" ] && [ -z "${checkPhase-}" ]; then + checkPhase=gradleCheckPhase +fi + +if [ -z "${dontUseGradleInstall-}" ] && [ -z "${installPhase-}" ]; then + installPhase=gradleInstallPhase +fi diff --git a/plugin/base/src/main/kotlin/Gradle2NixPlugin.gradle69.kt b/plugin/base/src/main/kotlin/Gradle2NixPlugin.gradle69.kt index 628ff01..2b21d80 100644 --- a/plugin/base/src/main/kotlin/Gradle2NixPlugin.gradle69.kt +++ b/plugin/base/src/main/kotlin/Gradle2NixPlugin.gradle69.kt @@ -1,7 +1,8 @@ package org.nixos.gradle2nix -abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin( - GradleCacheAccessFactoryBase, - DependencyExtractorApplierBase, - ResolveAllArtifactsApplierBase, -) +abstract class Gradle2NixPlugin : + AbstractGradle2NixPlugin( + GradleCacheAccessFactoryBase, + DependencyExtractorApplierBase, + ResolveAllArtifactsApplierBase, + ) diff --git a/plugin/base/src/main/kotlin/GradleCacheAccess.gradle69.kt b/plugin/base/src/main/kotlin/GradleCacheAccess.gradle69.kt index 3d48c52..ce97ff0 100644 --- a/plugin/base/src/main/kotlin/GradleCacheAccess.gradle69.kt +++ b/plugin/base/src/main/kotlin/GradleCacheAccess.gradle69.kt @@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider import org.gradle.api.invocation.Gradle object GradleCacheAccessFactoryBase : GradleCacheAccessFactory { - override fun create(gradle: Gradle): GradleCacheAccess { - return GradleCacheAccessBase(gradle) - } + override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessBase(gradle) } -class GradleCacheAccessBase(gradle: Gradle) : GradleCacheAccess { +class GradleCacheAccessBase( + gradle: Gradle, +) : GradleCacheAccess { private val artifactCachesProvider = gradle.service() override fun useCache(block: () -> Unit) { diff --git a/plugin/common/src/main/kotlin/DependencyExtractor.kt b/plugin/common/src/main/kotlin/DependencyExtractor.kt index 3a86df6..cfdf248 100644 --- a/plugin/common/src/main/kotlin/DependencyExtractor.kt +++ b/plugin/common/src/main/kotlin/DependencyExtractor.kt @@ -116,22 +116,27 @@ private fun cachedComponentId(file: File): DependencyCoordinates? { val parts = file.invariantSeparatorsPath.split('/') if (parts.size < 6) return null if (parts[parts.size - 6] != "files-2.1") return null - return parts.dropLast(2).takeLast(3).joinToString(":").let(DefaultDependencyCoordinates::parse) + return parts + .dropLast(2) + .takeLast(3) + .joinToString(":") + .let(DefaultDependencyCoordinates::parse) } @OptIn(ExperimentalSerializationApi::class) private fun parseFileMappings(file: File): Map? = try { - Json.decodeFromStream(file.inputStream()) - .jsonObject["variants"]?.jsonArray + Json + .decodeFromStream(file.inputStream()) + .jsonObject["variants"] + ?.jsonArray ?.flatMap { it.jsonObject["files"]?.jsonArray ?: emptyList() } ?.map { it.jsonObject } ?.mapNotNull { val name = it["name"]?.jsonPrimitive?.content ?: return@mapNotNull null val url = it["url"]?.jsonPrimitive?.content ?: return@mapNotNull null if (name != url) name to url else null - } - ?.toMap() + }?.toMap() ?.takeUnless { it.isEmpty() } } catch (e: Throwable) { null diff --git a/plugin/common/src/main/kotlin/DependencySetModelBuilder.kt b/plugin/common/src/main/kotlin/DependencySetModelBuilder.kt index e5cd465..4db256d 100644 --- a/plugin/common/src/main/kotlin/DependencySetModelBuilder.kt +++ b/plugin/common/src/main/kotlin/DependencySetModelBuilder.kt @@ -17,11 +17,10 @@ class DependencySetModelBuilder( override fun buildAll( modelName: String, project: Project, - ): DependencySet { - return dependencyExtractor.buildDependencySet( + ): DependencySet = + dependencyExtractor.buildDependencySet( cacheAccess, checksumService, fileStoreAndIndexProvider, ) - } } diff --git a/plugin/common/src/main/kotlin/ResolveAllArtifacts.kt b/plugin/common/src/main/kotlin/ResolveAllArtifacts.kt index da1fadf..04d15a1 100644 --- a/plugin/common/src/main/kotlin/ResolveAllArtifacts.kt +++ b/plugin/common/src/main/kotlin/ResolveAllArtifacts.kt @@ -38,14 +38,15 @@ abstract class AbstractResolveAllArtifactsApplier : ResolveAllArtifactsApplier { abstract class ResolveProjectDependenciesTask : DefaultTask() { @Internal - protected fun getReportableConfigurations(): List { - return project.configurations.filter { (it as? DeprecatableConfiguration)?.canSafelyBeResolved() ?: true } - } + protected fun getReportableConfigurations(): List = + project.configurations.filter { + (it as? DeprecatableConfiguration)?.canSafelyBeResolved() ?: true + } - protected fun Configuration.artifactFiles(): FileCollection { - return incoming.artifactView { viewConfiguration -> - viewConfiguration.isLenient = true - viewConfiguration.componentFilter { it is ModuleComponentIdentifier } - }.files - } + protected fun Configuration.artifactFiles(): FileCollection = + incoming + .artifactView { viewConfiguration -> + viewConfiguration.isLenient = true + viewConfiguration.componentFilter { it is ModuleComponentIdentifier } + }.files } diff --git a/plugin/gradle8/src/main/kotlin/DependencyExtractor.gradle8.kt b/plugin/gradle8/src/main/kotlin/DependencyExtractor.gradle8.kt index 6d360e0..6513ad1 100644 --- a/plugin/gradle8/src/main/kotlin/DependencyExtractor.gradle8.kt +++ b/plugin/gradle8/src/main/kotlin/DependencyExtractor.gradle8.kt @@ -18,12 +18,14 @@ object DependencyExtractorApplierG8 : DependencyExtractorApplier { extractor: DependencyExtractor, ) { val serviceProvider = - gradle.sharedServices.registerIfAbsent( - "nixDependencyExtractor", - DependencyExtractorService::class.java, - ) {}.map { service -> - service.apply { this.extractor = extractor } - } + gradle.sharedServices + .registerIfAbsent( + "nixDependencyExtractor", + DependencyExtractorService::class.java, + ) {} + .map { service -> + service.apply { this.extractor = extractor } + } gradle.service().onOperationCompletion(serviceProvider) } @@ -31,7 +33,9 @@ object DependencyExtractorApplierG8 : DependencyExtractorApplier { @Suppress("UnstableApiUsage") internal abstract class DependencyExtractorService : - BuildService, BuildOperationListener, AutoCloseable { + BuildService, + BuildOperationListener, + AutoCloseable { var extractor: DependencyExtractor? = null override fun started( diff --git a/plugin/gradle8/src/main/kotlin/ResolveAllArtifacts.gradle8.kt b/plugin/gradle8/src/main/kotlin/ResolveAllArtifacts.gradle8.kt index 404170b..f2f0d2e 100644 --- a/plugin/gradle8/src/main/kotlin/ResolveAllArtifacts.gradle8.kt +++ b/plugin/gradle8/src/main/kotlin/ResolveAllArtifacts.gradle8.kt @@ -23,13 +23,12 @@ abstract class ResolveProjectDependenciesTaskG8 ) : ResolveProjectDependenciesTask() { private val artifactFiles = Cached.of { artifactFiles() } - private fun artifactFiles(): FileCollection { - return objects.fileCollection().from( + private fun artifactFiles(): FileCollection = + objects.fileCollection().from( getReportableConfigurations().map { configuration -> configuration.artifactFiles() }, ) - } @TaskAction fun action() { diff --git a/plugin/gradle80/src/main/kotlin/Gradle2NixPlugin.gradle80.kt b/plugin/gradle80/src/main/kotlin/Gradle2NixPlugin.gradle80.kt index e39189f..b925142 100644 --- a/plugin/gradle80/src/main/kotlin/Gradle2NixPlugin.gradle80.kt +++ b/plugin/gradle80/src/main/kotlin/Gradle2NixPlugin.gradle80.kt @@ -1,7 +1,8 @@ package org.nixos.gradle2nix -abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin( - GradleCacheAccessFactoryG80, - DependencyExtractorApplierG8, - ResolveAllArtifactsApplierG8, -) +abstract class Gradle2NixPlugin : + AbstractGradle2NixPlugin( + GradleCacheAccessFactoryG80, + DependencyExtractorApplierG8, + ResolveAllArtifactsApplierG8, + ) diff --git a/plugin/gradle80/src/main/kotlin/GradleCacheAccess.gradle80.kt b/plugin/gradle80/src/main/kotlin/GradleCacheAccess.gradle80.kt index 67cb510..db65a4e 100644 --- a/plugin/gradle80/src/main/kotlin/GradleCacheAccess.gradle80.kt +++ b/plugin/gradle80/src/main/kotlin/GradleCacheAccess.gradle80.kt @@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider import org.gradle.api.invocation.Gradle object GradleCacheAccessFactoryG80 : GradleCacheAccessFactory { - override fun create(gradle: Gradle): GradleCacheAccess { - return GradleCacheAccessG80(gradle) - } + override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessG80(gradle) } -class GradleCacheAccessG80(gradle: Gradle) : GradleCacheAccess { +class GradleCacheAccessG80( + gradle: Gradle, +) : GradleCacheAccess { private val artifactCachesProvider = gradle.service() override fun useCache(block: () -> Unit) { diff --git a/plugin/gradle81/src/main/kotlin/Gradle2NixPlugin.gradle81.kt b/plugin/gradle81/src/main/kotlin/Gradle2NixPlugin.gradle81.kt index c4c79dd..b498ebf 100644 --- a/plugin/gradle81/src/main/kotlin/Gradle2NixPlugin.gradle81.kt +++ b/plugin/gradle81/src/main/kotlin/Gradle2NixPlugin.gradle81.kt @@ -1,7 +1,8 @@ package org.nixos.gradle2nix -abstract class Gradle2NixPlugin : AbstractGradle2NixPlugin( - GradleCacheAccessFactoryG81, - DependencyExtractorApplierG8, - ResolveAllArtifactsApplierG8, -) +abstract class Gradle2NixPlugin : + AbstractGradle2NixPlugin( + GradleCacheAccessFactoryG81, + DependencyExtractorApplierG8, + ResolveAllArtifactsApplierG8, + ) diff --git a/plugin/gradle81/src/main/kotlin/GradleCacheAccess.gradle81.kt b/plugin/gradle81/src/main/kotlin/GradleCacheAccess.gradle81.kt index d247f1a..8c1488d 100644 --- a/plugin/gradle81/src/main/kotlin/GradleCacheAccess.gradle81.kt +++ b/plugin/gradle81/src/main/kotlin/GradleCacheAccess.gradle81.kt @@ -4,12 +4,12 @@ import org.gradle.api.internal.artifacts.ivyservice.ArtifactCachesProvider import org.gradle.api.invocation.Gradle object GradleCacheAccessFactoryG81 : GradleCacheAccessFactory { - override fun create(gradle: Gradle): GradleCacheAccess { - return GradleCacheAccessG81(gradle) - } + override fun create(gradle: Gradle): GradleCacheAccess = GradleCacheAccessG81(gradle) } -class GradleCacheAccessG81(gradle: Gradle) : GradleCacheAccess { +class GradleCacheAccessG81( + gradle: Gradle, +) : GradleCacheAccess { private val artifactCachesProvider = gradle.service() override fun useCache(block: () -> Unit) {