#!/bin/sh # File: yummirror.sh # Location: https://gitlab.com/bgstack15/coprmirror # Author: bgstack15 # Startdate: 2021-08-16 09:57 # SPDX-License-Identifier: GPL-3.0 # Title: Script that copies a single copr yum repo # Project: coprmirror # Purpose: mirror copr locally, given baseurl; part of a larger set # History: # Usage: # Called by a larger script that catches the entire copr. This file only does a single yum repo for a single architecture and OS release. See coprmirror.sh # References: # https://unix.stackexchange.com/questions/19701/yum-how-can-i-view-variables-like-releasever-basearch-yum0 # https://gitlab.com/bgstack15/former-gists/-/blob/master/obsmirror.sh/obsmirror.sh # Improve: # resign_repo is not implemented yet. # Dependencies: # jq, yum-utils, awk, sed, grep umask 0002 test -n "${YUMMIRROR_CONF}" && . "${YUMMIRROR_CONF}" test -z "${logfile}" && logfile=./yummirror.$( date "+%FT%H%M%S" ).log test -z "${inurl}" && inurl='https://copr-be.cloud.fedoraproject.org/results/bgstack15/stackrpms/epel-7-$basearch/' test -z "${workdir}" && workdir=/tmp/copr test -z "${thisuser}" && thisuser=${USER} # also use include_sources resign_repo DEBUG VERBOSE exec 3>&1 show() { printf "%s" "${*}" 1>&3 } reset_show() { printf "\r%s" "${*}" 1>&3 } ## Functions get_file() { # call: get_file "${tu}" "${md5sum}" "absolute" ___tu="${1}" ___sum="${2}" ___abs="${3}" if test "${___abs}" = "absolute" ; then tn="$( basename "${___tu}" )" else tn="${___tu##${inurl}}" fi tf="${workdir}/${tn}" ; tf="$( readlink -m "${tf}" )" td="$( dirname "${tf}" )" test -d "${td}" || mkdir -p "${td}" gotten="skipped " #printf '\n%s\n' "inside get_file ${@}, DRYRUN=${DRYRUN}" if test -z "${DRYRUN}" || test "${DRYRUN}" = "metadata"; then if test -z "${___sum}" || test "$( sha256sum "${tf}" 2>/dev/null | awk '{print $1}' )" != "${___sum}" ; then test -n "${VERBOSE}" && show "retrieving ${___tu}" 2>/dev/null || : wget --content-disposition --no-verbose --quiet -O "${tf}" "${___tu}" && gotten=DOWNLOADED fi fi test -n "${VERBOSE}" && reset_show 2>/dev/null || : echo "${gotten} ${___tu} -> ${tf}" } ## MAIN # Interpret any yum vars in the inurl if echo "${inurl}" | grep -qE '\$' ; then echo "" | jq 1>/dev/null 2>&1 || { echo "Need jq to interpret yum vars in baseurl ${inurl}. Aborted." ; exit 1 ; } raw="$( python -c 'import yum, json; yb = yum.YumBase(); print json.dumps(yb.conf.yumvar, indent=2)' )" # validated on centos 7 basearch="$( echo "${raw}" | sed -n '1!p' | jq '.basearch' | tr -d '"' )" releasever="$( echo "${raw}" | sed -n '1!p' | jq '.releasever' | tr -d '"' )" #echo "${inurl}" | awk -v "basearch=${basearch}" -v "releasever=${releasever}" '{gsub("\$basearch",basearch,$0);gsub("\$releasever",releasever,$0);print}' newurl="$( echo "${inurl}" | sed -r -e "s/\\\$basearch/${basearch}/g;" -e "s/\\\$releasever/${releasever}/g;" )" test -n "${DEBUG}" && { echo "Interpreting ${inurl} -> ${newurl}" } 1>&2 inurl="${newurl}" fi # clean up trailing slashes inurl="${inurl%%/}" # sync to workdir wget_verbose=--quiet test -n "${VERBOSE}" && unset wget_verbose { test "${DEBUG:-NONE}" = "FULL" && set -x echo "logfile=${logfile}" mkdir -p "${workdir}" ; cd "${workdir}" # This file lists the files that define a yum repo for word in repodata/repomd.xml ; do # coprmirror.sh will pass DRYRUN=metadata if it has anything set in dryrun, and we interpret "metadata" here, because we absolutely need the repomd.xml and associated files no matter what, even for a dry run. DRYRUN="${DRYRUN:+metadata}" get_file "${inurl%%/}/${word}" done # loop through the important files listed in that file. # read sha256sum, so we don't have to download these if we already have them. metadata_list="$( grep -iE '/{gsub(\"^>\",\"\",\$0);gsub(\"<.*$\",\"\",\$0);a=\$0;} /repodata/{print a,\$0}" )" echo "${metadata_list}" | while read sum word ; do DRYRUN="${DRYRUN:+metadata}" get_file "${inurl%%/}/${word}" "${sum}" 3>/dev/null done # go ahead and fetch the gpgkey if resign_repo=no if echo "${resign_repo}" | grep -qiE 'yes|\|1|true' ; then # do something echo "Resigning functionality not built yet. Skipping..." else if test -n "${gpgkey}" ; then # fetch the gpgkey # note: yum variable parsing not yet implemented here. I would need to turn the variable parsing into a function and call it here. # cannot use get_file because it uses a relative path evaluation #wget --output-file="${workdir}/pubkey.gpg" "${gpgkey}" get_file "${gpgkey}" "" "absolute" fi fi # COPR always provides a primary.xml.gz file, which lists the assets to download full_list="$( zgrep -iE 'checksum|href' $( grep -oiE 'href=.*primary.xml.gz.*$' repodata/repomd.xml 2>/dev/null | awk -F'"' '{print $2}' ; echo "none.XXXXXXX" ) 2>/dev/null | awk "/checksum/{gsub(\".*\\\">\",\"\",\$0);gsub(\"|1|true' ; then get_file "${inurl}/${word}" "${sum}" fi else # always get all regular rpms and other non-.src.rpm files if any get_file "${inurl}/${word}" "${sum}" fi done chown -R "${thisuser}:$( id -G "${thisuser}" | awk '{print $1}' )" "${workdir}" } 2>&1 | tee -a "${logfile}"