├── .gitignore
├── README.md
├── UNLICENSE
├── default.nix
├── flake.lock
├── flake.nix
├── mavenix.nix
├── mvnix-init
├── mvnix-update
├── overlay.nix
└── release.nix
/.gitignore:
--------------------------------------------------------------------------------
1 | result*
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mavenix
2 |
3 | Deterministic Maven builds using Nix?
4 |
5 | ## Install
6 |
7 | First you need to install the [Nix package manager](https://nixos.org/nix/), if
8 | you already haven't.
9 |
10 | ```sh
11 | nix-env -i -f https://github.com/nix-community/mavenix/tarball/master
12 | ```
13 |
14 | ## Usage
15 |
16 | ### Create stub files
17 |
18 | First we need to create some stub Nix expression files. `cd` into your maven
19 | project directory and run:
20 |
21 | ```sh
22 | mvnix-init
23 | ```
24 |
25 | Follow the instructions displayed.
26 |
27 | ### Generate lock file
28 |
29 | The `mvnix-update` script generates a `mavenix.lock` file:
30 |
31 | ```sh
32 | mvnix-update
33 | ```
34 |
35 | Note the `mvnix-update` script expects a `default.nix` that evaluates to the derivation,
36 | just as is generated by `mvnix-init`. It is possible however to pass in a custom expression
37 | in order to update the derivation. E.g., if the derivation is the attribute `pkgset.pkg`:
38 |
39 | ```sh
40 | mvnix-update -E "(import ./. {}).pkgset.pkg"
41 | ```
42 |
43 | ### Packaging third-party projects
44 |
45 | If you are packaging a third-party Maven project you can specify a Nix
46 | expression that returns the source of that project.
47 |
48 | This makes it possible to generate a lock file without having to first
49 | manually clone the target project repository.
50 |
51 | E.g. generate and build a Nix package for Traccar v4.2:
52 |
53 | ```sh
54 | mvnix-init -S 'fetchTarball "http://github.com/traccar/traccar/tarball/v4.2"'
55 | mvnix-update
56 | nix-build
57 | ```
58 |
59 | Or a Spring Boot application:
60 |
61 | ```sh
62 | mvnix-init -S 'fetchTarball https://github.com/Gerschtli/spring-rest-api/tarball/master'
63 | mvnix-update
64 | nix-build
65 | ```
66 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
--------------------------------------------------------------------------------
/default.nix:
--------------------------------------------------------------------------------
1 | {
2 | pkgs ? (import (fetchTarball "https://github.com/NixOS/nixpkgs-channels/tarball/c75de8bc12cc7e713206199e5ca30b224e295041") {}),
3 | mavenixLib ? import ./mavenix.nix { inherit pkgs; },
4 | }: with pkgs;
5 |
6 | let
7 | inherit (mavenixLib) name version;
8 | homepage = "https://github.com/nix-community/mavenix";
9 | download = "${homepage}/tarball/v${version}";
10 | gen-header = "# This file has been generated by ${name}.";
11 |
12 | default-tmpl = writeText "default-tmpl.nix" ''
13 | ${gen-header} Configure the build here!
14 | let
15 | mavenix-src = %%env%%;
16 | in {
17 | # pkgs is pinned to 19.09 in mavenix-src,
18 | # replace/invoke with or /path/to/your/nixpkgs_checkout
19 | pkgs ? (import mavenix-src {}).pkgs,
20 | mavenix ? import mavenix-src { inherit pkgs; },
21 | src ? %%src%%,
22 | doCheck ? false,
23 | }: mavenix.buildMaven {
24 | inherit src doCheck;
25 | infoFile = ./mavenix.lock;
26 |
27 | # Add build dependencies
28 | #
29 | #buildInputs = with pkgs; [ git makeWrapper ];
30 |
31 | # Set build environment variables
32 | #
33 | #MAVEN_OPTS = "-Dfile.encoding=UTF-8";
34 |
35 | # Attributes are passed to the underlying `stdenv.mkDerivation`, so build
36 | # hooks can be set here also.
37 | #
38 | #postInstall = '''
39 | # makeWrapper ''${pkgs.jre8_headless}/bin/java $out/bin/my-bin \
40 | # --add-flags "-jar $out/share/java/my-proj.jar"
41 | #''';
42 |
43 | # Add extra maven dependencies which might not have been picked up
44 | # automatically
45 | #
46 | #deps = [
47 | # { path = "org/group-id/artifactId/version/file.jar"; sha1 = "0123456789abcdef"; }
48 | # { path = "org/group-id/artifactId/version/file.pom"; sha1 = "123456789abcdef0"; }
49 | #];
50 |
51 | # Add dependencies on other mavenix derivations
52 | #
53 | #drvs = [ (import ../other/mavenix/derivation {}) ];
54 |
55 | # Override which maven package to build with
56 | #
57 | #maven = maven.overrideAttrs (_: { jdk = pkgs.oraclejdk10; });
58 |
59 | # Override remote repository URLs and settings.xml
60 | #
61 | #remotes = { central = "https://repo.maven.apache.org/maven2"; };
62 | #settings = ./settings.xml;
63 | }
64 | '';
65 | in mavenixLib // {
66 | cli = stdenv.mkDerivation {
67 | inherit name;
68 | src = lib.cleanSource ./.;
69 |
70 | buildInputs = [ makeWrapper ];
71 |
72 | phases = [ "unpackPhase" "installPhase" "fixupPhase" ];
73 | installPhase = ''
74 | mkdir -p $out/bin
75 | cp mvnix-init mvnix-update $out/bin
76 | wrapProgram $out/bin/mvnix-init \
77 | --set CONFIG_TEMPLATE ${default-tmpl} \
78 | --set MAVENIX_SCRIPT ${./mavenix.nix} \
79 | --set MAVENIX_DOWNLOAD ${download} \
80 | --set MAVENIX_VERSION ${version} \
81 | --prefix PATH : ${lib.makeBinPath [ nix coreutils yq ]}
82 | wrapProgram $out/bin/mvnix-update \
83 | --set MAVENIX_VERSION ${version} \
84 | --prefix PATH : ${lib.makeBinPath [ nix coreutils jq yq mktemp ]}
85 | '';
86 |
87 | meta = with lib; {
88 | inherit homepage;
89 | description = "Mavenix: deterministic builds for Maven using Nix?";
90 | license = licenses.unlicense;
91 | maintainers = [ { email = "me@icetan.org"; github = "icetan"; name = "Christopher Fredén"; } ];
92 | };
93 | };
94 | }
95 |
--------------------------------------------------------------------------------
/flake.lock:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": {
3 | "nixpkgs": {
4 | "locked": {
5 | "lastModified": 1621552131,
6 | "narHash": "sha256-AD/AEXv+QOYAg0PIqMYv2nbGOGTIwfOGKtz3rE+y+Tc=",
7 | "owner": "NixOS",
8 | "repo": "nixpkgs",
9 | "rev": "d42cd445dde587e9a993cd9434cb43da07c4c5de",
10 | "type": "github"
11 | },
12 | "original": {
13 | "id": "nixpkgs",
14 | "type": "indirect"
15 | }
16 | },
17 | "root": {
18 | "inputs": {
19 | "nixpkgs": "nixpkgs",
20 | "utils": "utils"
21 | }
22 | },
23 | "utils": {
24 | "locked": {
25 | "lastModified": 1620759905,
26 | "narHash": "sha256-WiyWawrgmyN0EdmiHyG2V+fqReiVi8bM9cRdMaKQOFg=",
27 | "owner": "numtide",
28 | "repo": "flake-utils",
29 | "rev": "b543720b25df6ffdfcf9227afafc5b8c1fabfae8",
30 | "type": "github"
31 | },
32 | "original": {
33 | "owner": "numtide",
34 | "repo": "flake-utils",
35 | "type": "github"
36 | }
37 | }
38 | },
39 | "root": "root",
40 | "version": 7
41 | }
42 |
--------------------------------------------------------------------------------
/flake.nix:
--------------------------------------------------------------------------------
1 | {
2 | description = "Mavenix";
3 |
4 | inputs.utils.url = "github:numtide/flake-utils";
5 |
6 | outputs = { self, nixpkgs, utils }:
7 | utils.lib.eachSystem utils.lib.allSystems (system:
8 | let
9 | pkgs = import nixpkgs { inherit system; };
10 | mavenix = import ./. { inherit pkgs; };
11 | in rec {
12 | packages = utils.lib.flattenTree {
13 | mavenix-cli = mavenix.cli;
14 | };
15 | defaultPackage = packages.mavenix-cli;
16 | apps.mavenix-cli = utils.lib.mkApp { drv = packages.mavenix-cli; };
17 | defaultApp = apps.mavenix-cli;
18 | }) // {
19 | overlay = final: prev: {
20 | inherit (import ./mavenix.nix { pkgs = prev; }) buildMaven;
21 | mavenix-cli = (import ./. { pkgs = prev; }).cli;
22 | };
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/mavenix.nix:
--------------------------------------------------------------------------------
1 | { pkgs }:
2 |
3 | let
4 | inherit (builtins) attrNames attrValues pathExists toJSON foldl' elemAt;
5 | inherit (pkgs) stdenv runCommand fetchurl makeWrapper maven writeText
6 | requireFile yq;
7 | inherit (pkgs.lib) concatLists concatStrings importJSON strings
8 | optionalAttrs optionalString;
9 |
10 | maven' = maven;
11 | settings' = writeText "settings.xml" ''
12 |
16 |
17 | '';
18 |
19 | mapmap = fs: ls: concatLists (map (v: map (f: f v) fs) ls);
20 |
21 | urlToScript = remoteList: dep:
22 | let
23 | inherit (dep) path sha1;
24 | authenticated = if (dep?authenticated) then dep.authenticated else false;
25 |
26 | fetch = if authenticated then (requireFile {
27 | inherit sha1;
28 | url = "${elemAt remoteList 0}/${path}";
29 | }) else (fetchurl {
30 | inherit sha1;
31 | urls = map (r: "${r}/${path}") remoteList;
32 | });
33 | in ''
34 | mkdir -p "$(dirname ${path})"
35 | ln -sfv "${fetch}" "${path}"
36 | '';
37 |
38 | metadataToScript = remote: meta:
39 | let
40 | inherit (meta) path content;
41 | name = "maven-metadata-${remote}.xml";
42 | in ''
43 | mkdir -p "${path}"
44 | ( cd "${path}"
45 | ln -sfv "${writeText "maven-metadata.xml" content}" "${name}"
46 | linkSnapshot "${name}" )
47 | '';
48 |
49 | drvToScript = drv: ''
50 | echo >&2 === building mavenix drvs: ${drv.name} ===
51 | props="${drv}/share/java/*.properties"
52 | for prop in $props; do getMavenPathFromProperties $prop; done
53 | '';
54 |
55 | transInfo = map (drv: importJSON "${drv}/share/mavenix/mavenix.lock");
56 |
57 | transDeps = tinfo: concatLists (map (info: info.deps) tinfo);
58 | transMetas = tinfo: concatLists (map (info: info.metas) tinfo);
59 | transRemotes = foldl' (acc: info: acc // info.remotes) {};
60 |
61 | mkRepo = {
62 | deps ? [],
63 | metas ? [],
64 | remotes ? {},
65 | drvs ? [],
66 | drvsInfo ? [],
67 | postHook ? "",
68 | }: let
69 | deps' = deps ++ (transDeps drvsInfo);
70 | metas' = metas ++ (transMetas drvsInfo);
71 | remotes' = (transRemotes drvsInfo) // remotes;
72 | remoteList = attrValues remotes';
73 | in runCommand "mk-repo" {} ''
74 | set -e
75 |
76 | getMavenPath() {
77 | local version=$(sed -n 's|^version=||p' "$1")
78 | local groupId=$(sed -n 's|^groupId=||p' "$1")
79 | local artifactId=$(sed -n 's|^artifactId=||p' "$1")
80 | echo "''${groupId//.//}/$artifactId/$version/$artifactId-$version"
81 | }
82 |
83 | linkSnapshot() {
84 | [ "$(${yq}/bin/xq '.metadata.versioning.snapshotVersions' "$1")" == "null" ] \
85 | && return
86 | ${yq}/bin/xq -r '
87 | .metadata as $o
88 | | [.metadata.versioning.snapshotVersions.snapshotVersion] | flatten | .[]
89 | | ((if .classifier? then ("-" + .classifier) else "" end) + "." + .extension) as $e
90 | | $o.artifactId + "-" + .value + $e + " " + $o.artifactId + "-" + $o.version + $e
91 | ' "$1" | xargs -L1 ln -sfv
92 | }
93 |
94 | getMavenPathFromProperties() {
95 | local path="$(getMavenPath "$1")"
96 | local bpath="$(dirname $path)"
97 | local basefilename="''${1%%.properties}"
98 |
99 | if test "$bpath"; then
100 | mkdir -p "$bpath"
101 | for fn in $basefilename-* $basefilename.{pom,jar}; do
102 | test ! -f $fn || ln -sfv "$fn" "$bpath"
103 | done
104 | ln -sfv "$basefilename.metadata.xml" "$bpath/maven-metadata-local.xml"
105 | fi
106 | }
107 |
108 | mkdir -p "$out"
109 | (cd $out
110 | ${concatStrings (map (urlToScript remoteList) deps')}
111 | ${concatStrings (mapmap
112 | (map metadataToScript (attrNames remotes')) metas')}
113 | ${concatStrings (map drvToScript drvs)}
114 | )
115 |
116 | ${postHook}
117 | '';
118 |
119 | cp-artifact = submod: ''
120 | find . -type f \
121 | -regex "${submod.path}/target/[^/]*\.\(jar\|war\)$" ! -name "*-sources.jar" \
122 | -exec cp -v {} $dir \;
123 | '';
124 |
125 | cp-pom = submod: ''
126 | cp -v ${submod.path}/pom.xml $dir/${submod.name}.pom
127 | '';
128 |
129 | mk-properties = submod: ''
130 | echo 'groupId=${submod.groupId}
131 | artifactId=${submod.artifactId}
132 | version=${submod.version}
133 | ' > $dir/${submod.name}.properties
134 | '';
135 |
136 | mk-maven-metadata = submod: ''
137 | echo '
138 | ${submod.groupId}
139 | ${submod.artifactId}
140 | ${submod.version}
141 |
142 | ' > $dir/${submod.name}.metadata.xml
143 | '';
144 |
145 | overrideOverrideAttrs = f: attrs: (f attrs) // {
146 | overrideAttrs = f_: overrideOverrideAttrs f (attrs // (f_ attrs));
147 | };
148 |
149 | buildMaven = overrideOverrideAttrs ({
150 | src,
151 | infoFile,
152 | deps ? [],
153 | drvs ? [],
154 | settings ? settings',
155 | maven ? maven',
156 |
157 | nativeBuildInputs ? [],
158 | passthru ? {},
159 |
160 | remotes ? {},
161 |
162 | postMkRepoHook ? "",
163 |
164 | doCheck ? true,
165 | debug ? false,
166 | build ? true,
167 | ...
168 | }@config:
169 | let
170 | dummy-info = { name = "update"; deps = []; metas = []; };
171 |
172 | info = if (build && pathExists infoFile) then importJSON infoFile else dummy-info;
173 | remotes' = (optionalAttrs (info?remotes) info.remotes) // remotes;
174 | drvsInfo = transInfo drvs;
175 |
176 | emptyRepo = mkRepo {
177 | inherit drvs drvsInfo;
178 | remotes = remotes';
179 | };
180 |
181 | repo = mkRepo {
182 | inherit (info) deps metas;
183 | inherit drvs drvsInfo;
184 | remotes = remotes';
185 | postHook = postMkRepoHook;
186 | };
187 |
188 | # Wrap mvn with settings to improve the nix-shell experience
189 | maven' = runCommand "mvn" {
190 | nativeBuildInputs = [ makeWrapper ];
191 | } ''
192 | mkdir -p $out/bin
193 | makeWrapper ${maven}/bin/mvn $out/bin/mvn --add-flags "--settings ${settings}"
194 | '';
195 |
196 | mvn = "${maven'}/bin/mvn --offline --batch-mode -Dmaven.repo.local=${repo} -nsu ";
197 |
198 | in
199 | stdenv.mkDerivation ({
200 | name = info.name;
201 |
202 | nativeBuildInputs = nativeBuildInputs ++ [
203 | maven' maven.jdk
204 | (pkgs.ensureNewerSourcesHook { year = "1980"; })
205 | ];
206 |
207 | # Export as environment variable to make it possible to reuse default flags in other phases/hooks
208 | inherit mvn;
209 |
210 | postPhases = [ "mavenixDistPhase" ];
211 |
212 | checkPhase = optionalString build ''
213 | runHook preCheck
214 |
215 | $mvn test
216 |
217 | runHook postCheck
218 | '';
219 |
220 | buildPhase = optionalString build ''
221 | runHook preBuild
222 |
223 | $mvn --version
224 | $mvn package -DskipTests=true -Dmaven.test.skip.exec=true
225 |
226 | runHook postBuild
227 | '';
228 |
229 | installPhase = optionalString build ''
230 | runHook preInstall
231 |
232 | dir="$out/share/java"
233 | mkdir -p $dir
234 |
235 | ${optionalString (info?submodules) (concatStrings (mapmap
236 | [ cp-artifact cp-pom mk-properties mk-maven-metadata ]
237 | info.submodules
238 | ))}
239 |
240 | runHook postInstall
241 | '';
242 |
243 | mavenixDistPhase = optionalString build ''
244 | mkdir -p $out/share/mavenix
245 | echo copying lock file
246 | cp -v ${infoFile} $out/share/mavenix/mavenix.lock
247 | '';
248 |
249 | passthru = passthru // {
250 | mavenixMeta = {
251 | inherit deps emptyRepo settings;
252 | infoFile = toString infoFile;
253 | srcPath = toString src;
254 | };
255 | };
256 | } // (
257 | removeAttrs config [
258 | "deps" "drvs" "remotes" "infoFile"
259 | "nativeBuildInputs" "passthru"
260 | ]
261 | ))
262 | );
263 | in rec {
264 | version = "2.3.3";
265 | name = "mavenix-${version}";
266 | updateInfo = f: infoFile:
267 | writeText "updated-lock" (
268 | toJSON ((x: x // f x) (importJSON infoFile))
269 | );
270 | inherit buildMaven pkgs;
271 | }
272 |
--------------------------------------------------------------------------------
/mvnix-init:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | usage() {
5 | # shellcheck disable=SC2015
6 | test "$1" && echo -e Error: "$1"\\n || true
7 | cat >&2 <]
9 |
10 | Options:
11 | -S, --src A Nix expression to use as 'src' for derivation
12 | -o, --output Output directory for generated files
13 | -s, --standalone Include 'mavenix.nix' file
14 | -f, --force Overwrite output file if exists
15 | -v, --verbose Verbose output
16 | -h, --help Print usage
17 |
18 | Version: $MAVENIX_VERSION
19 | EOF
20 | exit 1
21 | }
22 |
23 | tmpl() { sed "s|%%$1%%|$2|g"; }
24 |
25 | # Default values
26 | outputDir="."
27 |
28 | # Parse CLI arguments
29 | while test "$1";do
30 | case "$1" in
31 | -S|--src) shift;srcExpr="($1)";;
32 | -o|--output) shift;outputDir="$1";;
33 | -s|--standalone) standalone=1;;
34 | -f|--force) forceOverwrite=1;;
35 | -v|--verbose) set -x;;
36 | -h|--help) usage;;
37 | -*) usage "no option \"$1\"";;
38 | *) config="$1";;
39 | esac
40 | shift
41 | done
42 |
43 | mkdir -p "$outputDir"
44 | config="${config-$outputDir/default.nix}"
45 | [[ -n "$forceOverwrite" || ! -e "$config" ]] || usage "\"$config\" already exists"
46 |
47 | srcExpr="${srcExpr-./$(realpath --relative-to="$(dirname "$config")" ".")}"
48 |
49 | copy() { cp "$1" "$2"; echo "$2"; }
50 | echo >&2 "
51 | Creating files:
52 | "
53 |
54 | if test "$standalone"; then
55 | relEnv="./$(realpath --relative-to="$(dirname "$config")" "$outputDir/mavenix.nix")"
56 | copy "$MAVENIX_SCRIPT" "$outputDir/mavenix.nix"
57 | chmod u+w "$outputDir/mavenix.nix"
58 | else
59 | relEnv="fetchTarball { url = \"$MAVENIX_DOWNLOAD\"; sha256 = \"$(nix-prefetch-url "$MAVENIX_DOWNLOAD" --unpack 2>&-)\"; }"
60 | fi
61 |
62 | # shellcheck disable=SC2002
63 | cat "$CONFIG_TEMPLATE" \
64 | | tmpl src "$srcExpr" \
65 | | tmpl env "$relEnv" \
66 | > "$config"
67 | echo "$config"
68 |
69 | echo >&2 "
70 | 1. Configure by editing '$config'
71 | 2. Create a lock file by running 'mvnix-update \"$config\"'
72 | 3. Build your project 'nix-build \"$config\"'
73 | "
74 |
--------------------------------------------------------------------------------
/mvnix-update:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | usage() {
5 | # shellcheck disable=SC2015
6 | test "$1" && echo -e Error: "$1"\\n || true
7 | cat >&2 <]
9 |
10 | Options:
11 | -E, --exp Pass in a Nix expression that represents the
12 | derivation to be updated.
13 | -s, --save-repo Specify path to save maven repo to. This will
14 | speed up consecutive runs, but might affect
15 | lock file if POM is changed in between.
16 | -n, --no-add Don't add dependencies to nix store
17 | -v, --verbose Verbose output
18 | -h, --help Print usage
19 |
20 | Version: $MAVENIX_VERSION
21 | EOF
22 | exit 1
23 | }
24 |
25 | # Setup work dir and cleanup
26 | WORK_DIR=$(mktemp -d --tmpdir mvnix-update.XXXXXX)
27 | cleanup() { { chmod -R +w "$WORK_DIR"; rm -rf "$WORK_DIR"; } || true; }
28 | trap 'trap - EXIT; cleanup; kill -- $$' EXIT
29 |
30 | # Default values
31 | tmp_repo="$WORK_DIR/m2-repo"
32 |
33 | # Parse CLI arguments
34 | while test "$1";do
35 | case "$1" in
36 | -E|--exp) shift;expression="$1";;
37 | -s|--save-repo) shift;tmp_repo="$1";;
38 | -n|--no-add) no_add=1;;
39 | -v|--verbose) verbose=1;set -x;;
40 | -h|--help) usage;;
41 | -*) usage "no option \"$1\"";;
42 | *) config="$1";;
43 | esac
44 | shift
45 | done
46 |
47 | die() { echo >&2 "$@"; exit 1;}
48 |
49 | nix_flags=$(test "$verbose" && printf %s "--verbose" || true)
50 |
51 | if [[ "$expression" && "$config" ]]; then
52 | die "Expression and file arguments are mutually exclusive"
53 | elif [[ "$config" ]]; then
54 | expression="import \"$(realpath "$config")\" {}"
55 | elif [[ ! "$expression" ]]; then
56 | expression="import ./. {}"
57 | fi
58 |
59 | tmp_repo=$(realpath "$tmp_repo")
60 | mkdir -p "$tmp_repo"
61 |
62 | ns_() {
63 | local ns_wd="$1";shift
64 | HOME="/tmp/nowhere" nix-shell $nix_flags --show-trace --pure \
65 | --run "cd \"$ns_wd\"; $*" -E "($expression).overrideAttrs (_: { build = false; })";
66 | }
67 |
68 | echo >&2 "
69 | Getting mavenix meta data...
70 | "
71 |
72 | realiseStorePath() {
73 | # Check if $1 is a store path (similar to lib.isStorePath) and realize only
74 | # if it is.
75 | if [[ $1 =~ ^/nix/store/ ]]; then
76 | nix-store --realise "$1" >/dev/null
77 | fi
78 | }
79 | mavenixMeta=$(nix-instantiate $nix_flags --eval --strict --json -E "($expression).mavenixMeta" | jq -rc .)
80 | mq() { jq -rc "$1" <<<"$mavenixMeta"; }
81 |
82 | test "$mavenixMeta" || die "Nix expression is not a mavenix derivation"
83 |
84 | nix-build --no-out-link -E "{ inherit (($expression).mavenixMeta) emptyRepo settings infoFile; }"
85 |
86 | src_path=$(mq .srcPath)
87 | realiseStorePath "$src_path"
88 |
89 | settings=$(mq .settings)
90 | empty_repo=$(mq .emptyRepo)
91 |
92 | if test -d "$empty_repo"; then
93 | cp -rf -t "$tmp_repo" "$empty_repo"/* >/dev/null 2>&1 || true
94 | chmod -R u+w "$tmp_repo" || true
95 | fi
96 |
97 | src_wd="$src_path"
98 | if test ! -w "$src_wd"; then
99 | src_wd="$WORK_DIR/src"
100 | cp -r "$src_path" "$src_wd"
101 | chmod -R u+w "$src_wd" || true #echo >&2 Failed to set chmod on temp repo dir.
102 | fi
103 |
104 | # shellcheck disable=SC2015
105 | mvn_flags=$(test "$verbose" && printf %s "-e -X" || true)
106 | # shellcheck disable=SC2086
107 | mvn_() { ns_ "$src_wd" mvn $mvn_flags -B -nsu --settings "$settings" "$@"; }
108 | mvn_out() { ns_ "$src_wd" mvn -B -nsu --settings "$settings" "$@"; }
109 |
110 | echo >&2 "
111 | Running mvn package...
112 | "
113 | mvn_ >&2 install -Dmaven.test.skip.exec=true -DskipTests -Dmaven.repo.local="$tmp_repo"
114 |
115 | echo >&2 "
116 | Getting project info...
117 | "
118 | pom=$(mvn_out help:effective-pom | grep -v '^\[\|^Effective \|^$' | xq -c .)
119 | projects=$(jq -c '.projects.project // [.project]' <<<"$pom")
120 | pq() { jq -rc "$1" <<<"$projects"; }
121 | export -f pq
122 |
123 | groupId=$(pq .[0].groupId)
124 | artifactId=$(pq .[0].artifactId)
125 | version=$(pq .[0].version)
126 |
127 | modules=$(pq '
128 | [ .[]
129 | | {
130 | name: (.artifactId + "-" + .version),
131 | groupId, artifactId, version,
132 | path: (.build.directory | sub("^'"$src_wd"'/"; "./") | sub("/target"; ""))
133 | }
134 | ]
135 | ')
136 |
137 | remotes_repos=$(pq '
138 | [ [.[].repositories.repository, .[].pluginRepositories.pluginRepository]
139 | | flatten | .[]
140 | | {(.id):.url}
141 | ] | add
142 | ')
143 |
144 | tmp_lock_file="$WORK_DIR/tmp-mavenix.lock"
145 | lock_file="$(mq .infoFile)"
146 |
147 | echo >&2 "
148 | Resolving maven dependencies...
149 | "
150 | mvn_ >&2 dependency:go-offline -Dmaven.repo.local="$tmp_repo"
151 |
152 | echo >&2 "
153 | Creating lock file...
154 | "
155 | (
156 | echo -n "{
157 | \"name\": \"$artifactId-$version\",
158 | \"groupId\": \"$groupId\",
159 | \"artifactId\": \"$artifactId\",
160 | \"version\": \"$version\",
161 | \"submodules\": $modules,
162 | \"deps\": [ $(mq .deps[] | sed 's/\(.\)$/\1,/')"
163 | ( cd "$tmp_repo"
164 | remotes=$(find . -type f -name "*.repositories" | sed 's|^\./||' | sort)
165 | sep=""
166 | for remote in $remotes; do
167 | dir=$(dirname "$remote")
168 | files=$(find "$dir" -type f ! -name "*.repositories" ! -name "*.sha1" \
169 | | grep -v '^#' "$remote" | sed "s|^|$dir/|" | sort)
170 | for file_ in $files; do
171 | file=$(echo "$file_" | cut -d '>' -f1)
172 | # Maven 3.0.5 for 3.3.9 use $file instead of $file_real
173 | # shellcheck disable=SC2116,SC2086
174 | file_real=$(echo ${file//-SNAPSHOT./-[0-9]*.})
175 | repo=$(echo "$file_" | cut -d '>' -f2 | sed 's/=$//')
176 | test "$repo" || continue
177 | echo -n "$sep
178 | {\"path\":\"$file_real\",\"sha1\":\"$(grep -Eo '[0-9a-zA-Z]{40}' < "$file_real.sha1")\"}"
179 | sep=","
180 |
181 | test "$no_add" || nix-store --add-fixed sha1 "$file_real" >&2
182 | done
183 | done
184 |
185 | echo -n "
186 | ],
187 | \"metas\": ["
188 | metafiles=$(find . -type f -name "maven-metadata-*.xml" | sed 's|^\./||' | sort)
189 | sep=""
190 | for file in $metafiles; do
191 | repo=$(basename "$file" | sed 's/^maven-metadata-//;s/\.xml$//')
192 | [[ "$repo" && "$repo" != "local" ]] || continue
193 | echo -n "$sep{
194 | \"path\": \"$(dirname "$file")\",
195 | \"content\": \"$(sed ':a;N;$!ba;s/\n/\\n/g;s/\"/\\\"/g' "$file")\"
196 | }"
197 | sep=", "
198 | done
199 | )
200 | echo -n "
201 | ],
202 | \"remotes\": $remotes_repos
203 | }
204 | "
205 | ) > "$tmp_lock_file"
206 |
207 |
208 | echo >&2 "
209 | Sanity check...
210 | "
211 | jq -c . "$tmp_lock_file" > /dev/null
212 | jq -S . "$tmp_lock_file" > "$lock_file"
213 |
214 | echo >&2 "
215 | Lock file created at: $lock_file
216 | "
217 |
--------------------------------------------------------------------------------
/overlay.nix:
--------------------------------------------------------------------------------
1 | final: prev:
2 | let
3 | mavenix = import ./. {};
4 | in {
5 | inherit mavenix;
6 | mavenix-cli = mavenix.cli;
7 | }
8 |
--------------------------------------------------------------------------------
/release.nix:
--------------------------------------------------------------------------------
1 | {
2 | mavenixSrc ? { outPath = ./.; revCount = 1234; shortRev = "abcdef"; }
3 | }:
4 |
5 | {
6 | build = { system ? builtins.currentSystem }:
7 | let
8 | pkgs = import { inherit system; };
9 | in
10 | import mavenixSrc.outPath { inherit pkgs; };
11 | }
12 |
--------------------------------------------------------------------------------