{
pkgs ? import (fetchGit {
url = "https://github.com/NixOS/nixpkgs-channels";
ref = "nixos-19.09";
rev = "c75de8bc12cc7e713206199e5ca30b224e295041";
}) {},
}:
let
inherit (builtins) attrNames attrValues pathExists toJSON foldl' elemAt;
inherit (pkgs) stdenv runCommand fetchurl makeWrapper maven writeText
requireFile yq;
inherit (pkgs.lib) concatLists concatStrings importJSON strings
optionalAttrs optionalString;
maven' = maven;
settings' = writeText "settings.xml" ''
'';
mapmap = fs: ls: concatLists (map (v: map (f: f v) fs) ls);
urlToScript = remoteList: dep:
let
inherit (dep) path sha1;
authenticated = if (dep?authenticated) then dep.authenticated else false;
fetch = if authenticated then (requireFile {
inherit sha1;
url = "${elemAt remoteList 0}/${path}";
}) else (fetchurl {
inherit sha1;
urls = map (r: "${r}/${path}") remoteList;
});
in ''
mkdir -p "$(dirname ${path})"
ln -sfv "${fetch}" "${path}"
'';
metadataToScript = remote: meta:
let
inherit (meta) path content;
name = "maven-metadata-${remote}.xml";
in ''
mkdir -p "${path}"
( cd "${path}"
ln -sfv "${writeText "maven-metadata.xml" content}" "${name}"
linkSnapshot "${name}" )
'';
drvToScript = drv: ''
echo >&2 === building mavenix drvs: ${drv.name} ===
props="${drv}/share/java/*.properties"
for prop in $props; do getMavenPathFromProperties $prop; done
'';
transInfo = map (drv: importJSON "${drv}/share/mavenix/mavenix.lock");
transDeps = tinfo: concatLists (map (info: info.deps) tinfo);
transMetas = tinfo: concatLists (map (info: info.metas) tinfo);
transRemotes = foldl' (acc: info: acc // info.remotes) {};
mkRepo = {
deps ? [],
metas ? [],
remotes ? {},
drvs ? [],
drvsInfo ? [],
postHook ? "",
}: let
deps' = deps ++ (transDeps drvsInfo);
metas' = metas ++ (transMetas drvsInfo);
remotes' = (transRemotes drvsInfo) // remotes;
remoteList = attrValues remotes';
in runCommand "mk-repo" {} ''
set -e
getMavenPath() {
local version=$(sed -n 's|^version=||p' "$1")
local groupId=$(sed -n 's|^groupId=||p' "$1")
local artifactId=$(sed -n 's|^artifactId=||p' "$1")
echo "''${groupId//.//}/$artifactId/$version/$artifactId-$version"
}
linkSnapshot() {
[ "$(${yq}/bin/xq '.metadata.versioning.snapshotVersions' "$1")" == "null" ] \
&& return
${yq}/bin/xq -r '
.metadata as $o
| [.metadata.versioning.snapshotVersions.snapshotVersion] | flatten | .[]
| ((if .classifier? then ("-" + .classifier) else "" end) + "." + .extension) as $e
| $o.artifactId + "-" + .value + $e + " " + $o.artifactId + "-" + $o.version + $e
' "$1" | xargs -L1 ln -sfv
}
getMavenPathFromProperties() {
local path="$(getMavenPath "$1")"
local bpath="$(dirname $path)"
local basefilename="''${1%%.properties}"
if test "$bpath"; then
mkdir -p "$bpath"
for fn in $basefilename-* $basefilename.{pom,jar}; do
test ! -f $fn || ln -sfv "$fn" "$bpath"
done
ln -sfv "$basefilename.metadata.xml" "$bpath/maven-metadata-local.xml"
fi
}
mkdir -p "$out"
(cd $out
${concatStrings (map (urlToScript remoteList) deps')}
${concatStrings (mapmap
(map metadataToScript (attrNames remotes')) metas')}
${concatStrings (map drvToScript drvs)}
)
${postHook}
'';
cp-artifact = submod: ''
find . -type f \
-regex "${submod.path}/target/[^/]*\.\(jar\|war\)$" ! -name "*-sources.jar" \
-exec cp -v {} $dir \;
'';
cp-pom = submod: ''
cp -v ${submod.path}/pom.xml $dir/${submod.name}.pom
'';
mk-properties = submod: ''
echo 'groupId=${submod.groupId}
artifactId=${submod.artifactId}
version=${submod.version}
' > $dir/${submod.name}.properties
'';
mk-maven-metadata = submod: ''
echo '
${submod.groupId}
${submod.artifactId}
${submod.version}
' > $dir/${submod.name}.metadata.xml
'';
overrideOverrideAttrs = f: attrs: (f attrs) // {
overrideAttrs = f_: overrideOverrideAttrs f (attrs // (f_ attrs));
};
buildMaven = overrideOverrideAttrs ({
src,
infoFile,
deps ? [],
drvs ? [],
settings ? settings',
maven ? maven',
nativeBuildInputs ? [],
passthru ? {},
remotes ? {},
postMkRepoHook ? "",
doCheck ? true,
debug ? false,
build ? true,
...
}@config:
let
dummy-info = { name = "update"; deps = []; metas = []; };
info = if build then importJSON infoFile else dummy-info;
remotes' = (optionalAttrs (info?remotes) info.remotes) // remotes;
drvsInfo = transInfo drvs;
emptyRepo = mkRepo {
inherit drvs drvsInfo;
remotes = remotes';
};
repo = mkRepo {
inherit (info) deps metas;
inherit drvs drvsInfo;
remotes = remotes';
postHook = postMkRepoHook;
};
# Wrap mvn with settings to improve the nix-shell experience
maven' = runCommand "mvn" {
nativeBuildInputs = [ makeWrapper ];
} ''
mkdir -p $out/bin
makeWrapper ${maven}/bin/mvn $out/bin/mvn --add-flags "--settings ${settings}"
'';
mvn = "${maven'}/bin/mvn --offline --batch-mode -Dmaven.repo.local=${repo} -nsu ";
in
stdenv.mkDerivation ({
name = info.name;
nativeBuildInputs = nativeBuildInputs ++ [
maven' maven.jdk
(pkgs.ensureNewerSourcesHook { year = "1980"; })
];
# Export as environment variable to make it possible to reuse default flags in other phases/hooks
inherit mvn;
postPhases = [ "mavenixDistPhase" ];
checkPhase = optionalString build ''
runHook preCheck
$mvn test
runHook postCheck
'';
buildPhase = optionalString build ''
runHook preBuild
$mvn --version
$mvn package -DskipTests=true -Dmaven.test.skip.exec=true
runHook postBuild
'';
installPhase = optionalString build ''
runHook preInstall
dir="$out/share/java"
mkdir -p $dir
${optionalString (info?submodules) (concatStrings (mapmap
[ cp-artifact cp-pom mk-properties mk-maven-metadata ]
info.submodules
))}
runHook postInstall
'';
mavenixDistPhase = optionalString build ''
mkdir -p $out/share/mavenix
echo copying lock file
cp -v ${infoFile} $out/share/mavenix/mavenix.lock
'';
passthru = passthru // {
mavenixMeta = {
inherit deps emptyRepo settings;
infoFile = toString infoFile;
srcPath = toString src;
};
};
} // (
removeAttrs config [
"deps" "drvs" "remotes" "infoFile"
"nativeBuildInputs" "passthru"
]
))
);
in rec {
version = "2.3.3";
name = "mavenix-${version}";
updateInfo = f: infoFile:
writeText "updated-lock" (
toJSON ((x: x // f x) (importJSON infoFile))
);
inherit buildMaven pkgs;
}