blob: 6e06ac27dccbacb8896616cbadd6bb05ae1ef674 [file]
#!/bin/bash
#
# Asserts that two JAR files are functionally identical by comparing the
# CRC-32 checksums of all their internal components.
#
# This function is designed for scripting and testing:
# - If the JARs are identical, it prints NOTHING and returns an exit code of 0.
# - If the JARs differ, it prints a single line describing the FIRST
# point of difference to STDERR and returns an exit code of 1.
#
# DEPENDENCIES:
# - unzip, awk, sort
#
assert_jars_equal() {
# --- Input Validation ---
if [[ "$#" -ne 2 ]]; then
echo "Usage: assert_jars_equal <jar1_path> <jar2_path>" >&2
return 1
fi
local jar1="$1"
local jar2="$2"
for cmd in unzip awk sort; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error (assert_jars_equal): Required command '$cmd' not found." >&2
return 1
fi
done
for jar in "$jar1" "$jar2"; do
if [[ ! -f "$jar" ]]; then
echo "Error (assert_jars_equal): File not found: $jar" >&2
return 1
fi
if ! unzip -tq "$jar" &>/dev/null; then
echo "Error (assert_jars_equal): Not a valid JAR/ZIP file: $jar" >&2
return 1
fi
done
# --- Helper function to generate a manifest of "crc<space><space>filepath" ---
_generate_manifest() {
local jar_path="$1"
unzip -v "$jar_path" 2>/dev/null | awk '
/----/ {p=1-p; next}
p {
if (substr($NF, length($NF)) == "/") next;
print $(NF-1) " " $NF
}
' | sort
}
# --- Core Logic using AWK ---
# The awk script is designed to exit with a non-zero status code on the first
# discrepancy it finds. If it processes everything without finding a
# difference, it exits with a zero status code.
# Output is redirected to stderr to keep stdout clean for success cases.
awk '
BEGIN {
# Define colors for stderr output
RED="\033[0;31m"; GREEN="\033[0;32m"; YELLOW="\033[0;33m";
BOLD="\033[1m"; RESET="\033[0m";
}
# Pass 1: Load the manifest of the first JAR into a map.
FNR==NR {
path = substr($0, length($1) + 3);
checksum_map[path] = $1;
next;
}
# Pass 2: Process the second JARs manifest.
{
path = substr($0, length($1) + 3);
checksum_new = $1;
if (path in checksum_map) {
# Path exists in both. If checksums differ, its a MODIFICATION.
if (checksum_map[path] != checksum_new) {
print BOLD YELLOW "DIFFERENCE (Modified):" RESET " " path > "/dev/stderr";
exit 1; # Exit immediately with a failure code.
}
# If they match, delete from map. We use the remainder to find removed files.
delete checksum_map[path];
} else {
# Path is new. This is an ADDITION.
print BOLD GREEN "DIFFERENCE (Added):" RESET " " path > "/dev/stderr";
exit 1; # Exit immediately with a failure code.
}
}
# END Block: This code only runs if no "Modified" or "Added" files were found.
# We now check if any files were removed.
END {
# The `for..in` loop will only run if the map is not empty.
for (path in checksum_map) {
# If we enter this loop, it means a file from jar1 was not in jar2.
# This is a REMOVAL.
print BOLD RED "DIFFERENCE (Removed):" RESET " " path > "/dev/stderr";
exit 1; # Exit on the very first one we find.
}
# If the loop never runs, the map is empty, and the JARs are identical.
# awk exits with a default code of 0 (success).
}
' <(_generate_manifest "$jar1") <(_generate_manifest "$jar2")
# Return the exit code of the awk command
return $?
}