Files
rk1/media/scripts/fetch-sources.sh
T

86 lines
2.8 KiB
Bash
Raw Permalink Normal View History

2026-08-17 18:42:29 +00:00
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
# shellcheck source=lib.sh
. "${SCRIPT_DIR}/lib.sh"
LOCK_FILE="${RKMEDIA_ROOT}/sources.lock.json"
DEST_DIR="${RKMEDIA_ROOT}/out/sources"
usage() {
cat <<'EOF'
Usage: fetch-sources.sh [--lock FILE] [--dest DIRECTORY]
Fetch every build input at the exact commit recorded in the source lock.
Existing repositories are accepted only when their origin and HEAD match.
EOF
}
while (($#)); do
case "$1" in
--lock)
[[ $# -ge 2 ]] || die "--lock requires a file"
LOCK_FILE="$2"
shift 2
;;
--dest)
[[ $# -ge 2 ]] || die "--dest requires a directory"
DEST_DIR="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*) die "unknown argument: $1" ;;
esac
done
need_command git
need_command jq
LOCK_FILE="$(absolute_path "${LOCK_FILE}")"
DEST_DIR="$(absolute_path "${DEST_DIR}")"
[[ -f "${LOCK_FILE}" ]] || die "source lock not found: ${LOCK_FILE}"
jq -e '.schema_version == 1 and (.sources | type == "array")' "${LOCK_FILE}" >/dev/null \
|| die "invalid source lock: ${LOCK_FILE}"
mkdir -p -- "${DEST_DIR}"
verify_checkout() {
local dir="$1" expected_repo="$2" expected_commit="$3"
local actual_repo actual_commit
[[ -d "${dir}/.git" ]] || return 1
actual_repo="$(git -C "${dir}" remote get-url origin 2>/dev/null || true)"
actual_commit="$(git -C "${dir}" rev-parse HEAD 2>/dev/null || true)"
[[ "${actual_repo}" == "${expected_repo}" && "${actual_commit}" == "${expected_commit}" ]]
}
while IFS=$'\t' read -r name repository ref commit; do
[[ "${name}" =~ ^[a-z0-9][a-z0-9._-]*$ ]] || die "unsafe source name in lock: ${name}"
[[ "${commit}" =~ ^[0-9a-f]{40}$ ]] || die "invalid commit for ${name}: ${commit}"
source_dir="${DEST_DIR}/${name}"
if verify_checkout "${source_dir}" "${repository}" "${commit}"; then
log "source already verified: ${name} ${commit}"
continue
fi
if [[ -e "${source_dir}" ]]; then
die "${source_dir} exists but does not match the lock; move it aside and retry"
fi
log "fetching ${name} at ${commit}"
mkdir -p -- "${source_dir}"
git -C "${source_dir}" init --quiet
git -C "${source_dir}" remote add origin "${repository}"
if ! git -C "${source_dir}" fetch --quiet --depth=1 origin "${commit}"; then
log "direct commit fetch was unavailable; fetching history from ${ref}"
git -C "${source_dir}" fetch --quiet --filter=blob:none origin "${ref}"
fi
git -C "${source_dir}" checkout --quiet --detach "${commit}"
verify_checkout "${source_dir}" "${repository}" "${commit}" \
|| die "checkout verification failed for ${name}"
done < <(jq -r '.sources[] | select(.build == true) | [.name, .repository, .ref, .commit] | @tsv' "${LOCK_FILE}")
log "all locked sources are present in ${DEST_DIR}"