summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbill-auger <mr.j.spam.me@gmail.com>2023-12-24 03:47:46 -0500
committerbill-auger <mr.j.spam.me@gmail.com>2024-03-28 23:13:28 -0400
commit8f1839b025e1e12d6b104b02ad8a445003c460dc (patch)
tree793e2dc8ca19a3504e64f792cf66f94d0a5f9b22
parent2478cf7b101ec6769b45b8372c2e7aba8dd8b1d8 (diff)
refactor librerelease
-rw-r--r--po/es/libretools.po2
-rwxr-xr-xsrc/abslibre-tools/librerelease306
-rw-r--r--src/lib/notifications.sh4
-rw-r--r--src/libretools.conf37
4 files changed, 191 insertions, 158 deletions
diff --git a/po/es/libretools.po b/po/es/libretools.po
index fbd4122..880e915 100644
--- a/po/es/libretools.po
+++ b/po/es/libretools.po
@@ -341,7 +341,7 @@ msgid "Dry-run; don't actually do anything"
msgstr "Dry-run; no hace nada en realidad"
#: src/abslibre-tools/librerelease:139
-msgid "This program should be run as regular user"
+msgid "This program should be run as unprivileged user"
msgstr "Este programa debiera ser ejecutado como usuario normal"
#: src/abslibre-tools/librerelease:201
diff --git a/src/abslibre-tools/librerelease b/src/abslibre-tools/librerelease
index 70a20b0..24e163d 100755
--- a/src/abslibre-tools/librerelease
+++ b/src/abslibre-tools/librerelease
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
-# Librerelease
-# Uploads packages and releases them
+# librerelease - uploads packages to the repo server and publishes 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>
@@ -11,13 +11,13 @@
# 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>
+# 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+
+# SPDX-License-Identifier: GPL-3.0-or-later
#
# This file is part of Parabola Libretools.
#
@@ -37,17 +37,16 @@
# create_signature() is taken from pacman:makepkg, which is GPLv2+,
# so we take the '+' to combine it with our GPLv3+.
+
set -euE
-source "$(librelib conf )"
-source "$(librelib messages )"
-source "$(librelib notifications)"
+source "$(librelib conf )" # LIBREUSER, load_conf()
+source "$(librelib messages )" # setup_traps(), msg(), msg2() error(), print(), prose(), flag()
+source "$(librelib notifications)" # notify_release()
-setup_traps
-dryrun=""
-upload_only=false
-readonly rsync_flags=(
+declare -ri STAGING_LOCK=8
+declare -ra RSYNC_FLAGS=(
--no-group
--no-perms
--copy-links
@@ -56,7 +55,6 @@ readonly rsync_flags=(
--human-readable
--progress
)
-
DRY_RUN='' # main()
UPLOAD_ONLY='' # main()
TIER0_HOST='' # main()
@@ -67,16 +65,24 @@ SSH_CMD='' # main()
RSYNC_DEST='' # main()
-# Functions ####################################################################
+## helpers ##
+
+lock_staging() {
+ lock $STAGING_LOCK "${WORKDIR}/staging.lock" \
+ "Waiting for an exclusive lock on the staging directory ...."
+}
+
+unlock_staging() {
+ lock_close $STAGING_LOCK
+}
list0_files() {
find -L "${WORKDIR}/staging" -type f -not -name '*.lock' \
- -exec realpath -z --relative-to="${WORKDIR}/staging" {} +
+ -exec realpath -z --relative-to="${WORKDIR}/staging" {} +
}
# This function is taken almost verbatim from makepkg
create_signature() {
- local ret=$EXIT_SUCCESS
local filename="$1"
msg "Signing package..."
@@ -85,14 +91,13 @@ create_signature() {
SIGNWITHKEY=(-u "${GPGKEY}")
fi
- gpg --detach-sign --use-agent "${SIGNWITHKEY[@]}" --no-armor "$filename" &>/dev/null || ret=$EXIT_FAILURE
-
-
- if (( ! ret )); then
+ if gpg --detach-sign --use-agent "${SIGNWITHKEY[@]}" \
+ --no-armor "$filename" &>/dev/null ; then
msg2 "Created signature file %s." "$filename.sig"
+ return $EXIT_SUCCESS
else
error "Failed to sign package file."
- return $ret
+ return $EXIT_FAILURE
fi
}
@@ -120,20 +125,23 @@ sign_packages() {
# Clean everything if not in dry-run mode
clean_files() (
local file_list=$1
+ local rmcmd
- local rmcmd=(rm -fv)
- if [[ -n "${dryrun}" ]]; then
- rmcmd=(printf "$(_ "removed '%s' (dry-run)")\n")
+ if [[ -z "$DRY_RUN" ]]; then
+ rmcmd=( rm -fv )
+ else
+ rmcmd=( printf "$(_ "removed '%s' (dry-run)")\n" )
fi
msg "Removing files from local staging directory"
cd "${WORKDIR}/staging"
xargs -0r -a "$file_list" "${rmcmd[@]}"
find . -depth -mindepth 1 -type d \
- -exec rmdir --ignore-fail-on-non-empty -- '{}' +
+ -exec rmdir --ignore-fail-on-non-empty -- '{}' +
)
-################################################################################
+
+## The different modes ##
usage() {
print "Usage: %s [OPTIONS]" "${0##*/}"
@@ -154,82 +162,14 @@ usage() {
\$XDG_CONFIG_HOME/libretools/libretools.conf
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 $EXIT_NOPERMISSION
- 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 $EXIT_INVALIDARGUMENT ;;
- esac
- done
- shift $((OPTIND - 1))
- if [[ $# != 0 ]]; then
- usage >&2
- return $EXIT_INVALIDARGUMENT
- fi
-
- if [[ $mode == usage ]]; then
- usage
- return $EXIT_SUCCESS
- fi
-
- # source makepkg and libretools configuration files
- # the specified config vars will be used in this script, and so are mandatory
- # optional config vars used in this script, if specified in libretools.conf:
- # TIER0_LOGIN, TIER0_PORT, TIER0_STAGING, HOOKPRERELEASE, HOOKPOSTRELEASE
- if ! load_conf makepkg.conf GPGKEY; then
- error '$GPGKEY is not configured.'
- return $EXIT_NOTCONFIGURED
- elif ! load_conf libretools.conf WORKDIR TIER0_HOST DBSCRIPTS_CONFIG; then
- config_error_msg WORKDIR TIER0_HOST DBSCRIPTS_CONFIG
- return $EXIT_NOTCONFIGURED
- fi
-
- # validate/sanitize tier-0 repo URL components
- if [[ -n ${TIER0_HOST:-} ]]; then
- # normalize or reject tilde operator in staging path
- if [[ "$TIER0_STAGING" == '/~/'* ]]; then
- TIER0_STAGING=${TIER0_STAGING#'/~/'}
- elif [[ "$TIER0_STAGING" == '/~'* ]]; then
- error "Unfortunately, tilde expansion ('~' home directory) is not supported in libretools.conf::TIER0_STAGING"
- return $EXIT_NOTCONFIGURED
- fi
- else
- config_error_msg TIER0_HOST ; return $EXIT_NOTCONFIGURED ;
- fi
-
- # construct the SSH and rsync destination parameters
- readonly TIER0_HOST
- readonly TIER0_STAGING=${TIER0_STAGING:-/home/${TIER0_LOGIN:-$LIBREUSER}/staging}
- readonly TIER0_LOGIN=${TIER0_LOGIN:+${TIER0_LOGIN}@}
- readonly TIER0_PORT=${TIER0_PORT:+-p $TIER0_PORT}
- readonly SSH_CMD=( ssh ${TIER0_PORT} ${TIER0_LOGIN}${TIER0_HOST} )
- readonly RSYNC_DEST=${TIER0_LOGIN}${TIER0_HOST}:${TIER0_STAGING%/}/
-
- "$mode"
+ flag '-c' "Clean Local: delete packages in local staging directory"
+ flag '-h' "Help: Show this message"
+ flag '-l' "List: list packages but not upload them"
+ flag '-n' "Dry-run: don't actually do anything"
+ flag '-u' "Upload-only: do not run db-update on the server"
}
-# The different modes (sans 'usage') ###########################################
-
-pretty_print_packages() {
+list() {
find "$WORKDIR/staging/" -mindepth 1 -maxdepth 1 -type d -not -empty | sort |
while read -r path; do
msg2 "${path##*/}"
@@ -239,30 +179,34 @@ pretty_print_packages() {
}
clean() {
- lock 8 "${WORKDIR}/staging.lock" \
- 'Waiting for an exclusive lock on the staging directory'
+ lock_staging
local file_list
file_list="$(mktemp -t "${0##*/}.XXXXXXXXXX")"
trap "rm -f -- ${file_list@Q}" EXIT
list0_files > "$file_list"
- lock_close 8
+ unlock_staging
clean_files "$file_list"
}
-release_packages() {
- local tier0_port="${REPODEST_port:+-p "$REPODEST_port"}"
- local tier0_host="${REPODEST_userhost}"
- local ssh_cmd=( ssh ${tier0_port} ${tier0_host} ) # eg: ssh -p 1863 autobuilder@repo.parabola.nu STAGING='staging/' DBSCRIPTS_CONFIG='/etc/dbscripts/config.local.parabola' db-update
- local dbupdate_cmd="STAGING=${REPODEST_path@Q} DBSCRIPTS_CONFIG=${DBSCRIPTS_CONFIG@Q} db-update"
+release() {
+ local file_list="$( mktemp -t ${0##*/}_lst.XXXXXXXXXX)"
+ local dbupdate_log="$(mktemp -t ${0##*/}_log.XXXXXXXXXX)"
+ local mkdir_cmd="mkdir -p -- ${TIER0_STAGING@Q} && cd ${TIER0_STAGING@Q} && xargs -0r mkdir -pv --"
+ local dbupdate_cmd="STAGING=${TIER0_STAGING@Q} DBSCRIPTS_CONFIG=${DBSCRIPTS_CONFIG@Q} db-update"
+ local upload_size
- # verify connection and login
- if ! ${ssh_cmd[0]} -fN ${ssh_cmd[*]:1}; then
- error "Connection or login failed."
- return $EXIT_FAILURE
- fi
+ trap "rm -f -- ${file_list@Q} ${dbupdate_log@Q}" INT RETURN TERM
+
+ lock_staging
+
+ # verify connection and login
+ if ! ${SSH_CMD[0]} -fN ${SSH_CMD[*]:1}; then
+ error "Connection or login failed."
+ return $EXIT_FAILURE
+ fi
## prepare ##
@@ -275,31 +219,29 @@ release_packages() {
)
fi
- lock 8 "${WORKDIR}/staging.lock" \
- 'Waiting for an exclusive lock on the staging directory'
-
- sign_packages || return
+ sign_packages || return $EXIT_FAILURE
- # 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).
+ # collect staged files and set permissions for repository-bound files
+ list0_files > "$file_list"
+ upload_size="$(cd "${WORKDIR}/staging" && du -hc --files0-from="$file_list" | sed -n '$s/\t.*//p')"
find "${WORKDIR}/staging" -type f -exec chmod 644 {} +
find "${WORKDIR}/staging" -type d -exec chmod 755 {} +
- local file_list="$(mktemp -t ${0##*/}.XXXXXXXXXX)"
- trap "rm -f -- ${file_list@Q}" EXIT
- list0_files > "$file_list"
+ unlock_staging
- lock_close 8
+ # prepare remote staging directory tree
+ msg "%s to upload" "$upload_size"
+ xargs -0r -a "$file_list" dirname -z | ${SSH_CMD[*]} "$mkdir_cmd"
+
+
+ ## upload ##
- 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_port:+-p "$REPODEST_port"} "${REPODEST_userhost}" "mkdir -p -- ${REPODEST_path@Q} && cd ${REPODEST_path@Q} && xargs -0r mkdir -pv --"
- if ! rsync ${dryrun} "${rsync_flags[@]}" \
- -e "ssh ${REPODEST_port:+-p $REPODEST_port}" \
- -0 --files-from="$file_list" \
- "${WORKDIR}/staging" \
- "$REPODEST_userhost:$REPODEST_path/"
+ if ! rsync ${DRY_RUN} "${RSYNC_FLAGS[@]}" \
+ -e "ssh $SSH_PORT" \
+ -0 --files-from="$file_list" \
+ "${WORKDIR}/staging" \
+ "$RSYNC_DEST"
then
error "Sync failed, try again"
return $EXIT_FAILURE
@@ -307,32 +249,104 @@ release_packages() {
clean_files "$file_list"
- if $upload_only; then
+ if $UPLOAD_ONLY; then
return $EXIT_SUCCESS
fi
## publish ##
- msg "Running db-update on repos"
- ${ssh_cmd[*]} "${dbupdate_cmd}"
+ msg "Running db-update on repos"
+ if ${SSH_CMD[*]} "${dbupdate_cmd}"; then # eg: ssh -p 1863 autobuilder@repo.parabola.nu STAGING='staging/' DBSCRIPTS_CONFIG='/etc/dbscripts/config.local.parabola' db-update
+ if [[ -n $HOOKPOSTRELEASE ]]; then
+ msg "Running HOOKPOSTRELEASE..."
+ (
+ PS4=" \\[$BOLD\\]\$\\[$ALL_OFF\\] "
+ eval -- "set -x; $HOOKPOSTRELEASE"
+ )
+ fi
+
+ # notify pbot of the excellent work that we have done today
+ notify_release ${SSH_CMD[*]} < $file_list
- if [[ -n $HOOKPOSTRELEASE ]]; then
- msg "Running HOOKPOSTRELEASE..."
- (
- PS4=" \\[$BOLD\\]\$\\[$ALL_OFF\\] "
- eval -- "set -x; $HOOKPOSTRELEASE"
- )
+ return $EXIT_SUCCESS
+ else
+ return $EXIT_FAILURE
fi
+}
- ## notify pbot of the excellent work we have done ##
+## main entry ##
- notify_pbot ${ssh_cmd[*]} < $file_list
+main() {
+ # Parse CLI options
+ local mode=release # publish packages to public repo (default)
+ UPLOAD_ONLY=false # upload and publish
+ while getopts 'chlnu' arg; do
+ case $arg in
+ c) mode=clean ;; # empties local staging area
+ h) mode=usage ;; # print 'Usage' message
+ l) mode=list ;; # pretty-print locally-staged packages
+ n) DRY_RUN='--dry-run' ;; # only show what would be done
+ u) UPLOAD_ONLY=true ;; # upload, but do not publish
+ *) usage >&2 ; return $EXIT_INVALIDARGUMENT ;;
+ esac
+ done
+ shift $(( OPTIND - 1 ))
+ if [[ -w / ]]; then
+ error "This program should be run as unprivileged user"
+ return $EXIT_NOPERMISSION
+ elif (( $# )); then
+ usage >&2
+ return $EXIT_INVALIDARGUMENT
+ elif [[ $mode == usage ]]; then
+ usage
+ return $EXIT_SUCCESS
+ fi
+ # source makepkg and libretools configuration files
+ # the specified config vars will be used in this script, and so are mandatory
+ # optional config vars used in this script, if specified in libretools.conf:
+ # TIER0_LOGIN, TIER0_PORT, TIER0_STAGING, HOOKPRERELEASE, HOOKPOSTRELEASE
+ if ! load_conf makepkg.conf GPGKEY; then
+ error "The %s config variable is misconfigured." \$GPGKEY
+ return $EXIT_NOTCONFIGURED
+ elif ! load_conf libretools.conf WORKDIR TIER0_HOST DBSCRIPTS_CONFIG; then
+ for var in WORKDIR TIER0_HOST DBSCRIPTS_CONFIG; do
+ [[ -n ${!var} ]] || error "The $%s config variable is misconfigured." \$$var
+ done
+ prose "The format of %s variables may have changed.
+ Merge the %s file, if one is present; and adapt any custom %s to it." \
+ libretools.conf /etc/libretools.conf.pacnew ~/.config/libretools/libretools.conf
+ return $EXIT_NOTCONFIGURED
+ fi
+
+ # validate/sanitize tier-0 repo URL components
+ if [[ "$TIER0_STAGING" == '/~/'* ]]; then
+ TIER0_STAGING=${TIER0_STAGING#'/~/'}
+ elif [[ "$TIER0_STAGING" == '/~'* ]]; then
+ error "Unfortunately, tilde expansion ('~' home directory) is not supported in libretools.conf::TIER0_STAGING"
+ return $EXIT_NOTCONFIGURED
+ fi
- return $EXIT_SUCCESS
+ # finalize state
+ readonly DRY_RUN
+ readonly UPLOAD_ONLY
+
+ # construct the SSH and rsync destination parameters
+ readonly TIER0_LOGIN
+ readonly TIER0_HOST
+ readonly TIER0_PORT
+ readonly TIER0_STAGING=${TIER0_STAGING:-/home/${TIER0_LOGIN:-$LIBREUSER}/staging}
+ readonly SSH_URL=${TIER0_LOGIN:+${TIER0_LOGIN}@}${TIER0_HOST}
+ readonly SSH_PORT=${TIER0_PORT:+-p $TIER0_PORT}
+ readonly SSH_CMD=( ssh ${SSH_PORT} ${SSH_URL} )
+ readonly RSYNC_DEST=${SSH_URL}:${TIER0_STAGING%/}/
+
+ # do the requested business
+ $mode
}
+setup_traps
main "$@"
diff --git a/src/lib/notifications.sh b/src/lib/notifications.sh
index 2aa0b0e..2457dbd 100644
--- a/src/lib/notifications.sh
+++ b/src/lib/notifications.sh
@@ -1,5 +1,5 @@
# process librerelease::$file_list via STDIN
-notify_pbot() # ( ssh_cmd*** ) file_list->STDIN
+notify_release() # ( ssh_cmd* ) file_list->STDIN
{
local ssh_cmd=( $* )
local repo_user=${REPOUSER:-${LIBREUSER:-somebody}}
@@ -22,7 +22,7 @@ notify_pbot() # ( ssh_cmd*** ) file_list->STDIN
local pbotsay_msg="$(printf "%s just published:" ${repo_user}) ${releases[@]}"
local pbotsay_cmd="which pbot-say &> /dev/null && pbot-say '${pbotsay_msg}'"
- if [[ ${ssh_cmd[0]} =~ ^ssh\ ]] && (( ${#releases[@]} )); then
+ if [[ ${ssh_cmd[0]} == ssh ]] && (( ${#releases[@]} )); then
msg2 "$(_ "Notifying pbot:")" ; print " ${pbotsay_msg}" ;
${ssh_cmd[*]} "${pbotsay_cmd}" &> /dev/null || :
fi
diff --git a/src/libretools.conf b/src/libretools.conf
index b99a347..3ed6fa6 100644
--- a/src/libretools.conf
+++ b/src/libretools.conf
@@ -1,27 +1,45 @@
#!/hint/bash
# shellcheck disable=2034
+# System-wide Libretools configuration
+#
+# Users may over-ride this file in ~$LIBREUSER/.config/libretools/libretools.conf.
+# This file may be copied verbatim and adapted, or the user config may simply
+# redefine only the variables desired to over-ride.
+#
+# NOTE: * $LIBREHOME and $LIBREUSER are set in /usr/lib/libretools/conf.sh,
+# implicitly, before /etc/libretools.conf and overrides are loaded
+# * $DISPLAY is set implicitly by the X-server
+
################################################################################
-# misc #
+# general #
################################################################################
-# The dir where you work on
+## The directory where you work on packages (large storage)
+# This will be the parent directory of abslibre/ and staging/.
+# You can keep your VCS work area tidy by assigning SRCDEST and LOGDEST
+# in makepkg.conf to a subdirectory of this $$WORKDIR.
+# If you do that, use absolute paths.
+# $WORKDIR and $LIBREHOME are not valid in makepkg.conf when running `makepkg`.
+# SRCDEST=/path/to/WORKDIR/sources
+# LOGDEST=/path/to/WORKDIR/logs
WORKDIR="${LIBREHOME:-}"/packages
+## ABSLibre
+## Used by: `createworkdir`
+ABSLIBRERECV=git://git.parabola.nu/abslibre/abslibre.git
+ABSLIBRESEND=ssh://git@git.parabola.nu:1863/~git/abslibre/abslibre.git
+
## Blacklist URL
+## Used by: `blacklist.sh`
BLACKLIST=https://git.parabola.nu/blacklist.git/plain/blacklist.txt
-## Diff tool (vimdiff, gvimdiff, meld, etc)
+## Diff tool
## Used by `aur`, `diff-unfree`
# shellcheck disable=2046
DIFFPROG=$(which $([ -z "${DISPLAY:-}" ]||echo kdiff3 meld gvimdiff) vimdiff colordiff diff 2>/dev/null|sed 's/\s.*//;1q')
-## ABSLibre
-## Used by: `createworkdir`
-ABSLIBRERECV=git://git.parabola.nu/abslibre/abslibre.git
-ABSLIBRESEND=ssh://git@git.parabola.nu:1863/~git/abslibre/abslibre.git
-
################################################################################
# librerelease #
@@ -85,4 +103,5 @@ TORUPATH=/var/lib/libretools/toru
# inverted order of precedence. Put testing repos first so dagpkg will find new
# PKGBUILDs first, for instance. `toru-path` uses reverse order to enforce repo
# precedence on the path cache (the last path added replaces the rest)
-REPOS=('core' 'libre' 'extra' 'community' 'libre-testing' 'social' 'sugar' 'pcr' 'java')
+REPOS=( pcr{,-testing} extra core libre{,-testing} nonsystemd{,-testing} nonprism{,-testing} )
+