about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorbb010g <me@bb010g.com>2019-04-18 20:50:47 -0700
committerDoron Behar <doron.behar@gmail.com>2021-10-27 13:21:27 +0300
commit29fedf210f6eb7aae585946e36654e50be52e317 (patch)
tree38201225ef107dff26998e014dd5c4910957d9cf /pkgs/build-support
parent77382d5ebf92ac0ae021d02c73357f5e11d9e3ad (diff)
canonicalize-jars-hook: add
A build hook to run functions previously only implemented privately in
`pkgs/build-support/release/functions.sh`.
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/java/canonicalize-jar.nix9
-rw-r--r--pkgs/build-support/java/canonicalize-jar.sh29
-rw-r--r--pkgs/build-support/setup-hooks/canonicalize-jars.sh17
3 files changed, 55 insertions, 0 deletions
diff --git a/pkgs/build-support/java/canonicalize-jar.nix b/pkgs/build-support/java/canonicalize-jar.nix
new file mode 100644
index 0000000000000..1edd9a6e0d20f
--- /dev/null
+++ b/pkgs/build-support/java/canonicalize-jar.nix
@@ -0,0 +1,9 @@
+{ substituteAll, unzip, zip }:
+
+substituteAll {
+  name = "canonicalize-jar";
+  src = ./canonicalize-jar.sh;
+
+  unzip = "${unzip}/bin/unzip";
+  zip = "${zip}/bin/zip";
+}
diff --git a/pkgs/build-support/java/canonicalize-jar.sh b/pkgs/build-support/java/canonicalize-jar.sh
new file mode 100644
index 0000000000000..af010bcd2b26c
--- /dev/null
+++ b/pkgs/build-support/java/canonicalize-jar.sh
@@ -0,0 +1,29 @@
+# Canonicalize the manifest & repack with deterministic timestamps.
+canonicalizeJar() {
+    local input='' outer=''
+    input="$(realpath -sm -- "$1")"
+    outer="$(pwd)"
+    # -qq: even quieter
+    @unzip@ -qq "$input" -d "$input-tmp"
+    canonicalizeJarManifest "$input-tmp/META-INF/MANIFEST.MF"
+    # Sets all timestamps to Jan 1 1980, the earliest mtime zips support.
+    find -- "$input-tmp" -exec touch -t 198001010000.00 {} +
+    rm "$input"
+    pushd "$input-tmp" 2>/dev/null
+    # -q|--quiet, -r|--recurse-paths
+    # -o|--latest-time: canonicalizes overall archive mtime
+    # -X|--no-extra: don't store platform-specific extra file attribute fields
+    @zip@ -qroX "$outer/tmp-out.jar" . 2> /dev/null
+    popd 2>/dev/null
+    rm -rf "$input-tmp"
+    mv "$outer/tmp-out.jar" "$input"
+}
+
+# See also the Java specification's JAR requirements:
+# https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#Notes_on_Manifest_and_Signature_Files
+canonicalizeJarManifest() {
+    local input=''
+    input="$(realpath -sm -- "$1")"
+    (head -n 1 "$input" && tail -n +2 "$input" | sort | grep -v '^\s*$') > "$input-tmp"
+    mv "$input-tmp" "$input"
+}
diff --git a/pkgs/build-support/setup-hooks/canonicalize-jars.sh b/pkgs/build-support/setup-hooks/canonicalize-jars.sh
new file mode 100644
index 0000000000000..8c55810748ea0
--- /dev/null
+++ b/pkgs/build-support/setup-hooks/canonicalize-jars.sh
@@ -0,0 +1,17 @@
+# This setup hook causes the fixup phase to repack all JAR files in a
+# canonical & deterministic fashion, e.g. resetting mtimes (like with normal
+# store files) and avoiding impure metadata.
+
+fixupOutputHooks+=('if [ -z "$dontCanonicalizeJars" -a -e "$prefix" ]; then canonicalizeJarsIn "$prefix"; fi')
+
+canonicalizeJarsIn() {
+  local dir="$1"
+  header "canonicalizing jars in $dir"
+  dir="$(realpath -sm -- "$dir")"
+  while IFS= read -rd '' f; do
+    canonicalizeJar "$f"
+  done < <(find -- "$dir" -type f -name '*.jar' -print0)
+  stopNest
+}
+
+source @canonicalize_jar@