diff options
Diffstat (limited to 'src/commitpkg.in')
-rw-r--r-- | src/commitpkg.in | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/commitpkg.in b/src/commitpkg.in new file mode 100644 index 0000000..31adcd6 --- /dev/null +++ b/src/commitpkg.in @@ -0,0 +1,241 @@ +#!/bin/bash +# +# SPDX-License-Identifier: GPL-3.0-or-later + +m4_include(lib/common.sh) + +# Source makepkg.conf; fail if it is not found +if [[ -r '/etc/makepkg.conf' ]]; then + # shellcheck source=config/makepkg/x86_64.conf + source '/etc/makepkg.conf' +else + die '/etc/makepkg.conf not found!' +fi + +# Source user-specific makepkg.conf overrides +if [[ -r "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" ]]; then + # shellcheck source=/dev/null + source "${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" +elif [[ -r "$HOME/.makepkg.conf" ]]; then + # shellcheck source=/dev/null + source "$HOME/.makepkg.conf" +fi + +cmd=${0##*/} + +if [[ ! -f PKGBUILD ]]; then + die 'No PKGBUILD file' +fi + +source=() +# shellcheck source=PKGBUILD.proto +. ./PKGBUILD +pkgbase=${pkgbase:-$pkgname} + +case "$cmd" in + commitpkg) + if (( $# == 0 )); then + die 'Usage: commitpkg <reponame> [-f] [-s server] [-l limit] [-a arch] [commit message]' + fi + repo="$1" + shift + ;; + *pkg) + repo="${cmd%pkg}" + ;; + *) + die 'Usage: commitpkg <reponame> [-f] [-s server] [-l limit] [-a arch] [commit message]' + ;; +esac + + +if (( ${#validpgpkeys[@]} != 0 )); then + if [[ -d keys ]]; then + for key in "${validpgpkeys[@]}"; do + if [[ ! -f keys/pgp/$key.asc ]]; then + export-pkgbuild-keys || die 'Failed to export valid PGP keys for source files' + fi + done + else + export-pkgbuild-keys || die 'Failed to export valid PGP keys for source files' + fi + + svn add --parents --force keys/pgp/* +fi + +# find files which should be under source control +needsversioning=() +for s in "${source[@]}"; do + [[ $s != *://* ]] && needsversioning+=("$s") +done +for i in 'changelog' 'install'; do + while read -r file; do + # evaluate any bash variables used + eval "file=\"$(sed "s/^\(['\"]\)\(.*\)\1\$/\2/" <<< "$file")\"" + needsversioning+=("$file") + done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) +done +for key in "${validpgpkeys[@]}"; do + needsversioning+=("keys/pgp/$key.asc") +done + +# assert that they really are controlled by SVN +if (( ${#needsversioning[*]} )); then + # svn status's output is only two columns when the status is unknown + while read -r status filename; do + [[ $status = '?' ]] && unversioned+=("$filename") + done < <(svn status -v "${needsversioning[@]}") + (( ${#unversioned[*]} )) && die "%s is not under version control" "${unversioned[@]}" +fi + +rsyncopts=(-e ssh -p '--chmod=ug=rw,o=r' -c -h -L --progress --partial -y) +archreleaseopts=() +while getopts ':l:a:s:f' flag; do + case $flag in + f) archreleaseopts+=('-f') ;; + s) server=$OPTARG ;; + l) rsyncopts+=("--bwlimit=$OPTARG") ;; + a) commit_arch=$OPTARG ;; + :) die "Option requires an argument -- '%s'" "$OPTARG" ;; + \?) die "Invalid option -- '%s'" "$OPTARG" ;; + esac +done +shift $(( OPTIND - 1 )) + +# check packages for validity +for _arch in "${arch[@]}"; do + if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then + continue + fi + for _pkgname in "${pkgname[@]}"; do + fullver=$(get_full_version "$_pkgname") + + if pkgfile=$(find_cached_package "$_pkgname" "$fullver" "$_arch"); then + check_package_validity "$pkgfile" + fi + done + + fullver=$(get_full_version "$pkgbase") + if pkgfile=$(find_cached_package "$pkgbase-debug" "$fullver" "$_arch"); then + check_package_validity "$pkgfile" + fi +done + +if [[ -z $server ]]; then + server='repos.archlinux.org' +fi + +if [[ -n $(svn status -q) ]]; then + msgtemplate="upgpkg: $pkgbase $(get_full_version)" + if [[ -n $1 ]]; then + stat_busy 'Committing changes to trunk' + svn commit -q -m "${msgtemplate}: ${1}" || die + stat_done + else + msgfile="$(mktemp)" + echo "$msgtemplate" > "$msgfile" + if [[ -n $SVN_EDITOR ]]; then + $SVN_EDITOR "$msgfile" + elif [[ -n $VISUAL ]]; then + $VISUAL "$msgfile" + elif [[ -n $EDITOR ]]; then + $EDITOR "$msgfile" + else + vi "$msgfile" + fi + [[ -s $msgfile ]] || die + stat_busy 'Committing changes to trunk' + svn commit -q -F "$msgfile" || die + unlink "$msgfile" + stat_done + fi +fi + +declare -a uploads +declare -a commit_arches +declare -a skip_arches + +for _arch in "${arch[@]}"; do + if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then + skip_arches+=("$_arch") + continue + fi + + for _pkgname in "${pkgname[@]}"; do + fullver=$(get_full_version "$_pkgname") + if ! pkgfile=$(find_cached_package "$_pkgname" "$fullver" "${_arch}"); then + warning "Skipping %s: failed to locate package file" "$_pkgname-$fullver-$_arch" + skip_arches+=("$_arch") + continue 2 + fi + uploads+=("$pkgfile") + done + + fullver=$(get_full_version "$pkgbase") + if ! pkgfile=$(find_cached_package "$pkgbase-debug" "$fullver" "$_arch"); then + continue + fi + if ! is_debug_package "$pkgfile"; then + continue + fi + uploads+=("$pkgfile") +done + +for pkgfile in "${uploads[@]}"; do + sigfile="${pkgfile}.sig" + if [[ ! -f $sigfile ]]; then + msg "Signing package %s..." "${pkgfile}" + if [[ -n $GPGKEY ]]; then + SIGNWITHKEY=(-u "${GPGKEY}") + fi + gpg --detach-sign --use-agent --no-armor "${SIGNWITHKEY[@]}" "${pkgfile}" || die + fi + if ! gpg --verify "$sigfile" "$pkgfile" >/dev/null 2>&1; then + die "Signature %s is incorrect!" "$sigfile" + fi + uploads+=("$sigfile") +done + +for _arch in "${arch[@]}"; do + if ! in_array "$_arch" "${skip_arches[@]}"; then + commit_arches+=("$_arch") + fi +done + +if [[ ${#commit_arches[*]} -gt 0 ]]; then + archrelease "${archreleaseopts[@]}" "${commit_arches[@]/#/$repo-}" || die +fi + +if [[ ${#uploads[*]} -gt 0 ]]; then + new_uploads=() + + # convert to absolute paths so rsync can work with colons (epoch) + while read -r -d '' upload; do + new_uploads+=("$upload") + done < <(realpath -z "${uploads[@]}") + + uploads=("${new_uploads[@]}") + unset new_uploads + msg 'Uploading all package and signature files' + rsync "${rsyncopts[@]}" "${uploads[@]}" "$server:staging/$repo/" || die +fi + +if [[ "${arch[*]}" == 'any' ]]; then + if [[ -d ../repos/$repo-x86_64 ]]; then + pushd ../repos/ >/dev/null + stat_busy "Removing %s" "$repo-x86_64" + svn rm -q "$repo-x86_64" + svn commit -q -m "Removed $repo-x86_64 for $pkgname" + stat_done + popd >/dev/null + fi +else + if [[ -d ../repos/$repo-any ]]; then + pushd ../repos/ >/dev/null + stat_busy "Removing %s" "$repo-any" + svn rm -q "$repo-any" + svn commit -q -m "Removed $repo-any for $pkgname" + stat_done + popd >/dev/null + fi +fi |