diff options
Diffstat (limited to 'src/abslibre-tools')
-rw-r--r-- | src/abslibre-tools/Makefile | 4 | ||||
-rwxr-xr-x | src/abslibre-tools/createworkdir | 54 | ||||
-rw-r--r-- | src/abslibre-tools/createworkdir.md | 36 | ||||
-rwxr-xr-x | src/abslibre-tools/diff-unfree | 89 | ||||
-rwxr-xr-x | src/abslibre-tools/libreaddiff | 98 | ||||
-rwxr-xr-x | src/abslibre-tools/libredbdiff | 360 | ||||
-rwxr-xr-x | src/abslibre-tools/librerelease | 257 | ||||
-rwxr-xr-x | src/abslibre-tools/librestage | 154 |
8 files changed, 1052 insertions, 0 deletions
diff --git a/src/abslibre-tools/Makefile b/src/abslibre-tools/Makefile new file mode 100644 index 0000000..2903f4a --- /dev/null +++ b/src/abslibre-tools/Makefile @@ -0,0 +1,4 @@ +include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk +include $(topsrcdir)/automake.head.mk + +include $(topsrcdir)/automake.tail.mk diff --git a/src/abslibre-tools/createworkdir b/src/abslibre-tools/createworkdir new file mode 100755 index 0000000..5599de9 --- /dev/null +++ b/src/abslibre-tools/createworkdir @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# CreateWorkDir +# Creates a dir structure for working with Parabola packages + +# Copyright (C) 2010-2011 Nicolás Reynolds <fauno@parabola.nu> +# Copyright (C) 2011 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com> +# Copyright (C) 2013 Luke Shumaker <lukeshu@sbcglobal.net> +# +# 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/>. + +set -euE + +. libremessages +. "$(librelib conf.sh)" +load_files libretools +check_vars libretools WORKDIR ABSLIBRERECV ABSLIBRESEND # these are asked for by `xbs download` + +trap 'error "Aborting..."' EXIT + +msg "Creating WORKDIR at %s..." "$WORKDIR" +mkdir -p "$WORKDIR" + +msg "Creating staging directory in WORKDIR..." +mkdir -p "$WORKDIR/staging" + +cmd=(xbs -b abslibre download) +if ! "${cmd[@]}"; then + error "Could not clone ABSLibre" + plain "Try running this command:" + echo + printf '%q ' "${cmd[@]}" + echo + exit 1 +fi + +msg "Finished, your packaging directory tree looks like this now:" +ls --color=auto "${WORKDIR}"/* + +trap -- EXIT diff --git a/src/abslibre-tools/createworkdir.md b/src/abslibre-tools/createworkdir.md new file mode 100644 index 0000000..e50b00f --- /dev/null +++ b/src/abslibre-tools/createworkdir.md @@ -0,0 +1,36 @@ +# CreateWorkDir + +This script recreates a proper directory tree for packaging. Its aim is to help +you be organized with the work you do as a packager, and establish a certain +standard for packages' publication, so you don't have to lose much time with +them. Just package and upload! + +It will create a directory tree like this: + + $WORKDIR/ + ├── abslibre/ + │ ├── .git/ + │ ├── libre/<PKGBUILDS> + │ └── libre-testing/<PKGBUILDS> + └── staging/ + ├── libre/ + └── libre-testing/ + +*Related Variables* + - WORKDIR + +## staging/ + +This directory contains one directory for each repository, where the resulting +packages are in moved for syncing against the main repository on Parabola's +server. This directory is architecture independent. + +## abslibre/ + +This is the git repo for Parabola's PKGBUILDs. Here you can find the ABS tree +for our packages, and also where you'll have to put new ones for commit. + +(You'll need push access to Parabola's main server, but pulling is public.) + +*Related Variables* + - ABSLIBREGIT diff --git a/src/abslibre-tools/diff-unfree b/src/abslibre-tools/diff-unfree new file mode 100755 index 0000000..12c919f --- /dev/null +++ b/src/abslibre-tools/diff-unfree @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# This script will help you diff a *-libre PKGBUILD against the unfree one +# to check for updates. + +# Copyright (C) 2010-2011 Nicolás Reynolds <fauno@parabola.nu> +# Copyright (C) 2011 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com> +# +# 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/>. + +. libremessages +. "$(librelib conf.sh)" +load_files libretools +check_vars libretools DIFFPROG || exit 1 + +usage() { + print "Usage: %s [community|packages] [unfree-package] [repo]" "${0##*/}" + print "Usage: %s --help" "${0##*/}" + prose "Helps you diff build scripts from ABSLibre against (Unfree) ABS." + echo + prose "Package name and repo will we guessed if you don't specify them." +} + +main() { + if [[ "$1" == "--help" ]]; then + usage + exit 0 + fi + + local package_guess=${PWD##*/} + local repo=${1:-$(basename ${PWD%/*})} + local package=${2:-${package_guess%-libre}} + local trunk=${3:-trunk} + + svnrepo="packages" + case $repo in + community*) svnrepo="community";; + multilib*) svnrepo="community";; + *) :;; + esac + + if [[ ! -r PKGBUILD ]]; then + error "This is not a build dir." + exit 1 + fi + + + tmp_dir="$(mktemp --tmpdir -d ${package}.XXXXXX)" + if [[ ! -d "${tmp_dir}" ]]; then + error "Can't create temp dir" + exit 1 + fi + unfree_dir="${tmp_dir}/${svnrepo}/${package}/${trunk}" + + pushd "${tmp_dir}" &>/dev/null + + msg "Getting diff from %s..." "$repo/$package" + + svn checkout --depth=empty svn://svn.archlinux.org/$svnrepo &>/dev/null + + cd ${svnrepo} + svn update ${package} + + # Back to start dir + popd &>/dev/null + + msg "Diffing files" + + for _file in ${unfree_dir}/*; do + msg2 "%s" "$(basename "${_file}")" + ${DIFFPROG} "$PWD/$(basename "${_file}")" "${_file}" + done +} + +main "$@" diff --git a/src/abslibre-tools/libreaddiff b/src/abslibre-tools/libreaddiff new file mode 100755 index 0000000..8698920 --- /dev/null +++ b/src/abslibre-tools/libreaddiff @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# -*- coding: utf-8 -*- + +# Copyright (C) 2011-2012 Michał Masłowski <mtjm@mtjm.eu> +# Copyright (C) 2012 Daniel Molina (lluvia) +# +# License: GNU GPLv3+ +# +# This program 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. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -e + +. libremessages +. "$(librelib conf.sh)" +load_files libretools +check_vars libretools WORKDIR + +for arg in "$@" ; do + case "$arg" in + -h|--h|--he|--hel|--help|-\?) + { + print 'Usage: %s repo [arch]' "${0##*/}" + echo + prose "This script outputs a diff of package names and versions + in repo between pacman's sync db and abslibre checkout." + } >&2 + exit 0 + ;; + esac +done + +# The repo to find missing packages in. +repo=$1 +# The arch to check in Arch repos, other will have all arches checked. +arch=${2:-mips64el} +# A Python tuple of repos which don't have arch=any packages. +archrepos='("core", "extra", "community")' + +diff -U0 \ + <( ( + cd /var/lib/pacman/sync + for f in $repo.db ; do + tar xOf $f | python -c 'import sys +arch = None +name = None +version = None +it = iter(sys.stdin) +try: + while True: + line = next(it) + if line == "%ARCH%\n": + arch = next(it) + if arch == "'"$arch"'\n" or "'$repo'" not in '"$archrepos"': + print("%s-%s" % (name.strip(), version.strip())) + if line == "%NAME%\n": + name = next(it) + if line == "%VERSION%\n": + version = next(it) +except StopIteration: + pass +' + done + ) | sort ) \ + <( ( + cd "${WORKDIR}/abslibre" + # Needed to not include pkgnames specific to other arches. + CARCH=$arch + for f in $repo/* ; do + load_PKGBUILD "$f/PKGBUILD" || continue + is_here=false + for arc in ${arch[@]} ; do + if [[ "$arc" == "any" ]] || [[ "$arc" == "$CARCH" ]] ; then + is_here=true + break + fi + done + if [[ "$is_here" == "true" ]] ; then + for name in "${pkgname[@]}" ; do + if [[ -z "$epoch" ]] ; then + echo $name-$pkgver-$pkgrel + else + echo $name-$epoch:$pkgver-$pkgrel + fi + done + fi + done + ) | sort ) | sed -rn 's/^[+-][^+-].+$/&/p' diff --git a/src/abslibre-tools/libredbdiff b/src/abslibre-tools/libredbdiff new file mode 100755 index 0000000..09c7ad1 --- /dev/null +++ b/src/abslibre-tools/libredbdiff @@ -0,0 +1,360 @@ +#!/usr/bin/env bash +name="Libredbdiff" + +# Copyright (C) 2014 Esteban Carnevale <alfplayer@mailoo.org> +# Copyright (C) 2014 Luke Shumaker <lukeshu@sbcglobal.net> +# +# License: GNU GPLv3+ +# +# This program 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. +# +# This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + +baseconfpath="/etc/libredbdiff" +basedbpath="/var/lib/libredbdiff" + +conffile="$baseconfpath/pacman.conf.parabola" +conffilearch="$baseconfpath/pacman.conf.archlinux" + +dbpath="$basedbpath/pacman.parabola" +dbpatharch="$basedbpath/pacman.archlinux" + +mirrorlist="$baseconfpath/mirrorlist.parabola" +mirrorlistarch="$baseconfpath/mirrorlist.archlinux" + +mirror='http://repo.parabola.nu/$repo/os/$arch' +mirrorarch='http://mirrors.kernel.org/archlinux/$repo/os/$arch' + +repos="libre pcr libre-multilib nonprism" + +field_pkgname_parabola=30 +field_pkgname_arch=30 + + +. libremessages + +cmd="${0##*/}" + +arch_packages_tmp="/tmp/${cmd}.arch-packages" +parabola_packages_tmp="/tmp/${cmd}.parabola-packages" + +field_pkgname_total="$((${field_pkgname_parabola} + ${field_pkgname_arch}))" +printf_format="%s %-${field_pkgname_parabola}s%-${field_pkgname_arch}s %s | %s\n" +printf_format_noarch="%s %-${field_pkgname_total}s %s\n" + +downloadfile() { + local outfile=$1 + local url=$2 + local mesg=("${@:3}") + if [[ ! -e $outfile ]] ; then + msg "${mesg[@]}" + if wget -q "$url" -O "$outfile"; then + return 255 + else + die "Failed to download %q. Exiting." "$outfile" + fi + elif [[ $init ]]; then + warning "%q already exists. Skipping." "$outfile" + fi +} + +enablerepo() { + repo="$1" + conffile_arg="$2" + msg2 "Enabling repo %q in %q" "$repo" "${conffile_arg}" + sed -i "s/\#\[$repo\]/[$repo]/" "${conffile_arg}" + sed -i "\/\[$repo\]/,+1 s/#Include/Include/" "${conffile_arg}" +} + +createdir() { + local dir=$1 + if [[ ! -e $dir ]] ; then + msg "Creating directory %q" "$dir" + mkdir -- "$1" || die "Failed to create directory %q. Exiting." "$dir" + elif [[ $init ]]; then + warning "%q already exists. Skipping." "$dir" + fi +} + +setmirror() { + local distro="$1" + local mirror="$2" + local mirrorlist="$3" + if [[ $init ]] && [[ $mirror ]]; then + mirrorescaped="${mirror//./\\.}" + mirrorescaped="${mirrorescaped//\$/\\$}" + msg2 "Setting %s as the only enabled %s mirror." "${mirror}" "${distro}" + sed -i 's|^#\(Server = '"${mirrorescaped}"'\)$|\1|' "${mirrorlist}" + fi +} + +filenotfound() { + local file=$1 + if [[ ! -r $1 ]]; then + error "Could not read %q." "$file" + die "Nothing done. It may be necessary to run %q without \ +arguments as root to initialize %s." "$cmd" "$name" + fi +} + +initialize() { + createdir "$baseconfpath" + createdir "$basedbpath" + + downloadfile \ + "${conffile}" \ + "https://projects.parabola.nu/abslibre.git/plain/libre/pacman/pacman.conf.x86_64" \ + "Downloading Parabola %q" \ + pacman.conf + if [[ $? == 255 ]] ; then + msg2 "Setting DBPath in %q" "${conffile}" + sed -i "s|^#DBPath .*|DBPath = ${dbpath}|" "${conffile}" + enablerepo nonprism "${conffile}" + enablerepo pcr "${conffile}" + enablerepo libre-multilib "${conffile}" + enablerepo multilib "${conffile}" + fi + + downloadfile \ + "${conffilearch}" \ + "https://projects.archlinux.org/svntogit/packages.git/plain/pacman/trunk/pacman.conf.x86_64" \ + "Downloading Arch %q" \ + pacman.conf + if [[ $? == 255 ]] ; then + msg2 "Setting DBPath in %q" "${conffilearch}" + sed -i "s|^#DBPath .*|DBPath = ${dbpatharch}|" "${conffilearch}" + msg2 "Setting Arch mirrorlist file in %q" "${conffilearch}" + sed -i "s|/etc/pacman\.d/mirrorlist$|$baseconfpath/mirrorlist.archlinux|" \ + "${conffilearch}" + enablerepo multilib "${conffilearch}" + fi + + downloadfile \ + "${mirrorlist}" \ + "https://repo.parabola.nu/mirrorlist.txt" \ + "Downloading Parabola %q" \ + mirrorlist + if [[ $? == 255 ]] ; then + sed -i 's|^Server|#Server|' "${mirrorlist}" + setmirror "Parabola" "$mirror" "$mirrorlist" + fi + + downloadfile \ + "${mirrorlistarch}" \ + "https://projects.archlinux.org/svntogit/packages.git/plain/pacman-mirrorlist/trunk/mirrorlist" \ + "Downloading Arch %q" \ + mirrorlist + if [[ $? == 255 ]] ; then + setmirror "Arch" "$mirrorarch" "$mirrorlistarch" + fi +} + +repo_test() { + for repo in ${repos} ; do + if [[ $repo == $1 ]] ; then + found=1 + return 0 + fi + done + if [[ $found != 1 ]] ; then + die "The specified Parabola repo \"%s\" cannot be compared. It's not in the list of repos in the configuration variable \"repos\"." "$1" + fi +} + +compare_pkgs() { + local cmp + if [[ ${verarch[$pkgname]} ]] ; then + cmp=$(vercmp "${ver[$pkgname]}" "${verarch[$pkgname]}") + if [[ $cmp -lt 0 ]]; then + printf "${printf_format}" \ + '=' \ + "${pkgname}" \ + "" \ + "${ver[$pkgname]}" \ + "${verarch[$pkgname]}" + fi + elif [[ ${provides[$pkgname]} ]]; then + for provide in "${provides[$pkgname]}"; do + if [[ ${verarch["$provide"]} ]]; then + cmp=$(vercmp "${ver[$pkgname]}" "${verarch[$provide]}") + if [[ $cmp -lt 0 ]]; then + printf "${printf_format}" \ + 'p' \ + "${pkgname}" \ + "${provide}" \ + "${ver[$pkgname]}" \ + "${verarch[$provide]}" + fi + fi + done + else + printf "${printf_format_noarch}" \ + 'o' \ + "${pkgname}" \ + "${ver[$pkgname]}" + fi +} + +print_cmp() { + local repo="$1" + awk -F/ -v repo="$repo" \ + '$1 == repo {print $2}' \ + ${parabola_packages_tmp} | \ + while read -a line ; do + ver["${line[0]}"]="${line[1]}" + provides[${line[0]}]="${line[@]:2}" + pkgname=${line[0]} + compare_pkgs + done +} + +usage() { + print "Usage: %q [-n|-h]" "$cmd" + print 'Show packages that need to be updated from Arch repositories.' + echo + prose "Compares packages in Parabola repositories. Packages from + all configured Parabola repositories are compared. A Parabola + repository name can be specified as argument to compare only + packages in that repository." + echo + prose "The default mode of operation is to download/update all necessary + files for comparison, but not compare them. Specify the \`-n\` + flag to not download anything, but to compare already downloaded + files." + echo + print 'Options:' + flag '-n' "Don't update anything, just compare already downloaded files." + flag '-h' 'Show this message' + echo + print "Output format:" + print "type_character parabola_pkgname (arch_pkgname) parabola_pkgver - (arch_pkgver)" + echo + print "Type characters:" + flag '=' "Arch package with the same pkgname and greater pkgver was found" + flag 'p' "Arch package with pkgname equal to a provide and greater + pkgver was found In this case arch_pkgname is a provide of + parabola_pkgname" + flag 'o' "No Arch package with the same pkgname or with pkgname equal to + a provide was found" +} + +main() { + local UPDATE=1 + local arg + local repo_arg + + for arg in "$@"; do + case "$arg" in + -n|--noupdate) + UPDATE=0 + ;; + -h|--help) + usage + return 0 + ;; + *) + repo_test "$arg" + repo_arg="$arg" + break + ;; + esac + done + + if (( $UPDATE )) ; then + if [[ $EUID != 0 ]]; then + die "To initialize %s or update %s pacman databases, %s must be run as root (without arguments). Nothing done." \ + "$name" \ + "$name" \ + "$cmd" + fi + + if ! [[ -e "${conffile}" && \ + -e "${conffilearch}" && \ + -e "${mirrorlist}" && \ + -e "${mirrorlist}" ]]; then + warning "At least one %s configuration file is missing." \ + "${name}" + msg "Downloading and preparing missing configuration files." + init=1 + fi + + createdir "$baseconfpath" + createdir "$basedbpath" + + initialize + + if ! [[ -d "$dbpath" && \ + -d "$dbpatharch" ]]; then + warning "At least one %s pacman DB directory is missing. Synchronizing %s DB files." \ + "${name}" "${name}" + fi + + createdir "$dbpath" + msg "Synchronizing %s pacman databases for Parabola" "$name" + pacman --config "${conffile}" -Sy || + die "Failed to synchronize pacman database for Parabola. Exiting." + + createdir "$dbpatharch" + msg "Synchronizing %s pacman databases for Arch" "$name" + pacman --config "${conffilearch}" -b "${dbpatharch}" -Sy || + die "Failed to synchronize pacman database for Arch. Exiting." + + msg "%s pacman databases are updated. %s is ready. Run %q -n to print results." \ + "$name" "$name" "$cmd" + return 0 + else + filenotfound "${dbpath}" + filenotfound "${dbpatharch}" + filenotfound "${conffile}" + filenotfound "${conffilearch}" + filenotfound "${mirrorlist}" + filenotfound "${mirrorlistarch}" + + unset provides ver verarch + declare -gA provides ver verarch + + if ! [[ -d "$dbpath" && \ + -d "$dbpatharch" ]]; then + die "At least one %s pacman DB directory is missing. To update %s pacman databases, %s must be run as root. Nothing done." \ + "$name" \ + "$name" \ + "$cmd" + fi + + pacman --config "${conffilearch}" -Ss | \ + grep -v '^ ' | \ + awk -F/ '{print $2}' \ + > ${arch_packages_tmp} || \ + die "pacman command to get Arch package data has failed. Exiting." + chmod 777 ${arch_packages_tmp} + + while read -a line; do + verarch["${line[0]}"]="${line[1]}" + done < ${arch_packages_tmp} + + expac --config "${conffile}" -S '%r/%n %v %S' \ + > ${parabola_packages_tmp} || \ + die "expac command to get Parabola package data has failed. Exiting." + chmod 777 ${parabola_packages_tmp} + + if [[ ${repo_arg} ]] ; then + print_cmp "${repo_arg}" + else + for repo in ${repos} ; do + echo "[$repo]" + print_cmp "$repo" + done + fi + fi +} + +main "$@" 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 "$@" diff --git a/src/abslibre-tools/librestage b/src/abslibre-tools/librestage new file mode 100755 index 0000000..39523ac --- /dev/null +++ b/src/abslibre-tools/librestage @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +# LibreStage +# Prepares packages for upload + +# Copyright (C) 2010-2012 Nicolás Reynolds <fauno@parabola.nu> +# Copyright (C) 2011 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com> +# Copyright (C) 2013-2014 Luke Shumaker <lukeshu@sbcglobal.net> +# +# 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/>. + +. libremessages +. "$(librelib conf.sh)" + +usage() { + print "Usage: %s [REPO]" "${0##*/}" + print "Stages the package(s) build by ./PKGBUILD for upload." + echo + prose "The package(s) are staged for the named repository, or the name + of the parent directory if a repository is not named." +} + +main() { + if [[ -w / ]]; then + error "This program should be run as a regular user" + return 1 + fi + + # Parse options, set up + while getopts 'h' arg; do + case $arg in + h) usage; return 0;; + *) usage >&2; return 1;; + esac + done + local repo= + case $# in + 0) repo="$(basename "$(dirname "$PWD")")";; + 1) repo=$1;; + *) usage >&2; return 1;; + esac + + if ! [[ -e ./PKGBUILD ]]; then + error "PKGBUILD not found" + return 1 + fi + + if ! xbs -b abslibre status; then + error "There are uncommitted changes in the current directory" + return 1 + fi + + # Load configuration + load_files libretools + # ABSLIBREDEST is used by xbs release-client + check_vars libretools WORKDIR ARCHES ABSLIBREDEST || return 1 + load_files makepkg # for PKGDEST and SRCDEST, which are optional + load_files librefetch # for MIRRORS, which is optional + + # Load the PKGBUILD + load_PKGBUILD + + # Now for the main routine. + local staged=false + slock 8 "${WORKDIR}/staging.lock" \ + 'Waiting for a shared lock on the staging directory' + + # Look for makepkg output + local CARCH _pkgname pkgfile + for CARCH in "${ARCHES[@]}" any; do + for _pkgname in "${pkgname[@]}" "${pkgname[@]/%/-debug}"; do + if ! pkgfile=$(find_cached_package "$_pkgname" "$(get_full_version "$_pkgname")" "$CARCH"); then + continue + fi + + msg 'Found package: %s' "${pkgfile##*/}" + + # This little check is from devtools:commitpkg + if grep -q "packager = Unknown Packager" <(bsdtar -xOqf "$pkgfile" .PKGINFO); then + die "PACKAGER wes not set when building package" + fi + + xbs -b abslibre release-client "$repo" "$CARCH" + mkdir -p "${WORKDIR}/staging/${repo}" + if cp "$pkgfile" "${WORKDIR}/staging/${repo}/${pkgfile##*/}"; then + msg2 "%s staged on [%s]" "$_pkgname" "$repo" + staged=true + else + error "Can't put %s on [%s]" "$_pkgname" "$repo" + return 1 + fi + done + done + + # Look for librefetch output + local netfile mirror path + local srcurl srcname srcpath + for netfile in "${source[@]}"; do + for mirror in "${MIRRORS[@]}"; do + srcurl=${netfile#*::} + if [[ "$srcurl" == "$mirror"* ]]; then + if [[ $netfile = *::* ]]; then + srcname=${netfile%%::*} + else + srcname=${netfile##*/} + fi + + srcpath='' + for path in "./$srcname" "${SRCDEST:-.}/$srcname"; do + if [[ -f "$path" ]]; then + srcpath="$path" + break + fi + done + if [[ -n "$srcpath" ]]; then + msg "Found generated source file: %s" "$srcname" + local dest="${WORKDIR}/staging/other/${srcurl##"$mirror"}" + mkdir -p -- "${dest%/*}" + if cp "$srcpath" "$dest"; then + msg2 "%s staged on [%s]" "$srcname" other + staged=true + else + error "Can't put %s on [%s]" "$srcname" other + return 1 + fi + fi + break + fi + done + done + + if $staged ; then + return 0 + else + error "Nothing was staged" + return 1 + fi +} + +main "$@" |