mirror of
https://github.com/tadfisher/gradle2nix.git
synced 2026-01-11 15:30:38 -05:00
First stab
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.idea/
|
||||
.gradle/
|
||||
*.iml
|
||||
**/build/
|
||||
result
|
||||
45
app/build.gradle.kts
Normal file
45
app/build.gradle.kts
Normal file
@@ -0,0 +1,45 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.3.21"
|
||||
application
|
||||
}
|
||||
|
||||
group = "org.nixos"
|
||||
version = "1.0.0-SNAPSHOT"
|
||||
|
||||
application {
|
||||
mainClassName = "org.nixos.gradle2nix.MainKt"
|
||||
applicationName = "gradle2nix"
|
||||
applicationDefaultJvmArgs += "-Dorg.nixos.gradle2nix.initScript=@APP_HOME@/gradle/init.gradle"
|
||||
applicationDistribution
|
||||
.from(tasks.getByPath(":plugin:shadowJar"))
|
||||
.into("gradle")
|
||||
.rename("plugin.*\\.jar", "plugin.jar")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("org.gradle:gradle-tooling-api:${gradle.gradleVersion}")
|
||||
implementation("com.github.ajalt:clikt:1.7.0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url = uri("https://repo.gradle.org/gradle/libs-releases") }
|
||||
}
|
||||
|
||||
tasks {
|
||||
val startScripts by existing(CreateStartScripts::class)
|
||||
startScripts {
|
||||
doLast {
|
||||
unixScript.writeText(unixScript.readText().replace("@APP_HOME@", "\$APP_HOME"))
|
||||
windowsScript.writeText(windowsScript.readText().replace("@APP_HOME@", "%APP_HOME%"))
|
||||
}
|
||||
}
|
||||
withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
app/src/dist/gradle/init.gradle
vendored
Normal file
7
app/src/dist/gradle/init.gradle
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
initscript {
|
||||
dependencies {
|
||||
classpath files("plugin.jar")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: org.nixos.gradle2nix.Gradle2NixPlugin
|
||||
45
app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt
Normal file
45
app/src/main/kotlin/org/nixos/gradle2nix/GradleRunner.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.tooling.GradleConnector
|
||||
import java.io.File
|
||||
|
||||
class GradleRunner(
|
||||
private val projectDir: File,
|
||||
private val useWrapper: Boolean,
|
||||
private val gradleVersion: String?,
|
||||
private val configurations: List<String>
|
||||
) {
|
||||
companion object {
|
||||
val initScript: String = System.getProperty("org.nixos.gradle2nix.initScript")
|
||||
}
|
||||
|
||||
fun runGradle() {
|
||||
GradleConnector.newConnector()
|
||||
.apply {
|
||||
if (useWrapper) {
|
||||
useBuildDistribution()
|
||||
} else if (gradleVersion != null) {
|
||||
useGradleVersion(gradleVersion)
|
||||
}
|
||||
}
|
||||
.forProjectDirectory(projectDir)
|
||||
.connect()
|
||||
.use { connection ->
|
||||
connection.newBuild()
|
||||
.withArguments("--init-script", initScript)
|
||||
.apply {
|
||||
if (configurations.isNotEmpty()) {
|
||||
withArguments(
|
||||
"-Dorg.nixos.gradle2nix.configurations=${configurations.joinToString(
|
||||
","
|
||||
)}"
|
||||
)
|
||||
}
|
||||
}
|
||||
.forTasks("nixGradleEnv")
|
||||
.setStandardOutput(System.out)
|
||||
.setStandardError(System.err)
|
||||
.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
25
app/src/main/kotlin/org/nixos/gradle2nix/Main.kt
Normal file
25
app/src/main/kotlin/org/nixos/gradle2nix/Main.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.github.ajalt.clikt.core.CliktCommand
|
||||
import com.github.ajalt.clikt.parameters.arguments.argument
|
||||
import com.github.ajalt.clikt.parameters.arguments.defaultLazy
|
||||
import com.github.ajalt.clikt.parameters.options.flag
|
||||
import com.github.ajalt.clikt.parameters.options.multiple
|
||||
import com.github.ajalt.clikt.parameters.options.option
|
||||
import com.github.ajalt.clikt.parameters.types.file
|
||||
import java.io.File
|
||||
|
||||
class Main : CliktCommand() {
|
||||
val wrapper: Boolean by option(help = "Use the project's gradle wrapper for building").flag()
|
||||
val gradleVersion: String? by option(help = "Use a specific Gradle version")
|
||||
val configurations: List<String> by option(help = "Project configuration(s)").multiple()
|
||||
val projectDir: File by argument(help = "Path to the project root")
|
||||
.file(exists = true, fileOkay = false, folderOkay = true, readable = true)
|
||||
.defaultLazy { File(".") }
|
||||
|
||||
override fun run() {
|
||||
GradleRunner(projectDir, wrapper, gradleVersion, configurations).runGradle()
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) = Main().main(args)
|
||||
10
build.gradle.kts
Normal file
10
build.gradle.kts
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
base
|
||||
}
|
||||
|
||||
tasks {
|
||||
wrapper {
|
||||
gradleVersion = "5.3"
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
}
|
||||
71
default.nix
Normal file
71
default.nix
Normal file
@@ -0,0 +1,71 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
with pkgs;
|
||||
|
||||
let
|
||||
gradleEnvJson = builtins.fromJSON (builtins.readFile ./gradle/nix/gradle-env.json);
|
||||
gradleDist = builtins.fromJSON (builtins.readFile ./gradle/nix/gradle-dist.json);
|
||||
|
||||
mkGradleEnv = callPackage ./gradle-env.nix {};
|
||||
gradle = pkgs.gradleGen.gradleGen {
|
||||
name = "gradle-dist-${gradleDist.version}-${gradleDist.type}";
|
||||
src = pkgs.fetchurl {
|
||||
inherit (gradleDist) url sha256;
|
||||
};
|
||||
inherit (gradleDist) nativeVersion;
|
||||
};
|
||||
|
||||
maven = r: ''maven { url = uri("${r}") }'';
|
||||
|
||||
projects = lib.mapAttrsToList (path: envs: {
|
||||
inherit path;
|
||||
config = ''
|
||||
buildscript {
|
||||
repositories {
|
||||
clear()
|
||||
${maven (mkGradleEnv envs.buildscript)}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
clear()
|
||||
${maven (mkGradleEnv envs.project)}
|
||||
}
|
||||
'';
|
||||
}) gradleEnvJson;
|
||||
|
||||
initScript = pkgs.writeText "init.gradle" ''
|
||||
gradle.settingsEvaluated {
|
||||
it.pluginManagement.repositories {
|
||||
clear()
|
||||
${maven (mkGradleEnv gradleEnvJson.":".plugins)}
|
||||
}
|
||||
}
|
||||
gradle.projectsLoaded {
|
||||
${lib.concatMapStringsSep "\n" (p: ''
|
||||
rootProject.project("${p.path}") {
|
||||
${p.config}
|
||||
}
|
||||
'') projects}
|
||||
}
|
||||
'';
|
||||
|
||||
in stdenv.mkDerivation rec {
|
||||
name = "gradle2nix-${version}";
|
||||
version = "1.0";
|
||||
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = [ gradle ];
|
||||
|
||||
buildPhase = ''
|
||||
export GRADLE_USER_HOME=$(mktemp -d)
|
||||
gradle --offline --no-daemon --info --full-stacktrace --init-script ${initScript} installDist
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r app/build/install/gradle2nix/* $out/
|
||||
'';
|
||||
|
||||
dontStrip = true;
|
||||
}
|
||||
51
gradle-env.nix
Normal file
51
gradle-env.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
# This file is generated by gradle2nix.
|
||||
|
||||
{ stdenvNoCC, lib, buildEnv, fetchurl }:
|
||||
|
||||
{ path, env, repositories, artifacts }@args:
|
||||
|
||||
let
|
||||
mkPath = artifact: with artifact; lib.concatStringsSep "/" [
|
||||
(lib.replaceChars ["."] ["/"] artifact.groupId)
|
||||
artifact.artifactId
|
||||
artifact.version
|
||||
];
|
||||
|
||||
mkFilename = artifact: with artifact;
|
||||
"${artifactId}-${version}${lib.optionalString (classifier != "") "-${classifier}"}.${extension}";
|
||||
|
||||
mkArtifactUrl = base: artifact:
|
||||
"${lib.removeSuffix "/" base}/${mkPath artifact}/${mkFilename artifact}";
|
||||
|
||||
fetchArtifact = artifact:
|
||||
let
|
||||
artifactPath = mkPath artifact;
|
||||
artifactName = mkFilename artifact;
|
||||
in stdenvNoCC.mkDerivation rec {
|
||||
name = with artifact; lib.concatStrings [
|
||||
(lib.replaceChars ["."] ["_"] groupId) "-"
|
||||
(lib.replaceChars ["."] ["_"] artifactId) "-"
|
||||
version
|
||||
(lib.optionalString (classifier != "") "-${classifier}")
|
||||
"-" extension
|
||||
];
|
||||
|
||||
src = fetchurl {
|
||||
name = mkFilename artifact;
|
||||
urls = map (url: mkArtifactUrl url artifact) repositories;
|
||||
inherit (artifact) sha256;
|
||||
};
|
||||
|
||||
phases = "installPhase fixupPhase";
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/${artifactPath}
|
||||
ln -s ${src} $out/${artifactPath}/${artifactName}
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
buildEnv {
|
||||
name = "gradle-env-${builtins.replaceStrings [":"] ["-"] path}-${env}";
|
||||
paths = map fetchArtifact artifacts;
|
||||
}
|
||||
7
gradle/nix/gradle-dist.json
Normal file
7
gradle/nix/gradle-dist.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "5.3",
|
||||
"type": "all",
|
||||
"url": "https://services.gradle.org/distributions/gradle-5.3-all.zip",
|
||||
"sha256": "f4d820c2a9685710eba5b92f10e0e4fb20e0d6c0dd1f46971e658160f25e7147",
|
||||
"nativeVersion": "0.17"
|
||||
}
|
||||
1732
gradle/nix/gradle-env.json
Normal file
1732
gradle/nix/gradle-env.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
172
gradlew
vendored
Executable file
172
gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
gradlew.bat
vendored
Normal file
84
gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
34
plugin/build.gradle.kts
Normal file
34
plugin/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
id("com.github.johnrengelman.shadow") version "4.0.0"
|
||||
`java-gradle-plugin`
|
||||
`kotlin-dsl`
|
||||
`maven-publish`
|
||||
kotlin("kapt") version embeddedKotlinVersion
|
||||
}
|
||||
|
||||
group = "org.nixos"
|
||||
version = "1.0.0-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("org.apache.maven:maven-model:3.5.4")
|
||||
implementation("org.apache.maven:maven-model-builder:3.5.4")
|
||||
implementation("com.squareup.okio:okio:2.2.2")
|
||||
implementation("com.squareup.moshi:moshi:1.8.0")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:1.8.0")
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
register("gradle2nix") {
|
||||
id = "org.nixos.gradle2nix"
|
||||
displayName = "gradle2nix"
|
||||
description = "Create Nix configurations suitable for reproducible packaging"
|
||||
implementationClass = "org.nixos.gradle2nix.Gradle2NixPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
137
plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt
Normal file
137
plugin/src/main/kotlin/org/nixos/gradle2nix/Gradle2NixPlugin.kt
Normal file
@@ -0,0 +1,137 @@
|
||||
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.file.RegularFile
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.internal.DocumentationRegistry
|
||||
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme
|
||||
import org.gradle.api.internal.plugins.PluginRegistry
|
||||
import org.gradle.api.invocation.Gradle
|
||||
import org.gradle.api.provider.Provider
|
||||
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.property
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.gradle.plugin.management.PluginRequest
|
||||
import org.gradle.plugin.use.internal.PluginDependencyResolutionServices
|
||||
import org.gradle.plugin.use.internal.PluginResolverFactory
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
open class Gradle2NixPlugin : Plugin<Gradle> {
|
||||
override fun apply(gradle: Gradle) {
|
||||
val configurationNames: List<String> =
|
||||
System.getProperty("org.nixos.gradle2nix.configurations")?.split(",") ?: emptyList()
|
||||
|
||||
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 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)
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectPlugins(gradle: Gradle): List<PluginRequest> {
|
||||
val pluginRequests = mutableListOf<PluginRequest>()
|
||||
gradle.settingsEvaluated {
|
||||
pluginManagement.resolutionStrategy.eachPlugin {
|
||||
if (requested.id.namespace != null && requested.id.namespace != "org.gradle") {
|
||||
pluginRequests.add(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
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("""
|
||||
Failed to find native-platform jar in ${gradle.gradleHomeDir}.
|
||||
|
||||
Ask Tad to fix this.
|
||||
""".trimIndent())
|
||||
)
|
||||
}
|
||||
val gradleDistTask =
|
||||
gradle.rootProject.tasks.register("nixGradleDist", NixGradleDist::class) {
|
||||
this.gradleDist.set(gradleDist)
|
||||
outputDir.set(extension.outputDir)
|
||||
}
|
||||
gradleEnv.configure {
|
||||
dependsOn(gradleDistTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
connect()
|
||||
getInputStream().source().buffer().use { source ->
|
||||
source.readUtf8()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val nativePlatformJarRegex = Regex("""native-platform-(\d\.\d+)\.jar""")
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import java.lang.IllegalStateException
|
||||
import java.net.URI
|
||||
|
||||
open class NixBuildscriptEnv : NixEnv() {
|
||||
@InputFile
|
||||
val pluginEnvFile = project.objects.fileProperty()
|
||||
|
||||
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"
|
||||
}
|
||||
73
plugin/src/main/kotlin/org/nixos/gradle2nix/NixEnv.kt
Normal file
73
plugin/src/main/kotlin/org/nixos/gradle2nix/NixEnv.kt
Normal file
@@ -0,0 +1,73 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.squareup.moshi.Moshi
|
||||
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.OutputDirectory
|
||||
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.objects.directoryProperty()
|
||||
.convention(project.layout.buildDirectory.dir("nix"))
|
||||
|
||||
@OutputFile
|
||||
val outputFile = project.objects.fileProperty()
|
||||
.convention(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" }
|
||||
}
|
||||
44
plugin/src/main/kotlin/org/nixos/gradle2nix/NixGradleDist.kt
Normal file
44
plugin/src/main/kotlin/org/nixos/gradle2nix/NixGradleDist.kt
Normal file
@@ -0,0 +1,44 @@
|
||||
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.objects.directoryProperty()
|
||||
|
||||
@OutputFile
|
||||
val outputFile = project.objects.fileProperty()
|
||||
.convention(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
|
||||
58
plugin/src/main/kotlin/org/nixos/gradle2nix/NixGradleEnv.kt
Normal file
58
plugin/src/main/kotlin/org/nixos/gradle2nix/NixGradleEnv.kt
Normal file
@@ -0,0 +1,58 @@
|
||||
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.file.RegularFile
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.listProperty
|
||||
|
||||
open class NixGradleEnv : DefaultTask() {
|
||||
|
||||
@InputFiles
|
||||
val inputEnvs = project.objects.fileCollection()
|
||||
|
||||
@Internal
|
||||
val outputDir = project.objects.directoryProperty()
|
||||
|
||||
@OutputFile
|
||||
val outputFile = project.objects.fileProperty()
|
||||
.convention(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()
|
||||
}
|
||||
}
|
||||
}
|
||||
110
plugin/src/main/kotlin/org/nixos/gradle2nix/NixPluginEnv.kt
Normal file
110
plugin/src/main/kotlin/org/nixos/gradle2nix/NixPluginEnv.kt
Normal file
@@ -0,0 +1,110 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme
|
||||
import org.gradle.api.internal.plugins.PluginImplementation
|
||||
import org.gradle.plugin.management.PluginRequest
|
||||
import org.gradle.plugin.management.internal.PluginRequestInternal
|
||||
import org.gradle.plugin.use.PluginId
|
||||
import org.gradle.plugin.use.internal.PluginDependencyResolutionServices
|
||||
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(
|
||||
private val pluginDependencyResolutionServices: PluginDependencyResolutionServices,
|
||||
versionSelectorScheme: VersionSelectorScheme,
|
||||
private val pluginRequests: Collection<PluginRequest>
|
||||
) : NixEnv() {
|
||||
private val repositories by lazy {
|
||||
pluginDependencyResolutionServices.resolveRepositoryHandler
|
||||
}
|
||||
|
||||
private val artifactRepositoriesPluginResolver = ArtifactRepositoriesPluginResolver(
|
||||
pluginDependencyResolutionServices,
|
||||
versionSelectorScheme
|
||||
)
|
||||
|
||||
private val resolver by lazy {
|
||||
Resolver(
|
||||
pluginDependencyResolutionServices.configurationContainer,
|
||||
pluginDependencyResolutionServices.dependencyHandler,
|
||||
logger
|
||||
)
|
||||
}
|
||||
|
||||
private val pluginResult by lazy {
|
||||
PluginResult().apply {
|
||||
for (request in pluginRequests.filterIsInstance<PluginRequestInternal>()) {
|
||||
artifactRepositoriesPluginResolver.resolve(request, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val pluginContext by lazy {
|
||||
PluginContext().apply {
|
||||
for (result in pluginResult.found) result.execute(this)
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
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>()
|
||||
|
||||
override fun notFound(sourceDescription: String?, notFoundMessage: 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)
|
||||
}
|
||||
}
|
||||
|
||||
private class PluginContext : PluginResolveContext {
|
||||
val dependencies = mutableSetOf<ExternalModuleDependency>()
|
||||
val repositories = mutableSetOf<String>()
|
||||
|
||||
override fun add(plugin: PluginImplementation<*>) {
|
||||
println("add: $plugin")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
41
plugin/src/main/kotlin/org/nixos/gradle2nix/NixProjectEnv.kt
Normal file
41
plugin/src/main/kotlin/org/nixos/gradle2nix/NixProjectEnv.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.kotlin.dsl.setProperty
|
||||
import java.net.URI
|
||||
|
||||
open class NixProjectEnv : NixEnv() {
|
||||
@Input @Optional
|
||||
val configurations = project.objects.setProperty<String>()
|
||||
|
||||
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"
|
||||
}
|
||||
166
plugin/src/main/kotlin/org/nixos/gradle2nix/Resolver.kt
Normal file
166
plugin/src/main/kotlin/org/nixos/gradle2nix/Resolver.kt
Normal file
@@ -0,0 +1,166 @@
|
||||
package org.nixos.gradle2nix
|
||||
|
||||
import okio.ByteString
|
||||
import okio.HashingSource
|
||||
import okio.blackholeSink
|
||||
import okio.buffer
|
||||
import okio.source
|
||||
import org.apache.maven.model.Parent
|
||||
import org.apache.maven.model.Repository
|
||||
import org.apache.maven.model.building.DefaultModelBuilderFactory
|
||||
import org.apache.maven.model.building.DefaultModelBuildingRequest
|
||||
import org.apache.maven.model.building.ModelBuildingRequest
|
||||
import org.apache.maven.model.building.ModelSource2
|
||||
import org.apache.maven.model.resolution.ModelResolver
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
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.maven.MavenModule
|
||||
import org.gradle.maven.MavenPomArtifact
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.net.URI
|
||||
|
||||
internal class Resolver(
|
||||
private val configurations: ConfigurationContainer,
|
||||
private val dependencies: DependencyHandler,
|
||||
private val logger: Logger
|
||||
) {
|
||||
private val mavenPomResolver = MavenPomResolver(configurations, dependencies)
|
||||
|
||||
fun resolveDependencies(configuration: Configuration): Set<Artifact> {
|
||||
if (!configuration.isCanBeResolved) {
|
||||
logger.warn("Cannot resolve configuration ${configuration.name}; ignoring.")
|
||||
return emptySet()
|
||||
}
|
||||
return configuration.resolvedConfiguration.resolvedArtifacts.mapTo(sortedSetOf()) {
|
||||
with (it) {
|
||||
Artifact(
|
||||
groupId = moduleVersion.id.group,
|
||||
artifactId = moduleVersion.id.name,
|
||||
version = moduleVersion.id.version,
|
||||
classifier = classifier ?: "",
|
||||
extension = extension,
|
||||
sha256 = sha256(file)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveDependencies(
|
||||
dependencies: Collection<Dependency>,
|
||||
includeTransitive: Boolean = false
|
||||
): Set<Artifact> {
|
||||
val configuration = configurations.detachedConfiguration(*(dependencies.toTypedArray()))
|
||||
configuration.isTransitive = includeTransitive
|
||||
return resolveDependencies(configuration)
|
||||
}
|
||||
|
||||
fun resolvePoms(configuration: Configuration): Set<Artifact> {
|
||||
return dependencies.createArtifactResolutionQuery()
|
||||
.forComponents(configuration.incoming.resolutionResult.allComponents.map { it.id })
|
||||
.withArtifacts(MavenModule::class.java, MavenPomArtifact::class.java)
|
||||
.execute()
|
||||
.resolvedComponents.asSequence()
|
||||
.flatMap { component ->
|
||||
val id = component.id
|
||||
if (id !is ModuleComponentIdentifier) {
|
||||
emptySequence()
|
||||
} else {
|
||||
component.getArtifacts(MavenPomArtifact::class.java).asSequence()
|
||||
.filterIsInstance<ResolvedArtifactResult>()
|
||||
.map { id to it }
|
||||
}
|
||||
}
|
||||
.flatMapTo(sortedSetOf()) { (id, artifact) ->
|
||||
sequenceOf(Artifact(
|
||||
groupId = id.group,
|
||||
artifactId = id.module,
|
||||
version = id.version,
|
||||
classifier = "",
|
||||
extension = artifact.file.extension,
|
||||
sha256 = sha256(artifact.file)
|
||||
)) + mavenPomResolver.resolve(artifact.file).asSequence()
|
||||
}
|
||||
}
|
||||
|
||||
fun resolvePoms(
|
||||
dependencies: Collection<Dependency>,
|
||||
includeTransitive: Boolean = false
|
||||
): Set<Artifact> {
|
||||
val configuration = configurations.detachedConfiguration(*(dependencies.toTypedArray()))
|
||||
configuration.isTransitive = includeTransitive
|
||||
return resolvePoms(configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private class MavenPomResolver(
|
||||
private val configurations: ConfigurationContainer,
|
||||
private val dependencies: DependencyHandler
|
||||
) : ModelResolver {
|
||||
private val modelBuilder = DefaultModelBuilderFactory().newInstance()
|
||||
private val resolvedDependencies = mutableSetOf<Artifact>()
|
||||
|
||||
@Synchronized
|
||||
fun resolve(pom: File): Set<Artifact> {
|
||||
resolvedDependencies.clear()
|
||||
modelBuilder.build(
|
||||
DefaultModelBuildingRequest()
|
||||
.setModelResolver(this)
|
||||
.setPomFile(pom)
|
||||
.setSystemProperties(System.getProperties())
|
||||
.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL)
|
||||
).effectiveModel
|
||||
return resolvedDependencies.toSet()
|
||||
}
|
||||
|
||||
override fun newCopy() = this
|
||||
|
||||
override fun resolveModel(
|
||||
groupId: String,
|
||||
artifactId: String,
|
||||
version: String
|
||||
): ModelSource2 {
|
||||
val file = configurations
|
||||
.detachedConfiguration(dependencies.create("$groupId:$artifactId:$version@pom"))
|
||||
.singleFile
|
||||
resolvedDependencies.add(Artifact(
|
||||
groupId = groupId,
|
||||
artifactId = artifactId,
|
||||
version = version,
|
||||
classifier = "",
|
||||
extension = file.extension,
|
||||
sha256 = sha256(file)
|
||||
))
|
||||
|
||||
return object : ModelSource2 {
|
||||
override fun getLocation(): String = file.absolutePath
|
||||
override fun getLocationURI(): URI = file.absoluteFile.toURI()
|
||||
override fun getRelatedSource(relPath: String?): ModelSource2? = null
|
||||
override fun getInputStream(): InputStream = file.inputStream()
|
||||
}
|
||||
}
|
||||
|
||||
override fun resolveModel(parent: Parent): ModelSource2 =
|
||||
resolveModel(parent.groupId, parent.artifactId, parent.version)
|
||||
|
||||
override fun resolveModel(dependency: org.apache.maven.model.Dependency): ModelSource2 =
|
||||
resolveModel(dependency.groupId, dependency.artifactId, dependency.version)
|
||||
|
||||
override fun addRepository(repository: Repository) {}
|
||||
|
||||
override fun addRepository(repository: Repository, replace: Boolean) {}
|
||||
}
|
||||
|
||||
fun sha256(file: File): String {
|
||||
val hashSource = HashingSource.sha256(file.source())
|
||||
val hash: ByteString = hashSource.buffer().use { source ->
|
||||
source.readAll(blackholeSink())
|
||||
hashSource.hash
|
||||
}
|
||||
return hash.base64()
|
||||
}
|
||||
51
plugin/src/main/resources/gradle-env.nix
Normal file
51
plugin/src/main/resources/gradle-env.nix
Normal file
@@ -0,0 +1,51 @@
|
||||
# This file is generated by gradle2nix.
|
||||
|
||||
{ stdenvNoCC, lib, buildEnv, fetchurl }:
|
||||
|
||||
{ name, repositories, dependencies }:
|
||||
|
||||
let
|
||||
mkPath = artifact: with artifact; lib.concatStringsSep "/" [
|
||||
(lib.replaceChars ["."] ["/"] artifact.groupId)
|
||||
artifact.artifactId
|
||||
artifact.version
|
||||
];
|
||||
|
||||
mkFilename = artifact: with artifact;
|
||||
"${artifactId}-${version}${lib.optionalString (classifier != "") "-${classifier}"}.${extension}";
|
||||
|
||||
mkArtifactUrl = base: artifact:
|
||||
"${lib.removeSuffix "/" base}/${mkPath artifact}/${mkFilename artifact}";
|
||||
|
||||
fetchArtifact = artifact:
|
||||
let
|
||||
artifactPath = mkPath artifact;
|
||||
artifactName = mkFilename artifact;
|
||||
in stdenvNoCC.mkDerivation rec {
|
||||
name = with artifact; lib.concatStrings [
|
||||
(lib.replaceChars ["."] ["_"] groupId) "-"
|
||||
(lib.replaceChars ["."] ["_"] artifactId) "-"
|
||||
version
|
||||
(lib.optionalString (classifier != "") "-${classifier}")
|
||||
"-" type
|
||||
];
|
||||
|
||||
src = fetchurl {
|
||||
name = mkFilename artifact;
|
||||
urls = map (url: mkArtifactUrl url artifact) repositories;
|
||||
inherit (artifact) sha256;
|
||||
};
|
||||
|
||||
phases = "installPhase fixupPhase";
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/${artifactPath}
|
||||
ln -s ${src} $out/${artifactPath}/${artifactName}
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
buildEnv {
|
||||
inherit name;
|
||||
paths = map fetchArtifact dependencies;
|
||||
}
|
||||
2
settings.gradle.kts
Normal file
2
settings.gradle.kts
Normal file
@@ -0,0 +1,2 @@
|
||||
include(":app")
|
||||
include(":plugin")
|
||||
Reference in New Issue
Block a user