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