devtools/commitpkg.in

215 lines
5.6 KiB
Bash

#!/bin/bash
# License: Unspecified
m4_include(lib/common.sh)
# Source makepkg.conf; fail if it is not found
if [[ -r '/etc/makepkg.conf' ]]; then
# shellcheck source=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
# 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
# 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
if grep -q "packager = Unknown Packager" <(bsdtar -xOqf "$pkgfile" .PKGINFO); then
die "PACKAGER was not set when building package"
fi
hashsum=sha256sum
pkgbuild_hash=$(awk -v"hashsum=$hashsum" -F' = ' '$1 == "pkgbuild_"hashsum {print $2}' <(bsdtar -xOqf "$pkgfile" .BUILDINFO))
if [[ "$pkgbuild_hash" != "$($hashsum PKGBUILD|cut -d' ' -f1)" ]]; then
die "PKGBUILD $hashsum mismatch: expected $pkgbuild_hash"
fi
fi
done
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")
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
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