Skip to content

Instantly share code, notes, and snippets.

@MichaelNesterenko
Last active November 1, 2024 11:07
Show Gist options
  • Save MichaelNesterenko/838efa5a7127c1df7ebd8b018f93ae8d to your computer and use it in GitHub Desktop.
Save MichaelNesterenko/838efa5a7127c1df7ebd8b018f93ae8d to your computer and use it in GitHub Desktop.
maven transfer dependencies
#!/usr/bin/env bash
set -eEuo pipefail
shopt -s inherit_errexit
trap "echo command failed 1>&2" ERR
repo_url="$1"
export DEPLOYMENT_TARGET_USERNAME="$2"
export DEPLOYMENT_TARGET_PASSWORD="$3"
shift 3
opt_force_upload=false
opt_dep_release=false
opt_dep_snapshot=false
while getopts "frs" opt; do
case "${opt}" in
f) opt_force_upload=true ;;
r) opt_dep_release=true ;;
s) opt_dep_snapshot=true ;;
esac
done
declare -a path_to_remove && trap '[[ "${#path_to_remove[@]}" -gt 0 ]] && rm -rf "${path_to_remove[@]}"' EXIT
function make_tmp() {
eval "$1=\$(shift; mktemp \"\$@\"); path_to_remove+=("\$$1")"
}
function msg() {
printf "===== %s\n" "$(printf "$1")"
}
maven_deploy_plugin=org.apache.maven.plugins:maven-deploy-plugin:3.1.3
make_tmp mvn_tmp -d
make_tmp mvn_dep_input
make_tmp mvn_dep_file
make_tmp mvn_settings
echo "$(
cat ~/.m2/settings.xml | \
xmlstarlet ed -N xmlns=http://maven.apache.org/SETTINGS/1.0.0 -d "/_:settings/_:servers" -s "/_:settings" -t elem -n servers | \
xmlstarlet ed -N xmlns=http://maven.apache.org/SETTINGS/1.0.0 -s "/_:settings/_:servers" -t elem -n server | \
xmlstarlet ed -N xmlns=http://maven.apache.org/SETTINGS/1.0.0 -s "/_:settings/_:servers/_:server" -t elem -name id -v deployment-target \
-s "/_:settings/_:servers/_:server" -t elem -name username -v '${DEPLOYMENT_TARGET_USERNAME}' \
-s "/_:settings/_:servers/_:server" -t elem -name password -v '${DEPLOYMENT_TARGET_PASSWORD}'
)" > "$mvn_settings"
mvn -B dependency:3.8.1:get -Dartifact=$maven_deploy_plugin:jar
for c in resolve resolve-plugins resolve-sources; do
mvn -B dependency:3.8.1:$c -DexcludeScope=system -DappendOutput=true "-DoutputFile=$mvn_dep_input" -DoutputAbsoluteArtifactFilename=true -Dmdep.outputScope=false
done
function dep_short_name() {
local a="$1"; local v="$2"; local c="$3"
echo "$a-$v$([[ -n "$c" ]] && echo "-$c")"
}
function dep_coord_to_path() {
local g="$1"; local a="$2"; local v="$3"; local p="$4"; local c="$5"
echo "${g//./\/}/$a/$v/$(dep_short_name "$a" "$v" "$c").$p"
}
function compare_local_to_remote() {
local local_path="$1"
local remote_path="$2"
local remote_payload="$((curl -sf "$remote_path" || true) | base64 -w0)" # may have falsely report that dependency is not available if transport error occurs
if [[ -z "$remote_payload" ]]; then
echo "missing"
elif [[ "$(base64 -w0 < "$local_path")" == "$remote_payload" ]]; then
echo "present"
else
echo "differs"
fi
}
cp "$mvn_dep_input" deps.txt
cd "$mvn_tmp" && cat "$mvn_dep_input" | grep -E '^ +' | awk '{print $1}' | sort -u | while read -r dep; do
msg "processing $dep"
(
if [[ "$(dep=${dep//[^:]/}; echo ${#dep})" -eq 4 ]]; then
IFS=: read -r dep_group dep_artifact _ dep_version dep_path <<< "$dep"
dep_classifier=""
elif [[ "$(dep=${dep//[^:]/}; echo ${#dep})" -eq 5 ]]; then
IFS=: read -r dep_group dep_artifact _ dep_classifier dep_version dep_path <<< "$dep"
else
msg "\tWARN: ignoring unknwon dependency"
exit 0
fi
dep_pkg=$(basename "$dep_path"); dep_pkg=${dep_pkg##$(dep_short_name "$dep_artifact" "$dep_version" "$dep_classifier").}
dep_coord_path="$(dep_coord_to_path "$dep_group" "$dep_artifact" "$dep_version" "$dep_pkg" "$dep_classifier")"
pom_coord_path="$(dep_coord_to_path "$dep_group" "$dep_artifact" "$dep_version" "pom" "")"
pom_path="$(dirname "$dep_path")/$(basename "$pom_coord_path")"
msg "\tg:$dep_group a:$dep_artifact p:$dep_pkg v:$dep_version c:${dep_classifier} dp:$dep_path pom:$pom_path"
if [[ -f "$pom_path" ]]; then
if ! ( ([[ "$opt_dep_release" = "true" ]] && [[ "$dep_version" != *-SNAPSHOT ]]) || \
([[ "$opt_dep_snapshot" = "true" ]] && [[ "$dep_version" = *-SNAPSHOT ]]) ); then
msg "\t\tskipping version $dep_version"
exit 0
fi
remote_pom_path="$repo_url/$pom_coord_path"
remote_dep_path="$repo_url/$dep_coord_path"
comparison_state="$(compare_local_to_remote "$pom_path" "$remote_pom_path") $(compare_local_to_remote "$dep_path" "$remote_dep_path")"
while true; do
case "$comparison_state" in
*differs*)
if [[ "$comparison_state" = differs\ * ]]; then
msg "\t\tWARN: will upload only if forced, contents differ for pom: $remote_pom_path != $pom_path"
diff -uw <(curl -s "$remote_pom_path") "$pom_path" || true
fi
if [[ "$comparison_state" = *\ differs ]]; then
msg "\t\tWARN: will upload only if forced, contents differ for dep: $remote_dep_path != $dep_path"
fi
if [[ "$opt_force_upload" = "true" ]]; then
msg "\t\tforcing upload"
else
break
fi
;&
missing\ missing|present\ missing|missing\ present)
mvn -s "$mvn_settings" $maven_deploy_plugin:deploy-file \
-DrepositoryId=deployment-target "-Durl=$repo_url" \
"-Dfile=$(cp "$dep_path" "$mvn_dep_file" && echo "$mvn_dep_file")" \
-DgeneratePom=false "-DpomFile=$pom_path" \
-Dpackaging=$dep_pkg "-Dversion=$dep_version" $([[ -n "${dep_classifier}" ]] && echo "-Dclassifier=$dep_classifier")
msg "\t\tOK: uploaded ($comparison_state) ($remote_pom_path $remote_dep_path)"
;;
present\ present) msg "\t\tOK: upload skipped, already present" ;;
esac
break
done
else
msg "\t\tWARN: skipping upload, local pom file missing: $pom_path"
fi
)
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment