#!/usr/bin/env bash # Usage: script/mirror update # script/mirror verify # script/mirror stats set -e eval "$(grep RUBY_BUILD_MIRROR_URL= ./bin/ruby-build | head -1)" help_text() { sed -ne '/^#/!q;s/.\{1,2\}//;1d;p' < "$0" } test_mirrored() { curl -qsSfIL "$RUBY_BUILD_MIRROR_URL/$1" >/dev/null 2>&1 } compute_sha2() { local output output="$(openssl dgst -sha256)" tr '[:upper:]' '[:lower:]' <<<"${output##* }" } download_package() { curl -qsSfL -o "$2" "$1" } download_and_verify() { local checksum local url="$1" local file="$2" local expected="$3" download_package "$url" "$file" checksum="$(compute_sha2 < "$file")" if [ "$checksum" != "$expected" ]; then echo "Error: $url doesn't match its checksum $expected" >&2 return 1 fi } changed_files() { git diff --name-only --diff-filter=ACMR "$@" } potentially_new_packages() { local head="${1#*..}" local files IFS=$'\n' read -d '' -r -a files < <(changed_files "$1" -- ./share/ruby-build) [ ${#files[@]} -gt 0 ] || return 0 extract_urls "${head:-HEAD}" -- "${files[@]}" } extract_urls() { git grep -hoe 'http[^"]\+#[^"]\+' "$@" | sort | uniq } update() { local url local checksum local file local tmp_path for url in $(potentially_new_packages "$1"); do checksum="${url#*#}" url="${url%#*}" if test_mirrored "$checksum"; then echo "Already mirrored: $url" else echo "Will mirror: $url" [ -n "$tmp_path" ] || tmp_path="$(mktemp -d "${TMPDIR:-/tmp}/s3-sync.XXXXX")" file="$tmp_path/$checksum" download_and_verify "$url" "$file" "$checksum" fi done if [ -n "$tmp_path" ]; then echo "Uploading..." aws s3 sync --acl=public-read --size-only --no-progress "$tmp_path" "s3://${AMAZON_S3_BUCKET?}" fi } verify() { local url local checksum local file local status=0 for url in $(potentially_new_packages "$1"); do checksum="${url#*#}" url="${url%#*}" echo "Verifying checksum for $url" file="${TMPDIR:-/tmp}/$checksum" download_and_verify "$url" "$file" "$checksum" || status=$? done return $status } stats() { local packages IFS=$'\n' read -d '' -r -a packages < <(extract_urls -- ./share/ruby-build/\*) local total="${#packages[@]}" local confirmed=0 local checksum for url in "${packages[@]}"; do checksum="${url#*#}" if test_mirrored "$checksum"; then : $((confirmed++)) else echo "failed: $url" >&2 fi echo -n "." done echo echo "$confirmed/$total mirrored" } cmd="$1" case "$cmd" in update | verify | stats ) shift 1 "$cmd" "$@" ;; -h | --help ) help_text exit 0 ;; * ) help_text >&2 exit 1 ;; esac