This commit is contained in:
Tad Fisher
2023-12-19 13:52:14 -08:00
parent 6da87262a4
commit 8ceeeb9611
69 changed files with 5970 additions and 13633 deletions

View File

@@ -25,6 +25,8 @@
, fetchs3
, fetchurl
, gradleGen
, runCommandLocal
, symlinkJoin
, writeText
, writeTextDir
}:
@@ -32,7 +34,7 @@
{
# Path to the environment spec generated by gradle2nix (e.g. gradle-env.json).
envSpec
, pname ? null
, pname ? "project"
, version ? null
, enableParallelBuilding ? true
# Arguments to Gradle used to build the project in buildPhase.
@@ -52,9 +54,10 @@
# `{ urls, sha256 }` and fetch into the Nix store. For example:
#
# {
# s3 = { urls, sha256 }: fetchs3 {
# s3 = { name, urls, hash }: fetchs3 {
# s3url = builtins.head urls;
# inherit sha256;
# # TODO This doesn't work without patching fetchs3 to accept SRI hashes
# inherit name hash;
# region = "us-west-2";
# credentials = {
# access_key_id = "foo";
@@ -67,7 +70,7 @@
let
inherit (builtins)
attrValues concatStringsSep filter fromJSON getAttr head match
attrValues concatStringsSep elemAt filter fromJSON getAttr head match
replaceStrings sort;
inherit (lib)
@@ -75,162 +78,185 @@ let
mapAttrsToList optionalString readFile removeSuffix unique versionAtLeast
versionOlder;
inherit (lib.strings) sanitizeDerivationName;
toCoordinates = id:
let
coords = builtins.split ":" id;
in {
group = elemAt coords 0;
module = elemAt coords 2;
};
fetchers' = {
http = fetchurl;
https = fetchurl;
s3 = { urls, sha256 }: fetchs3 {
s3url = head urls;
inherit sha256;
};
} // fetchers;
# Fetch urls using the scheme for the first entry only; there isn't a
# straightforward way to tell Nix to try multiple fetchers in turn
# and short-circuit on the first successful fetch.
fetch = { urls, sha256 }:
fetch = _: { urls, hash }:
let
first = head urls;
scheme = head (builtins.match "([a-z0-9+.-]+)://.*" first);
fetch' = getAttr scheme fetchers';
urls' = filter (hasPrefix scheme) urls;
in
fetch' { urls = urls'; inherit sha256; };
fetch' { urls = urls'; inherit hash; };
mkDep = { name, path, urls, sha256, ... }: stdenv.mkDerivation {
inherit name;
src = fetch {
inherit urls sha256;
};
phases = "installPhase";
installPhase = ''
mkdir -p $out/${path}
ln -s $src $out/${path}/${name}
'';
};
mkModuleMetadata = deps:
mkDep = id: version: artifacts:
let
ids = filter
(id: id.type == "pom")
(map (dep: dep.id) deps);
modules = groupBy'
(meta: id:
let
isNewer = versionOlder meta.latest id.version;
isNewerRelease =
!(hasSuffix "-SNAPSHOT" id.version) &&
versionOlder meta.release id.version;
in {
groupId = id.group;
artifactId = id.name;
latest = if isNewer then id.version else meta.latest;
release = if isNewerRelease then id.version else meta.release;
versions = meta.versions ++ [id.version];
}
)
{
latest = "";
release = "";
versions = [];
}
(id: "${replaceStrings ["."] ["/"] id.group}/${id.name}/maven-metadata.xml")
ids;
coords = toCoordinates id;
modulePath = "${replaceStrings ["."] ["/"] coords.group}/${coords.module}/${version}";
in
attrValues (mapAttrs (path: meta:
let
versions' = sort versionOlder (unique meta.versions);
in
with meta; writeTextDir path ''
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1">
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<versioning>
${optionalString (latest != "") "<latest>${latest}</latest>"}
${optionalString (release != "") "<release>${release}</release>"}
<versions>
${concatMapStringsSep "\n " (v: "<version>${v}</version>") versions'}
</versions>
</versioning>
</metadata>
''
) modules);
stdenv.mkDerivation {
pname = "${coords.group}-${coords.module}";
version = version;
mkSnapshotMetadata = deps:
let
snapshotDeps = filter (dep: dep ? build && dep ? timestamp) deps;
srcs = mapAttrsToList fetch artifacts;
modules = groupBy'
(meta: dep:
let
id = dep.id;
isNewer = dep.build > meta.buildNumber;
# Timestamp values can be bogus, e.g. jitpack.io
updated = if (match "[0-9]{8}\.[0-9]{6}" dep.timestamp) != null
then replaceStrings ["."] [""] dep.timestamp
else "";
in {
groupId = id.group;
artifactId = id.name;
version = id.version;
timestamp = if isNewer then dep.timestamp else meta.timestamp;
buildNumber = if isNewer then dep.build else meta.buildNumber;
lastUpdated = if isNewer then updated else meta.lastUpdated;
versions = meta.versions or [] ++ [{
classifier = id.classifier or "";
extension = id.extension;
value = "${removeSuffix "-SNAPSHOT" id.version}-${dep.timestamp}-${toString dep.build}";
updated = updated;
}];
}
)
{
timestamp = "";
buildNumber = -1;
lastUpdated = "";
}
(dep: "${replaceStrings ["."] ["/"] dep.id.group}/${dep.id.name}/${dep.id.version}/maven-metadata.xml")
snapshotDeps;
dontPatch = true;
dontConfigure = true;
dontBuild = true;
dontFixup = true;
dontInstall = true;
mkSnapshotVersion = version: ''
<snapshotVersion>
${optionalString (version.classifier != "") "<classifier>${version.classifier}</classifier>"}
<extension>${version.extension}</extension>
<value>${version.value}</value>
${optionalString (version.updated != "") "<updated>${version.updated}</updated>"}
</snapshotVersion>
'';
preUnpack = ''
mkdir -p "$out/${modulePath}"
'';
in
attrValues (mapAttrs (path: meta:
with meta; writeTextDir path ''
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1">
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
<versioning>
<snapshot>
${optionalString (timestamp != "") "<timestamp>${timestamp}</timestamp>"}
${optionalString (buildNumber != -1) "<buildNumber>${toString buildNumber}</buildNumber>"}
</snapshot>
${optionalString (lastUpdated != "") "<lastUpdated>${lastUpdated}</lastUpdated>"}
<snapshotVersions>
${concatMapStringsSep "\n " mkSnapshotVersion versions}
</snapshotVersions>
</versioning>
</metadata>
''
) modules);
unpackCmd = ''
cp "$curSrc" "$out/${modulePath}/$(stripHash "$curSrc")"
'';
mkRepo = project: type: deps: buildEnv {
name = "${project}-gradle-${type}-env";
paths = map mkDep deps ++ mkModuleMetadata deps ++ mkSnapshotMetadata deps;
sourceRoot = ".";
preferLocalBuild = true;
allowSubstitutes = false;
};
mkModule = id: versions:
mapAttrsToList (version: artifacts: mkDep id version artifacts) versions;
mkModuleMetadata = id: versions:
let
modules = groupBy'
(meta: id:
let
isNewer = versionOlder meta.latest id.version;
isNewerRelease =
!(hasSuffix "-SNAPSHOT" id.version) &&
versionOlder meta.release id.version;
in {
groupId = id.group;
artifactId = id.name;
latest = if isNewer then id.version else meta.latest;
release = if isNewerRelease then id.version else meta.release;
versions = meta.versions ++ [id.version];
}
)
{
latest = "";
release = "";
versions = [];
}
(id: "${replaceStrings ["."] ["/"] id.group}/${id.name}/maven-metadata.xml")
ids;
in
attrValues (mapAttrs (path: meta:
let
versions' = sort versionOlder (unique meta.versions);
in
with meta; writeTextDir path ''
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1">
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<versioning>
${optionalString (latest != "") "<latest>${latest}</latest>"}
${optionalString (release != "") "<release>${release}</release>"}
<versions>
${concatMapStringsSep "\n " (v: "<version>${v}</version>") versions'}
</versions>
</versioning>
</metadata>
''
) modules);
# mkSnapshotMetadata = deps:
# let
# snapshotDeps = filter (dep: dep ? build && dep ? timestamp) deps;
# modules = groupBy'
# (meta: dep:
# let
# id = dep.id;
# isNewer = dep.build > meta.buildNumber;
# # Timestamp values can be bogus, e.g. jitpack.io
# updated = if (match "[0-9]{8}\.[0-9]{6}" dep.timestamp) != null
# then replaceStrings ["."] [""] dep.timestamp
# else "";
# in {
# groupId = id.group;
# artifactId = id.name;
# version = id.version;
# timestamp = if isNewer then dep.timestamp else meta.timestamp;
# buildNumber = if isNewer then dep.build else meta.buildNumber;
# lastUpdated = if isNewer then updated else meta.lastUpdated;
# versions = meta.versions or [] ++ [{
# classifier = id.classifier or "";
# extension = id.extension;
# value = "${removeSuffix "-SNAPSHOT" id.version}-${dep.timestamp}-${toString dep.build}";
# updated = updated;
# }];
# }
# )
# {
# timestamp = "";
# buildNumber = -1;
# lastUpdated = "";
# }
# (dep: "${replaceStrings ["."] ["/"] dep.id.group}/${dep.id.name}/${dep.id.version}/maven-metadata.xml")
# snapshotDeps;
# mkSnapshotVersion = version: ''
# <snapshotVersion>
# ${optionalString (version.classifier != "") "<classifier>${version.classifier}</classifier>"}
# <extension>${version.extension}</extension>
# <value>${version.value}</value>
# ${optionalString (version.updated != "") "<updated>${version.updated}</updated>"}
# </snapshotVersion>
# '';
# in
# attrValues (mapAttrs (path: meta:
# with meta; writeTextDir path ''
# <?xml version="1.0" encoding="UTF-8"?>
# <metadata modelVersion="1.1">
# <groupId>${groupId}</groupId>
# <artifactId>${artifactId}</artifactId>
# <version>${version}</version>
# <versioning>
# <snapshot>
# ${optionalString (timestamp != "") "<timestamp>${timestamp}</timestamp>"}
# ${optionalString (buildNumber != -1) "<buildNumber>${toString buildNumber}</buildNumber>"}
# </snapshot>
# ${optionalString (lastUpdated != "") "<lastUpdated>${lastUpdated}</lastUpdated>"}
# <snapshotVersions>
# ${concatMapStringsSep "\n " mkSnapshotVersion versions}
# </snapshotVersions>
# </versioning>
# </metadata>
# ''
# ) modules);
mkRepo = name: deps: symlinkJoin {
name = "${name}-gradle-env";
# paths = map mkDep deps ++ mkModuleMetadata deps ++ mkSnapshotMetadata deps;
paths = mapAttrsToList mkModule deps;
};
mkInitScript = projectSpec: gradle:
@@ -264,12 +290,12 @@ let
static def offlineRepo(RepositoryHandler repositories, String env, String path) {
repositories.clear()
repositories.maven {
name "Nix''${env.capitalize()}MavenOffline"
name "Nix''${env.capitalize()}Offline"
url path
metadataSources {
it.gradleMetadata()
it.mavenPom()
it.artifact()
it.
}
}
repositories.ivy {
@@ -279,7 +305,6 @@ let
metadataSources {
it.gradleMetadata()
it.ivyDescriptor()
it.artifact()
}
}
}
@@ -371,29 +396,31 @@ let
buildRootProject = buildProject projectEnv gradleFlags;
in stdenv.mkDerivation (args // {
# in stdenv.mkDerivation (args // {
inherit pname version;
# inherit pname version;
nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ projectEnv.gradle ];
# nativeBuildInputs = (args.nativeBuildInputs or []) ++ [ projectEnv.gradle ];
buildPhase = args.buildPhase or ''
runHook preBuild
# buildPhase = args.buildPhase or ''
# runHook preBuild
(
set -eux
# (
# set -eux
# Work around https://github.com/gradle/gradle/issues/1055
TMPHOME="$(mktemp -d)"
mkdir -p "$TMPHOME/init.d"
export GRADLE_USER_HOME="$TMPHOME"
# # Work around https://github.com/gradle/gradle/issues/1055
# TMPHOME="$(mktemp -d)"
# mkdir -p "$TMPHOME/init.d"
# export GRADLE_USER_HOME="$TMPHOME"
${buildIncludedProjects}
${buildRootProject}
)
# ${buildIncludedProjects}
# ${buildRootProject}
# )
runHook postBuild
'';
# runHook postBuild
# '';
dontStrip = true;
})
# dontStrip = true;
# })
in mkRepo pname (fromJSON (readFile envSpec))