{ lib, stdenv, fetchurl, substitute, symlinkJoin, }: { # Path to the lockfile generated by gradle2nix (e.g. gradle.lock). lockFile, # Override functions which fetch dependency artifacts. # Names in this set are URL schemes such as "https" or "s3". # Values are functions which take a dependency in the form # `{ urls, hash }` and fetch into the Nix store. For example: # # { # s3 = { name, urls, hash }: fetchs3 { # s3url = builtins.head urls; # # TODO This doesn't work without patching fetchs3 to accept SRI hashes # inherit name hash; # region = "us-west-2"; # credentials = { # access_key_id = "foo"; # secret_access_key = "bar"; # }; # }; # } fetchers ? { }, # Override artifacts in the offline Maven repository. # # This is an attrset is of the form: # # { # "${group}:${module}:${version}" = { # "${filename}" = ; # } # } # # The override function takes the original derivation from 'fetchers' (e.g. the result of # 'fetchurl') and produces a new derivation to replace it. # # Examples: # # 1. Replace a dependency's JAR artifact: # # { # "com.squareup.okio:okio:3.9.0"."okio-3.9.0.jar" = _: fetchurl { # url = "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/3.9.0/okio-3.9.0.jar"; # hash = "..."; # downloadToTemp = true; # postFetch = "install -Dt $out/com/squareup/okio/okio/3.9.0/ $downloadedFile" # }; # } # # 2. Patch a JAR containing native binaries: # # { # "com.android.tools.build:aapt2:8.5.0-rc02-11315950" = { # "aapt2-8.5.0-rc02-11315950-linux.jar" = src: runCommandCC src.name { # nativeBuildInputs = [ jdk autoPatchelfHook ]; # dontAutoPatchelf = true; # } '' # cp ${src} aapt2.jar # jar xf aapt2.jar aapt2 # chmod +x aapt2 # autoPatchelf aapt2 # jar uf aapt2.jar aapt2 # cp aapt2.jar $out # ''; # } # } overrides ? { }, }: let inherit (builtins) attrValues elemAt filter fromJSON getAttr head length mapAttrs replaceStrings ; inherit (lib) mapAttrsToList readFile; inherit (lib.strings) sanitizeDerivationName; toCoordinates = id: let coords = builtins.split ":" id; parseVersion = version: let parts = builtins.split ":" version; base = elemAt parts 0; in if length parts >= 2 then let snapshot = elemAt parts 2; in replaceStrings [ "-SNAPSHOT" ] [ "-${snapshot}" ] base else base; in rec { group = elemAt coords 0; module = elemAt coords 2; version = elemAt coords 4; uniqueVersion = parseVersion version; }; fetchers' = { http = fetchurl; https = fetchurl; } // fetchers; fetch = coords: overrides: name: { url, hash }: let scheme = head (builtins.match "([a-z0-9+.-]+)://.*" url); fetch' = getAttr scheme fetchers'; artifact = fetch' { inherit url hash; }; override = overrides.name or lib.id; in override artifact; mkModule = id: artifacts: let coords = toCoordinates id; modulePath = "${replaceStrings [ "." ] [ "/" ] coords.group}/${coords.module}/${coords.version}"; moduleOverrides = overrides.${id} or { }; in stdenv.mkDerivation { pname = sanitizeDerivationName "${coords.group}-${coords.module}"; version = coords.uniqueVersion; srcs = mapAttrsToList (fetch coords moduleOverrides) artifacts; dontPatch = true; dontConfigure = true; dontBuild = true; dontFixup = true; dontInstall = true; preUnpack = '' mkdir -p "$out/${modulePath}" ''; unpackCmd = '' cp "$curSrc" "$out/${modulePath}/$(stripHash "$curSrc")" ''; sourceRoot = "."; preferLocalBuild = true; allowSubstitutes = false; }; modulePaths = let dependencies = fromJSON (readFile lockFile); modules = mapAttrs mkModule dependencies; in filter lib.isDerivation (attrValues modules); mavenRepo = symlinkJoin { name = "gradle-maven-repo"; paths = modulePaths; passthru.gradleInitScript = substitute { src = ./init.gradle; substitutions = [ "--replace" "@mavenRepo@" "${mavenRepo}" ]; }; }; in mavenRepo