#!/bin/sh
# SPDX-FileCopyrightText: 2026 Martin Paljak <martin@martinpaljak.net>
# SPDX-License-Identifier: MIT

# Install the txtrepo extension without a working .jar download: the archive is
# fetched base64 armored as text and decoded here, the same path the extension
# itself takes once installed. The metadata and the checksums, being text, pass
# a content filter as they are.

set -eu

BASE=${TXTREPO_BASE:-https://mvn.javacard.pro/public}
GA=pro/javacard/maven/txtrepo
SUFFIX=${TXTREPO_SUFFIX:-.txt}

# whole-file GET, no compression, so the base64 arrives as it was sent
# XXX: -k for broken enterprise MITM truststores; the checksum rides the same channel
fetch() { curl -fsSLk -H 'Accept-Encoding: identity' "$1"; }

# the text between the first tag pair named $1
strip() { grep -o "<$1>[^<]*</$1>" | sed 's/<[^>]*>//g'; }

# newest published version, then that version's snapshot build
meta=$(fetch "$BASE/$GA/maven-metadata.xml")
version=$(printf '%s' "$meta" | strip latest | head -n1)
[ -n "$version" ] || version=$(printf '%s' "$meta" | strip version | tail -n1)
[ -n "$version" ] || { echo "no version in $BASE/$GA/maven-metadata.xml" >&2; exit 1; }

vmeta=$(fetch "$BASE/$GA/$version/maven-metadata.xml")
ts=$(printf '%s' "$vmeta" | strip timestamp | head -n1)
bn=$(printf '%s' "$vmeta" | strip buildNumber | head -n1)
if [ -n "$ts" ] && [ -n "$bn" ]; then
	value="${version%-SNAPSHOT}-$ts-$bn"
else
	value=$version
fi

jarurl="$BASE/$GA/$version/txtrepo-$value.jar"

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT

# the host sends one line of base64; line breaks are dropped should that ever change
fetch "$jarurl$SUFFIX" | tr -d '\r\n' | openssl base64 -A -d > "$tmp/txtrepo.jar"

# verify the decoded bytes against the strongest checksum the repo publishes
verified=
for algo in 512 256 1; do
	sum=$(fetch "$jarurl.sha$algo" | tr -d '[:space:]') || continue
	[ -n "$sum" ] || continue
	got=$(openssl dgst -sha$algo "$tmp/txtrepo.jar" | awk '{print $NF}')
	[ "$sum" = "$got" ] || { echo "checksum mismatch (sha$algo) for txtrepo-$value.jar" >&2; exit 1; }
	verified=sha$algo
	break
done
[ -n "$verified" ] || { echo "no checksum to verify txtrepo-$value.jar against" >&2; exit 1; }

# a version free path outside the repository tree, which gets wiped now and then
jar="${HOME}/.m2/txtrepo.jar"
mkdir -p "${HOME}/.m2"
mv "$tmp/txtrepo.jar" "$jar"

# windows needs a native path, and the launchers expand this unquoted
case $(uname -s) in
	MINGW* | MSYS* | CYGWIN*) opt=$(cygpath -ms "$jar"); win=$(cygpath -u "$USERPROFILE") ;;
	*) opt="$jar"; win= ;;
esac
prop="-Dmaven.ext.class.path=$opt"

# append a line to a file unless it is already there; $3 is an extra line ending
once() { tr -d '\r' 2>/dev/null < "$1" | grep -qxF -- "$2" || printf "%s${3:-}\n" "$2" >> "$1"; }

# the host this ran against
host=$(printf '%s' "$BASE" | sed -e 's|^[a-z+]*://||' -e 's|[:/].*||')
hosts="${HOME}/.m2/txtrepo.hosts"
once "$hosts" "$host"

# the environment of every build; mvn reads MAVEN_ARGS, mvnw only MAVEN_OPTS
rc="${HOME}/.mavenrc"
once "$rc" "MAVEN_ARGS=\"\${MAVEN_ARGS:-} $prop\""
once "$rc" "MAVEN_OPTS=\"\${MAVEN_OPTS:-} $prop\""

# cmd.exe sources none of that: mvnw.cmd and maven 3 call mavenrc_pre.cmd, maven 4 mavenrc.cmd
if [ -n "$win" ]; then
	for f in "$win/mavenrc_pre.cmd" "$win/mavenrc.cmd"; do
		once "$f" "set MAVEN_ARGS=%MAVEN_ARGS% $prop" '\r'
		once "$f" "set MAVEN_OPTS=%MAVEN_OPTS% $prop" '\r'
	done
fi

cat >&2 <<EOM
txtrepo $version installed ($verified verified)
  $jar

Every mvn and mvnw run now armors $host, nothing to add per project:
  $hosts  the hosts to armor, one per line
  $rc  the environment both launchers source${win:+
  $win/mavenrc_pre.cmd  the same for mvnw.cmd and maven 3 from cmd.exe
  $win/mavenrc.cmd  the same for maven 4}

Delete those lines to undo it. A project overrides either from .mvn/maven.config.
EOM
