index : devtools32 | |
Archlinux32 fork of devtools | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | src/pkgrepo.in | 260 |
diff --git a/src/pkgrepo.in b/src/pkgrepo.in new file mode 100644 index 0000000..2804cba --- /dev/null +++ b/src/pkgrepo.in @@ -0,0 +1,260 @@ +#!/bin/bash +# +# SPDX-License-Identifier: GPL-3.0-or-later + +m4_include(lib/common.sh) + +source /usr/share/makepkg/util/config.sh +source /usr/share/makepkg/util/message.sh + +set -e + + +usage() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} [COMMAND] [OPTIONS] + + Manage Git packaging repositories and helps with their configuration + according to distro specs. + + Git author information and the used signing key is set up from + makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. + The configure command can be used to synchronize the distro specs and + makepkg.conf settings for previously cloned repositories. + + The unprivileged option can be used for cloning packaging repositories + without SSH access using read-only HTTPS. + + COMMANDS + clone Clone a package repository + configure Configure a clone according to distro specs + + OPTIONS + -h, --help Show this help text +_EOF_ +} + +usage_clone() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} clone [OPTIONS] [PKGNAME...] + + Clone Git packaging repositories from the canonical namespace. + + The configure command is subsequently invoked to synchronize the distro + specs and makepkg.conf settings. The unprivileged option can be used + for cloning packaging repositories without SSH access using read-only + HTTPS. + + OPTIONS + -m, --maintainer=NAME Clone all packages of the named maintainer + -u, --unprivileged Clone package with read-only access and without + packager info as Git author. + -h, --help Show this help text +_EOF_ +} + +usage_configure() { + cat <<- _EOF_ + Usage: ${BASH_SOURCE[0]##*/} configure [OPTIONS] [PATH...] + + Configure Git packaging repositories according to distro specs and + makepkg.conf settings. + + Git author information and the used signing key is set up from + makepkg.conf read from any valid location like /etc or XDG_CONFIG_HOME. + The unprivileged option can be used for cloning packaging repositories + without SSH access using read-only HTTPS. + + OPTIONS + -u, --unprivileged Configure read-only repo without packager info as Git author. + -h, --help Show this help text +_EOF_ +} + +if (( $# < 1 )); then + usage + exit 1 +fi + +# commands +CLONE=0 +CONFIGURE=0 + +# options +GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_SSH} +UNPRIVILEGED=0 +MAINTAINER= +PACKAGER_NAME= +PACKAGER_EMAIL= + +# command checking +while (( $# )); do + case $1 in + -h|--help) + usage + exit 0 + ;; + clone) + CLONE=1 + CONFIGURE=1 + shift + break + ;; + configure) + CONFIGURE=1 + shift + break + ;; + *) + die "invalid argument: %s" "$1" + ;; + esac +done + +if (( CLONE )); then + # option checking + if (( $# < 1 )); then + usage_clone + exit 1 + fi + while (( $# )); do + case $1 in + -h|--help) + usage_clone + exit 0 + ;; + -u|--unprivileged) + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} + UNPRIVILEGED=1 + shift + ;; + -m|--maintainer) + (( $# <= 1 )) && die "missing argument for %s" "$1" + MAINTAINER="$2" + shift 2 + ;; + --maintainer=*) + MAINTAINER="${1#*=}" + shift + ;; + --) + shift + break + ;; + -*) + die "invalid argument: %s" "$1" + ;; + *) + break + ;; + esac + done +elif (( CONFIGURE )); then + # option checking + if (( $# < 1 )); then + usage_configure + exit 1 + fi + while (( $# )); do + case $1 in + -h|--help) + usage_configure + exit 0 + ;; + -u|--unprivileged) + GIT_REPO_BASE_URL=${GIT_PACKAGING_URL_HTTPS} + UNPRIVILEGED=1 + shift + ;; + --) + shift + break + ;; + -*) + die "invalid argument: %s" "$1" + ;; + *) + break + ;; + esac + done +fi + +pkgbases=("$@") + +# Load makepkg.conf variables to be available +load_makepkg_config + +# Check official packaging identity before setting Git author +if (( ! UNPRIVILEGED )); then + if [[ $PACKAGER == *"Unknown Packager"* ]]; then + die "Packager must be set in makepkg.conf" + fi + packager_pattern="(.+) <(.+@.+)>" + if [[ ! $PACKAGER =~ $packager_pattern ]]; then + die "Invalid Packager format '${PACKAGER}' in makepkg.conf" + fi + + PACKAGER_NAME=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\1/") + PACKAGER_EMAIL=$(echo "${PACKAGER}"|sed -E "s/${packager_pattern}/\2/") + + if [[ ! $PACKAGER_EMAIL =~ .+@archlinux.org ]]; then + die "Packager email '${PACKAGER_EMAIL}' is not an @archlinux.org address" + fi +fi + +# Query packages of a maintainer +if [[ -n ${MAINTAINER} ]]; then + stat_busy "Query packages for ${MAINTAINER}" + max_pages=$(curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}" | jq -r '.num_pages') + mapfile -t pkgbases < <(for page in $(seq "${max_pages}"); do + curl --silent --location --fail --retry 3 --retry-delay 3 "https://archlinux.org/packages/search/json/?sort=name&maintainer=${MAINTAINER}&page=${page}" | jq -r '.results[].pkgbase' + stat_progress + done | sort --unique) + stat_done +fi + +for pkgbase in "${pkgbases[@]}"; do + if (( CLONE )); then + if [[ ! -d ${pkgbase} ]]; then + msg "Cloning ${pkgbase} ..." + remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" + git clone --origin origin "${remote_url}" + else + warning "Skip cloning ${pkgbase}: Directory exists" + fi + fi + + if (( CONFIGURE )); then + msg "Configuring $(basename "${pkgbase}") ..." + path=${pkgbase} + if [[ ! -d "${path}/.git" ]]; then + error "Not a Git repository: ${path}" + continue + fi + + giturl=$(git -C "${path}" remote get-url origin) + if [[ ${giturl} != *${GIT_PACKAGING_NAMESPACE}* ]]; then + error "Not a packaging repository: ${path}" + continue + fi + + pkgbase=$(basename "${giturl}") + pkgbase=${pkgbase%.git} + remote_url="${GIT_REPO_BASE_URL}/${pkgbase}.git" + + git -C "${path}" remote set-url origin "${remote_url}" + git -C "${path}" config devtools.version "${GIT_REPO_SPEC_VERSION}" + git -C "${path}" config commit.gpgsign true + git -C "${path}" config pull.rebase true + git -C "${path}" config branch.main.rebase true + + if (( ! UNPRIVILEGED )); then + git -C "${path}" config user.name "${PACKAGER_NAME}" + git -C "${path}" config user.email "${PACKAGER_EMAIL}" + if [[ -n $GPGKEY ]]; then + git -C "${path}" config user.signingKey "${GPGKEY}" + fi + fi + fi +done |