summaryrefslogtreecommitdiff
path: root/src/abslibre-tools/librerelease
diff options
context:
space:
mode:
Diffstat (limited to 'src/abslibre-tools/librerelease')
-rwxr-xr-xsrc/abslibre-tools/librerelease257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/abslibre-tools/librerelease b/src/abslibre-tools/librerelease
new file mode 100755
index 0000000..b7a77d3
--- /dev/null
+++ b/src/abslibre-tools/librerelease
@@ -0,0 +1,257 @@
+#!/usr/bin/env bash
+# Librerelease
+# Uploads packages and releases them
+
+# Copyright (C) 2010-2012 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com>
+# Copyright (C) 2010-2013 Nicolás Reynolds <fauno@parabola.nu>
+# Copyright (C) 2013 Michał Masłowski <mtjm@mtjm.eu>
+# Copyright (C) 2013-2014 Luke Shumaker <lukeshu@sbcglobal.net>
+#
+# For just the create_signature() function:
+# Copyright (C) 2006-2013 Pacman Development Team <pacman-dev@archlinux.org>
+# Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>
+# Copyright (C) 2005 Aurelien Foret <orelien@chez.com>
+# Copyright (C) 2006 Miklos Vajna <vmiklos@frugalware.org>
+# Copyright (C) 2005 Christian Hamar <krics@linuxforum.hu>
+# Copyright (C) 2006 Alex Smith <alex@alex-smith.me.uk>
+# Copyright (C) 2006 Andras Voroskoi <voroskoi@frugalware.org>
+#
+# License: GNU GPLv3+
+#
+# This file is part of Parabola.
+#
+# Parabola is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Parabola is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Parabola. If not, see <http://www.gnu.org/licenses/>.
+
+# create_signature() is taken from pacman:makepkg, which is GPLv2+,
+# so we take the '+' to combine it with our GPLv3+.
+
+. libremessages
+. "$(librelib conf.sh)"
+
+dryrun=""
+upload_only=false
+readonly rsync_flags=(
+ --no-group
+ --no-perms
+ --copy-links
+ --hard-links
+ --partial
+ --human-readable
+ --progress
+ -e ssh
+)
+
+# Functions ####################################################################
+
+list0_files() {
+ find -L "${WORKDIR}/staging" -type f -not -name '*.lock' \
+ -exec realpath -z --relative-to="${WORKDIR}/staging" {} +
+}
+
+# This function is taken almost verbatim from makepkg
+create_signature() {
+ local ret=0
+ local filename="$1"
+ msg "Signing package..."
+
+ local SIGNWITHKEY=()
+ if [[ -n $GPGKEY ]]; then
+ SIGNWITHKEY=(-u "${GPGKEY}")
+ fi
+ # The signature will be generated directly in ascii-friendly format
+ gpg --detach-sign --use-agent "${SIGNWITHKEY[@]}" "$filename" || ret=$?
+
+
+ if (( ! ret )); then
+ msg2 "Created signature file %s." "$filename.sig"
+ else
+ error "Failed to sign package file."
+ return $ret
+ fi
+}
+
+sign_packages() {
+ IFS=$'\n'
+ local files=($(find "${WORKDIR}/staging/" \
+ \( -type d -name "${ABSLIBREDEST##*/}" \) -prune \
+ -o \( -type f -not -iname '*.sig' \) -print))
+ local file
+ for file in "${files[@]}"; do
+ if [[ -f "${file}.sig" ]]; then
+ msg2 "File signature found, verifying..."
+
+ # Verify that the signature is correct, else remove for re-signing
+ if ! gpg --quiet --verify "${file}.sig" >/dev/null 2>&1; then
+ error "Failed! Re-signing..."
+ rm -f "${file}.sig"
+ fi
+ fi
+
+ if ! [[ -f "${file}.sig" ]]; then
+ create_signature "$file" || return 2
+ fi
+ done
+}
+
+# Clean everything if not in dry-run mode
+clean_files() {
+ local file_list=$1
+
+ local rmcmd=(rm -fv)
+ if [[ -n "${dryrun}" ]]; then
+ rmcmd=(printf "$(_ "removed '%s' (dry-run)")\n")
+ fi
+
+ msg "Removing files from local staging directory"
+ cd "${WORKDIR}/staging" && xargs -0r -a "$file_list" "${rmcmd[@]}"
+ cd "${WORKDIR}/staging" && find . -mindepth 1 -type d -empty \
+ -exec rmdir -p {} + 2>/dev/null
+}
+
+################################################################################
+
+usage() {
+ print "Usage: %s [OPTIONS]" "${0##*/}"
+ echo
+ prose 'This script uploads packages on $WORKDIR/staging
+ to the Parabola server.'
+ echo
+ print "Options:"
+ flag '-c' 'Clean; delete packages in $WORKDIR/staging'
+ flag '-l' "List; list packages but not upload them"
+ flag '-u' "Upload-only; do not run db-update on the server"
+
+ flag '-n' "Dry-run; don't actually do anything"
+ flag '-h' "Show this message"
+}
+
+main() {
+ if [[ -w / ]]; then
+ error "This program should be run as regular user"
+ return 1
+ fi
+
+ # Parse options
+ local mode="release_packages"
+ while getopts 'clunh' arg; do
+ case $arg in
+ c) mode=clean ;;
+ l) mode=pretty_print_packages ;;
+ u) upload_only=true ;;
+ n) dryrun="--dry-run" ;;
+ h) mode=usage ;;
+ *) usage >&2; return 1 ;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+ if [[ $# != 0 ]]; then
+ usage >&2
+ return 1
+ fi
+
+ if [[ $mode == usage ]]; then
+ usage
+ return 0
+ fi
+
+ load_files makepkg
+ check_vars makepkg GPGKEY
+ load_files libretools
+ check_vars libretools WORKDIR REPODEST ABSLIBREDEST || return 1
+ REPODEST+='/staging/'
+ # The following settings are actually optional
+ #check_vars libretools HOOKPRERELEASE HOOKPOSTRELEASE || return 1
+
+ "$mode"
+}
+
+# The different modes (sans 'usage') ###########################################
+
+pretty_print_packages() {
+ find "$WORKDIR/staging/" -mindepth 1 -maxdepth 1 -type d -not -empty | sort |
+ while read -r path; do
+ msg2 "${path##*/}"
+ cd "$path"
+ find -L . -type f -not -name '*.lock' | sed 's|^\./| |' | sort
+ done
+}
+
+clean() {
+ lock 8 "${WORKDIR}/staging.lock" \
+ 'Waiting for an exclusive lock on the staging directory'
+
+ local file_list="$(mktemp -t ${0##*/}.XXXXXXXXXX)"
+ trap "$(printf 'rm -f -- %q' "$file_list")" EXIT
+ list0_files > "$file_list"
+
+ lock_close 8
+
+ clean_files "$file_list"
+}
+
+release_packages() {
+ if [[ -n $HOOKPRERELEASE ]]; then
+ msg "Running HOOKPRERELEASE..."
+ plain '%s' "${HOOKPRERELEASE}"
+ bash -c "${HOOKPRERELEASE}"
+ fi
+
+ lock 8 "${WORKDIR}/staging.lock" \
+ 'Waiting for an exclusive lock on the staging directory'
+
+ sign_packages || return 1
+
+ # Make the permissions of the packages 644 otherwise the user will get access
+ # denied error when they try to download (rsync --no-perms doesn't seem to
+ # work).
+ find "${WORKDIR}/staging" -type f -exec chmod 644 {} +
+ find "${WORKDIR}/staging" -type d -exec chmod 755 {} +
+
+ local file_list="$(mktemp -t ${0##*/}.XXXXXXXXXX)"
+ trap "$(printf 'rm -f -- %q' "$file_list")" EXIT
+ list0_files > "$file_list"
+
+ lock_close 8
+
+ msg "%s to upload" "$(cd "${WORKDIR}/staging" && du -hc --files0-from="$file_list" | sed -n '$s/\t.*//p')"
+ msg "Uploading packages..."
+ xargs -0r -a "$file_list" dirname -z | ssh "${REPODEST%%:*}" "$(printf 'mkdir -p -- %q && cd %q && xargs -0r mkdir -pv --' "${REPODEST#*:}"{,})"
+ if ! rsync ${dryrun} "${rsync_flags[@]}" \
+ -0 --files-from="$file_list" \
+ "${WORKDIR}/staging" \
+ "${REPODEST}/"
+ then
+ error "Sync failed, try again"
+ return 1
+ fi
+
+ clean_files "$file_list"
+
+ if $upload_only; then
+ return 0
+ fi
+
+ msg "Running db-update on repos"
+ ssh "${REPODEST%%:*}" "$(printf 'STAGING=%q dbscripts/db-update' "${REPODEST#*:}")"
+
+ if [[ -n $HOOKPOSTRELEASE ]]; then
+ msg "Running HOOKPOSTRELEASE..."
+ plain '%s' "${HOOKPOSTRELEASE}"
+ bash -c "${HOOKPOSTRELEASE}"
+ fi
+
+ return 0
+}
+
+main "$@"