diff --git a/.gitignore b/.gitignore index 77f1b42..0606f02 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ *.eggs *.egg-info dist -build eggs parts bin diff --git a/build-deb b/build-deb new file mode 100755 index 0000000..dec2ce7 --- /dev/null +++ b/build-deb @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# +# Debian/Ubuntu Packaging Scripts +# Copyright (C) 2002-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +# ====== Obtain package and version information ============================= +OVERRIDE_PACKAGE_DISTRIBUTION="$1" + +CHANGELOG_HEADER="`head -n1 debian/changelog`" + +# The package name, e.g. MyApplication +PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"` +# The package distribution, e.g. precise, raring, ... +PACKAGE_DISTRIBUTION=`echo ${CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"` +# The package's version, e.g. 1.2.3-1ubuntu1 +PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"` +# The package's output version, e.g. 1.2.3-1ubuntu +OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"` +# The package's Debian version, e.g. 1.2.3-1 +DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"` +# The package's upstream version, e.g. 1.2.3 +UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"` +# The package's plain upstream version, e.g. 1.2.3 (without e.g. ~svn) +PLAIN_VERSION=`echo ${UPSTREAM_VERSION} | sed -e "s/\([0-9\.]*\)[-+~].*$/\1/"` + + +echo -e "\x1b[34m######################################################################\x1b[0m" +echo -e "\x1b[34mCHANGELOG_HEADER: ${CHANGELOG_HEADER}\x1b[0m" +echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m" +echo -e "\x1b[34mPACKAGE_DISTRIBUTION: ${PACKAGE_DISTRIBUTION}\x1b[0m" +echo -e "\x1b[34mPACKAGE_VERSION ${PACKAGE_VERSION}\x1b[0m" +echo -e "\x1b[34mOUTPUT_VERSION: ${OUTPUT_VERSION}\x1b[0m" +echo -e "\x1b[34mDEBIAN_VERSION: ${DEBIAN_VERSION}\x1b[0m" +echo -e "\x1b[34mUPSTREAM_VERSION: ${UPSTREAM_VERSION}\x1b[0m" +echo -e "\x1b[34mPLAIN_VERSION: ${PLAIN_VERSION}\x1b[0m" +echo -e "\x1b[34m######################################################################\x1b[0m" + +if [ ! -e ./packaging.conf ] ; then + echo >&2 "ERROR: packaging.conf does not exist -> no configuration for the new package!" + exit 1 +fi +. ./packaging.conf + +if [ "${OVERRIDE_PACKAGE_DISTRIBUTION}" != "" ] ; then + PACKAGE_DISTRIBUTION="${OVERRIDE_PACKAGE_DISTRIBUTION}" + echo "" + echo -e "\x1b[34m**** Overriding PACKAGE_DISTRIBUTION: PACKAGE_DISTRIBUTION=${PACKAGE_DISTRIBUTION}! ****\x1b[0m" + echo "" +fi + + +# ====== Create source package ============================================== +sudo echo "" +./clean-deb +./make-deb ${PACKAGE_DISTRIBUTION} + +if [ "${ARCH}" == "" ] ; then + ARCH=`dpkg --print-architecture` +fi +if [ "${PACKAGE_DISTRIBUTION}" == "unstable" -o \ + "${PACKAGE_DISTRIBUTION}" == "testing" -o \ + "${PACKAGE_DISTRIBUTION}" == "stable" -o \ + "${PACKAGE_DISTRIBUTION}" == "oldstable" -o \ + "${PACKAGE_DISTRIBUTION}" == "default" ] ; then + if [ "${PACKAGE_DISTRIBUTION}" == "default" ] ; then + version=${PACKAGE_VERSION} + else + version=${DEBIAN_VERSION} + fi + changesFilesPattern="${PACKAGE}_${version}_${ARCH}*.changes" + dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1` +else + changesFilesPattern="${PACKAGE}_${OUTPUT_VERSION}~${PACKAGE_DISTRIBUTION}[0-9]_${ARCH}*.changes" + dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${PACKAGE_DISTRIBUTION}[0-9].dsc | tail -n1` +fi + + +# ====== Build binary package =============================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Building binary package ========================================\x1b[0m" +echo -e "" + +if [ ! -e "${dscFile}" ] ; then + echo >&2 "ERROR: Unable to find description file ${dscFile}!" + exit 1 +fi +sudo OS=${OS} DIST=${DIST} ARCH=${ARCH} pbuilder build ${dscFile} + + +# ====== Run lintian ======================================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Running lintian ================================================\x1b[0m" +echo -e "" + +changesFile=`find /var/cache/pbuilder/result/ -name "${changesFilesPattern}"` +if [ ! -e "${changesFile}" ] ; then + echo >&2 "ERROR: Unable to find changes file ${changesFile}!" + exit 1 +fi + +profile="ubuntu" +if [ "${PACKAGE_DISTRIBUTION}" == "unstable" -o \ + "${PACKAGE_DISTRIBUTION}" == "testing" -o \ + "${PACKAGE_DISTRIBUTION}" == "stable" -o \ + "${PACKAGE_DISTRIBUTION}" == "oldstable" ] ; then + profile="debian" +fi +echo "Calling: lintian -iIEv --pedantic --suppress-tags file-references-package-build-path --profile ${profile} ${changesFile}" +lintian -iIEv --pedantic --suppress-tags file-references-package-build-path --profile ${profile} ${changesFile} || true diff --git a/build-rpm b/build-rpm new file mode 100755 index 0000000..19ac7dc --- /dev/null +++ b/build-rpm @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# +# Packaging Scripts +# Copyright (C) 2017-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +# --------------------------------------------------------------------------- +# USAGE: +# ./make-rpm => Use current distribution and architecture +# ./make-rpm fedora-30-x86_64 => F30, amd64 +# ./make-rpm fedora-rawhide-i386 => F30, i386 +# ... +# --------------------------------------------------------------------------- + + +DISTRIBUTIONS=`\ +( \ +while [ x$1 != "x" ] ; do \ + echo $1 + shift +done \ +) | sort -u` +if [ "${DISTRIBUTIONS}" == "" ] ; then + release=`cat /etc/fedora-release | sed -e "s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g"` + arch=`uname -m` + + DISTRIBUTIONS="fedora-${release}-${arch}" +fi + +PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"` +PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"` + +echo -e "\x1b[34m###########################################\x1b[0m" +echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m" +echo -e "\x1b[34mPACKAGE_VERSION: ${PACKAGE_VERSION}\x1b[0m" +echo -e "\x1b[34m###########################################\x1b[0m" + + +# ====== Create source RPM ================================================== +./make-srpm + +PACKAGE_SRPM=`find $HOME/rpmbuild/SRPMS/ -name "${PACKAGE}-*-*.src.rpm"` +if [ ! -e "${PACKAGE_SRPM}" ] ; then + echo >&2 "ERROR: Cannot find SRPM ${PACKAGE}-*-*.src.rpm in $HOME/rpmbuild/SRPMS!" + exit 1 +fi + + +# ====== Build binary RPMs ================================================== +# Create binary RPMs +for DISTRIBUTION in ${DISTRIBUTIONS} ; do + echo -e "" + echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating binary RPM for ${DISTRIBUTION} ==========\x1b[0m" + echo -e "" + + # NOTE: DISTRIBUTION may point to another directory (e.g. "rawhide" instead of "30")! + if [ ! -e "/etc/mock/${DISTRIBUTION}.cfg" ] ; then + echo >&2 "ERROR: Cannot find /etc/mock/${DISTRIBUTION}.cfg!" + exit 1 + fi + + # Remove old files + find /var/lib/mock/${DISTRIBUTION}/result -name "${PACKAGE}-*.rpm" | xargs --no-run-if-empty rm -f + + # Build the binary RPM + # NOTE: using old chroot instead of container, to allow running it inside a container! + mock -r ${DISTRIBUTION} --isolation=simple --init + mock -r ${DISTRIBUTION} --isolation=simple --installdeps ${PACKAGE_SRPM} + mock -r ${DISTRIBUTION} --isolation=simple --install openssl pesign + mock -r ${DISTRIBUTION} --isolation=simple --no-clean --rebuild ${PACKAGE_SRPM} + + # Check whether files are at the right location + PACKAGE_RPMS=`find /var/lib/mock/${DISTRIBUTION}/result -name "${PACKAGE}-*-*.rpm" | grep -v "${PACKAGE}-*-*.src.rpm" || true` + if [ "${PACKAGE_RPMS}" == "" ] ; then + echo >&2 "ERROR: Cannot find RPMs!" + exit 1 + fi +done diff --git a/ci/ci-build b/ci/ci-build new file mode 100755 index 0000000..0e18d61 --- /dev/null +++ b/ci/ci-build @@ -0,0 +1,138 @@ +#!/usr/bin/env bash +# +# GitHub Actions Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + +DIRNAME=`dirname $0` +UNAME=`uname` +if [ "${UNAME}" == "Linux" ] ; then + DISTRIBUTION=`lsb_release -is` +else + DISTRIBUTION="Unknown" +fi + +if [ $# -lt 1 ] ; then + echo >&2 "Usage: $0 compile|package|... ..." + exit 1 +fi + + +# ###### Configure ########################################################## + +# ====== Configure with CMake =============================================== +if [ -e CMakeLists.txt ] ; then + cmake . + +# ====== Configure with autoconf/automake (via bootstrap script) ============ +elif [ -e configure.ac -o -e configure.in ] ; then + if [ -e autogen.sh ] ; then + ./autogen.sh + elif [ -e bootstrap ] ; then + ./bootstrap + ./configure + else + ./configure + fi +else + echo >&2 "WARNING: No build system detected. Trying to just call \"make\" ..." +fi + +if [ ${UNAME} == "Linux" ] ; then + cores=`getconf _NPROCESSORS_ONLN 2>/dev/null || true` + MAKEFLAGS="-j${cores}" +elif [ ${UNAME} == "FreeBSD" ] ; then + cores=`sysctl -a | grep 'hw.ncpu' | cut -d ':' -f2 | tr -d ' '` + MAKEFLAGS="-j${cores}" +else + MAKEFLAGS="" +fi + + +# ###### Perform builds ##################################################### +while [ $# -gt 0 ] ; do + TOOL="$1" + shift + + + # ====== Compile ========================================================= + if [ "${TOOL}" == "compile" ] ; then + MAKEFLAGS=${MAKEFLAGS} make # VERBOSE=1 + + +# # ====== Coverity Scan =================================================== +# elif [ "${TOOL}" == "coverity" ] ; then +# # ------ Build -------------------------------------------------------- +# cd coverity +# export PATH="coverity/$(ls -d cov*)/bin:$PATH" +# cd .. +# +# MAKEFLAGS=${MAKEFLAGS} cov-build --dir cov-int make +# tar czf coverity-results.tar.gz cov-int +# ls -l coverity-results.tar.gz +# +# # ------ Upload results ----------------------------------------------- +# if [ "${TRAVIS_BRANCH}" == "${COVERITY_SCAN_BRANCH}" ] ; then +# curl --form token=${COVERITY_SCAN_TOKEN} \ +# --form email=${COVERITY_SCAN_NOTIFICATION_EMAIL} \ +# --form file=@coverity-results.tar.gz \ +# --form version="master branch head" \ +# --form description="$(git log -1|head -1)" \ +# https://scan.coverity.com/builds?project=${COVERITY_PROJECT} +# CURL_RESULT=$? +# echo "curl returned ${CURL_RESULT}" +# if [ $CURL_RESULT -ne 0 ]; then +# echo >&2 "ERROR: Upload to Coverity Scan failed; curl returned ${CURL_RESULT}!" +# exit 1 +# fi +# else +# echo >&2 "###### NOTE: This branch \"${TRAVIS_BRANCH}\" is not the scan branch \"${COVERITY_SCAN_BRANCH}\"! Skipping upload! ######" +# fi + + + # ====== Package ======================================================= + elif [ "${TOOL}" == "package" ] ; then + if [ "${DISTRIBUTION}" == "Ubuntu" -o "${DISTRIBUTION}" == "Debian" ] ; then + OVERRIDE_SKIP_PACKAGE_SIGNING=1 ./build-deb ${DIST} + + # ====== Fedora ========================================================== + elif [ "${DISTRIBUTION}" == "Fedora" ] ; then + release=`cat /etc/fedora-release | sed -e "s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g" | sed -e "s/[^0-9]//g"` + if [ "${ARCH}" == "" ] ; then + arch=`uname -m | sed -e "s/[^0-9a-zA-Z_+-]//g"` + else + arch="${ARCH}" + fi + LD_PRELOAD=/usr/lib64/nosync/nosync.so OVERRIDE_SKIP_PACKAGE_SIGNING=1 ./build-rpm fedora-${release}-${arch} + + # ====== Unknown ========================================================= + else + echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!" + exit 1 + fi + + + # ====== Invalid setting ================================================= + else + echo >&2 "ERROR: Invalid setting of TOOL=${TOOL}!" + exit 1 + fi + +done diff --git a/ci/ci-install b/ci/ci-install new file mode 100755 index 0000000..8e92f65 --- /dev/null +++ b/ci/ci-install @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# +# GitHub Actions Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + +DIRNAME=`dirname $0` +UNAME=`uname` +if [ "${UNAME}" == "Linux" ] ; then + DISTRIBUTION=`lsb_release -is` +else + DISTRIBUTION="Unknown" +fi + + +# ###### Linux ############################################################## +if [ "${UNAME}" == "Linux" ] ; then + + # ====== Ubuntu ========================================================== + if [ "${DISTRIBUTION}" == "Ubuntu" ] ; then + DEBIAN_FRONTEND=noninteractive ${DIRNAME}/get-dependencies ubuntu --install + + # ====== Debian ========================================================== + elif [ "${DISTRIBUTION}" == "Debian" ] ; then + DEBIAN_FRONTEND=noninteractive ${DIRNAME}/get-dependencies debian --install + + # ====== Fedora ========================================================== + elif [ "${DISTRIBUTION}" == "Fedora" ] ; then + ${DIRNAME}/get-dependencies fedora --install + + # ====== Unknown ========================================================= + else + echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!" + exit 1 + fi + +# ###### FreeBSD ############################################################ +elif [ "${UNAME}" == "FreeBSD" ] ; then + + ${DIRNAME}/get-dependencies freebsd --install + +# ###### Unknown ############################################################ +else + + echo >&2 "ERROR: Unexpected system ${UNAME}!" + exit 1 + +fi diff --git a/ci/ci-setup b/ci/ci-setup new file mode 100755 index 0000000..4e0a963 --- /dev/null +++ b/ci/ci-setup @@ -0,0 +1,219 @@ +#!/usr/bin/env bash +# +# GitHub Actions Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + +UNAME=`uname` +USE_PACKAGING=0 + +while [ $# -gt 0 ] ; do + if [ "$1" == "package" ] ; then + USE_PACKAGING=1 + fi + shift +done + + +# ###### Linux ############################################################## +if [ "${UNAME}" == "Linux" ] ; then + + # NOTE: lsb_release may not be installed, yet! + # => Guess distribution by checking for the packaging tool. + + # ====== Ubuntu/Deban ==================================================== + if [ -e /usr/bin/apt-get ] ; then + PACKAGES="lsb-release python3" + if [[ "${CC}" =~ .*gcc.* ]] ; then + PACKAGES="${PACKAGES} gcc" + elif [[ "${CC}" =~ .*clang.* ]] ; then + PACKAGES="${PACKAGES} clang" + fi + if [ ${USE_PACKAGING} -eq 1 ] ; then + # Need to install pbuilder as well: + PACKAGES="${PACKAGES} build-essential debian-archive-keyring debian-ports-archive-keyring devscripts eatmydata fakeroot lintian pbuilder python3-debian qemu-user-static" + fi + + apt-get update -qq + # DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -qy + DEBIAN_FRONTEND=noninteractive apt-get install -qqy -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --no-install-recommends \ + ${PACKAGES} + + if [ "`lsb_release -is`" == "Ubuntu" ] ; then + # Add PPA dreibh/ppa for Ubuntu: + DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef --no-install-recommends \ + software-properties-common + apt-add-repository -y ppa:dreibh/ppa || true + apt-get update -q + fi + + if [ ${USE_PACKAGING} -eq 1 ] ; then + # ====== pbuilder environment ====================================== + # Example for GitHub Actions: + # https://github.com/jrl-umi3218/github-actions/tree/master/setup-pbuilder + + if [ "${OS}" == "" ] ; then + OS=`lsb_release -is` + OS=${OS,,} + fi + if [ "${DIST}" == "" ] ; then + DIST=`lsb_release -cs` + fi + if [ "${ARCH}" == "" ] ; then + ARCH=`dpkg --print-architecture` + fi + + if [ "${OS}" == "ubuntu" ] ; then + COMPONENTS="main universe" + MIRRORSITE=http://no.archive.ubuntu.com/ubuntu/ + KEYRING="/usr/share/keyrings/ubuntu-archive-keyring.gpg" + elif [ "${OS}" == "debian" ] ; then + COMPONENTS="main" + if [ "${ARCH}" == "m68k" -o "${ARCH}" == "riscv64" ] ; then + # Debian Ports (special architectures) + MIRRORSITE="http://ftp.ports.debian.org/debian-ports/" + KEYRING="/usr/share/keyrings/debian-ports-archive-keyring.gpg" + else + # Debian (supported architectures) + MIRRORSITE="http://ftp.no.debian.org/debian/" + KEYRING="/usr/share/keyrings/debian-archive-keyring.gpg" + fi + else + echo >&2 "ERROR: Unknown Linux distribution ${OS}!" + exit 1 + fi + + cores=`getconf _NPROCESSORS_ONLN 2>/dev/null || true` + cat >/etc/pbuilderrc < /etc/dpkg/dpkg.cfg.d/02apt-speedup" | \ + pbuilder login --save-after-exec + + # ====== Add ppa:dreibh/ppa, updates and backports ================= + if [ "${OS}" == "ubuntu" ] ; then + # Add PPA dreibh/ppa for Ubuntu: + pbuilder login --save-after-login <&2 "ERROR: Unable to inject PPA configuration into Mock configuration file /etc/mock/fedora-${release}-${arch}.cfg!" + exit 1 + fi + fi + fi + + + # ====== Unknown ========================================================= + else + echo >&2 "ERROR: Unknown Linux distribution!" + exit 1 + fi + +# ###### FreeBSD ############################################################ +elif [ "${UNAME}" == "FreeBSD" ] ; then + + ASSUME_ALWAYS_YES=yes pkg install -y bash gcc libtool git python3 + + # Ports collection: + # This is the slow method via portsnap: + # portsnap --interactive fetch extract | grep -v ^/usr/ports + # Using Git is much faster: + rm -rf /usr/ports + git clone --depth=1 https://github.com/freebsd/freebsd-ports /usr/ports + +# ###### Unknown ############################################################ +else + + echo >&2 "ERROR: Unexpected system ${UNAME}!" + exit 1 + +fi diff --git a/ci/ci-test b/ci/ci-test new file mode 100755 index 0000000..914f7a3 --- /dev/null +++ b/ci/ci-test @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# +# GitHub Actions Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +UNAME=`uname` +if [ "${UNAME}" == "Linux" ] ; then + DISTRIBUTION=`lsb_release -is` +else + DISTRIBUTION="Unknown" +fi + + +# ###### Linux ############################################################## +if [ "${UNAME}" == "Linux" ] ; then + + # ====== Ubuntu ========================================================== + if [ "${DISTRIBUTION}" == "Ubuntu" -o "${DISTRIBUTION}" == "Debian" ] ; then + + # ====== pbuilder environment ========================================= + CHANGELOG_HEADER="`head -n1 debian/changelog`" + PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"` + PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"` + OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"` + DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"` + + packages="" + if [ $# -eq 0 ] ; then + echo "Looking for *${DEBIAN_VERSION}*.deb in /var/cache/pbuilder/result ..." + packages="`find /var/cache/pbuilder/result -name "*${DEBIAN_VERSION}*.deb"`" + fi + while [ $# -gt 0 ] ; do + echo "Looking for $1*${DEBIAN_VERSION}*.deb in /var/cache/pbuilder/result ..." + packages="${packages} `find /var/cache/pbuilder/result -name "$1*${DEBIAN_VERSION}*.deb"`" + shift + done + packages=`echo "${packages}" | xargs -n1 | sort -u | xargs` + if [ "${packages}" == "" ] ; then + echo >&2 "ERROR: No packages have been found!" + exit 1 + fi + + echo "Installing ${packages} ..." + DEBIAN_FRONTEND=noninteractive eatmydata apt-get install -fy ${packages} || { + echo "NOTE: apt-get failed -> trying dpkg instead of apt-get for local file!" + # NOTE: Older "apt-get" versions do not handle local files! + if ! DEBIAN_FRONTEND=noninteractive eatmydata dpkg -i ${packages} ; then + echo "There may be some dependencies missing. Trying to install them ..." + DEBIAN_FRONTEND=noninteractive eatmydata apt-get install -fy -o Dpkg::Options::="--force-confold" -o Dpkg::Options::="--force-confdef" --no-install-recommends + echo "Retrying to install ${packages} ..." + DEBIAN_FRONTEND=noninteractive eatmydata dpkg -i ${packages} + fi + } + echo "Done!" + + + # ====== Fedora ========================================================== + elif [ "${DISTRIBUTION}" == "Fedora" ] ; then + + # ====== mock environment ============================================= + PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"` + PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"` + + release=`bash -c "LANG=C.UTF-8 ; cat /etc/fedora-release | sed -e \"s/^\(.*\) release \([0-9]*\) (\(.*\))$/\2/g\"" | sed -e "s/[^0-9]//g"` + arch=`uname -m | sed -e "s/[^0-9a-zA-Z_+-]//g"` + if ! cd /var/lib/mock/fedora-${release}-${arch}/result ; then + if cd /var/lib/mock/fedora-rawhide-${arch}/result ; then + release="rawhide" + else + echo >&2 "ERROR: No results have been found!" + exit 1 + fi + fi + + packages="" + if [ $# -eq 0 ] ; then + echo "Looking for *${PACKAGE_VERSION}*.rpm in /var/lib/mock/fedora-${release}-${arch}/result ..." + packages="`find /var/lib/mock/fedora-${release}-${arch}/result -name "*${PACKAGE_VERSION}*.rpm" | grep -v "\.src\.rpm$"`" + fi + while [ $# -gt 0 ] ; do + echo "Looking for $1*${PACKAGE_VERSION}*.rpm in /var/lib/mock/fedora-${release}-${arch}/result ..." + packages="${packages} `find /var/lib/mock/fedora-${release}-${arch}/result -name "$1*${PACKAGE_VERSION}*.rpm" | grep -v "\.src\.rpm$"`" + shift + done + packages=`echo "${packages}" | xargs -n1 | sort -u | xargs` + if [ "${packages}" == "" ] ; then + echo >&2 "ERROR: No packages have been found!" + exit 1 + fi + + echo "Installing ${packages} ..." + LD_PRELOAD=/usr/lib64/nosync/nosync.so dnf install -y --allowerasing ${packages} + echo "Done!" + + + # ====== Unknown ========================================================= + else + echo >&2 "ERROR: Unknown Linux distribution ${DISTRIBUTION}!" + exit 1 + fi + + +# ###### FreeBSD ############################################################ +elif [ "${UNAME}" == "FreeBSD" ] ; then + + # TDB + true + + +# ###### Unknown ############################################################ +else + + echo >&2 "ERROR: Unexpected system ${UNAME}!" + exit 1 + +fi diff --git a/ci/get-dependencies b/ci/get-dependencies new file mode 100755 index 0000000..3edde45 --- /dev/null +++ b/ci/get-dependencies @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Travis CI Scripts +# Copyright (C) 2018-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + + +import glob +import os +import re +import subprocess +import sys + + +# ###### Extract dependencies ############################################### +depLine = re.compile(r'^(.*:[ \t]*)(.*)$') +depItem = re.compile(r'^([a-zA-Z0-9-+\.]+)[\s]*(|\|.*|\(.*)[\s]*$') + +def extractDependencies(line, system): + dependencies = [] + + # Remove "build-depends:", etc.: + m = depLine.match(line) + if m != None: + line = m.group(2) + line = line.strip() + + # Split into segments + for l in line.split(','): + l = l.strip() + m = depItem.match(l) + if m != None: + dependency = m.group(1) + + # ------ Ugly work-around for cmake -------------------------------- + # We need cmake >= 3.0! + if ((dependency == 'cmake') or (dependency == 'cmake3')): + if ((system == 'debian') or (system == 'ubuntu')): + try: + distribution = subprocess.check_output( ["lsb_release", "-cs"] ).decode('utf-8').strip() + # print("distribution=", distribution, ".") + if distribution in [ 'trusty' ]: + dependency = 'cmake3' + except: + pass + + dependencies.append(dependency) + + return dependencies + + +# ###### Main program ####################################################### + +# ====== Check arguments ==================================================== +if len(sys.argv) < 2: + sys.stderr.write('Usage: ' + sys.argv[0] + ' debian|ubuntu|fedora|freebsd [-i|--install]\n') + sys.exit(1) +system = sys.argv[1] +runInstall = False +for i in range(2, len(sys.argv)): + if sys.argv[i] == '-i' or sys.argv[i] == '--install': + runInstall = True + else: + sys.stderr.write('ERROR: Bad parameter ' + sys.argv[i] + '!') + sys.exit(1) + +# ====== Debian/Ubuntu ====================================================== +dependencies = [ ] +if ((system == 'debian') or (system == 'ubuntu')): + if os.path.exists('debian/control'): + with open('debian/control', 'r', encoding='utf-8') as fp: + inside = False + for line in fp: + if not line: + break + line_lower = line.lower() + if inside: + if line.startswith((' ', "\t")): + dependencies = dependencies + extractDependencies(line, system) + continue + elif line.startswith('#'): + continue + inside = False + if line_lower.startswith(('build-depends:', 'build-depends-indep:')): + dependencies = dependencies + extractDependencies(line, system) + inside = True + + for dependency in sorted(set(dependencies)): + sys.stdout.write(dependency + ' ') + sys.stdout.write('\n') + + if runInstall == True: + subprocess.call([ 'apt-get', 'install', '-qy' ] + dependencies) + + else: + sys.stderr.write('ERROR: Unable to locate Debian control file!\n') + sys.exit(1) + + +# ====== Fedora ============================================================= +elif system == 'fedora': + specFiles = glob.glob('rpm/*.spec') + if len(specFiles) == 1: + with open(specFiles[0], 'r', encoding='utf-8') as fp: + inside = False + for line in fp: + if not line: + break + line_lower = line.lower() + if inside: + if line.startswith((' ', "\t")): + dependencies = dependencies + extractDependencies(line, system) + continue + elif line.startswith('#'): + continue + inside = False + if line_lower.startswith('buildrequires:'): + dependencies = dependencies + extractDependencies(line, system) + inside = True + + for dependency in sorted(set(dependencies)): + sys.stdout.write(dependency + ' ') + sys.stdout.write('\n') + + if runInstall == True: + subprocess.call([ 'dnf', 'install', '-y' ] + dependencies) + + else: + sys.stderr.write('ERROR: Unable to locate RPM spec file!\n') + sys.exit(1) + + +# ====== FreeBSD ============================================================ +elif system == 'freebsd': + freeBSDMakefile = glob.glob('freebsd/*/Makefile') + if len(freeBSDMakefile) == 1: + freeBSDDirectory = os.path.dirname(freeBSDMakefile[0]) + + cmd = 'make build-depends-list && make run-depends-list' + try: + os.chdir(freeBSDDirectory) + output = subprocess.check_output(cmd, shell=True) + except Exception as e: + sys.stderr.write('ERROR: Getting FreeBSD dependencies failed: ' + str(e) + '\n') + sys.exit(1) + + if output != None: + ports = output.decode('utf-8').splitlines() + for port in ports: + basename = os.path.basename(port) + if basename == 'glib20': + basename = 'glib' # May be there is a better solution here? + dependencies.append(basename) + + for dependency in sorted(set(dependencies)): + sys.stdout.write(dependency + ' ') + sys.stdout.write('\n') + + if runInstall == True: + subprocess.call([ 'pkg', 'install', '-y' ] + dependencies) + + else: + sys.stderr.write('ERROR: Unable to locate FreeBSD port makefile!\n') + sys.exit(1) + + +# ====== Error ============================================================== +else: + sys.stderr.write('ERROR: Invalid system name "' + system + '"!\n') + sys.exit(1) diff --git a/clean-deb b/clean-deb new file mode 100755 index 0000000..defcd75 --- /dev/null +++ b/clean-deb @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# +# Debian/Ubuntu Packaging Scripts +# Copyright (C) 2002-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + + +# ====== Obtain package information ========================================= +CHANGELOG_HEADER="`head -n1 debian/changelog`" +PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"` + + +# ====== Clean up =========================================================== +rm -f *.deb *.dsc *.asc *.changes *.build *.upload *.tar.gz stamp-h* svn-commit* *~ + +for type in gz bz2 xz ; do + find . -maxdepth 1 -name "${PACKAGE}-*.${type}" | xargs -r rm + find . -maxdepth 1 -name "${PACKAGE}_*.${type}" | xargs -r rm +done +find . -maxdepth 1 -name "*.buildinfo" | xargs -r rm + +shopt -s extglob +rm -rf ${PACKAGE}-+([0-9]).+([0-9]).+([0-9])* diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c1b0861 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +ripe.atlas.cousteau (1.5.0a2.td1-1ubuntu1) jammy; urgency=medium + + * New upstream version. + + -- Thomas Dreibholz Wed, 16 Feb 2022 08:08:08 +0800 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +12 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..093a9bf --- /dev/null +++ b/debian/control @@ -0,0 +1,42 @@ +Source: ripe.atlas.cousteau +Section: python +Priority: optional +Maintainer: Thomas Dreibholz +Homepage: https://github.com/dreibh/ripe-atlas-cousteau +Build-Depends: debhelper (>= 12), + dh-python, + python3-all, + python3-coverage, + python3-dateutil, + python3-funcsigs, + python3-jsonschema, + python3-mock, + python3-nose, + python3-pytest, + python3-requests, + python3-setuptools, + python3-socketio, + python3-socketio-client, + python3-websocket +Standards-Version: 4.6.0.1 +Rules-Requires-Root: no + +Package: ripe.atlas.cousteau +Architecture: all +Depends: python3-coverage, + python3-dateutil, + python3-funcsigs, + python3-jsonschema, + python3-mock, + python3-nose, + python3-requests, + python3-socketio, + python3-socketio-client, + python3-websocket, + ${misc:Depends}, + ${python3:Depends}, + ${shlibs:Depends} +Description: RIPE Atlas Cousteau + A Python wrapper around the + RIPE ATLAS API. + See https://ripe-atlas-cousteau.readthedocs.io/en/latest/ for details! diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..35cda26 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,24 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: RIPE Atlas Cousteau +Source: https://github.com/dreibh/ripe-atlas-cousteau + +Files: * +Copyright: 2014-2018 The RIPE Atlas Team +License: GPL-3+ + +License: GPL-3+ + 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 . + . + On Debian systems, the complete text of the GNU General + Public License can be found in `/usr/share/common-licenses/GPL-3'. diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..0d409c8 --- /dev/null +++ b/debian/rules @@ -0,0 +1,6 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 +export PYBUILD_NAME=ripe-atlas-cousteau + +%: + dh $@ --with python3 --buildsystem=pybuild diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/tests/control b/debian/tests/control new file mode 100644 index 0000000..5647142 --- /dev/null +++ b/debian/tests/control @@ -0,0 +1 @@ +Tests: diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 0000000..adebe51 --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,7 @@ +Name: TSCTP +Homepage: https://github.com/RIPE-NCC/ripe-atlas-cousteau +Repository: https://github.com/RIPE-NCC/ripe-atlas-cousteau.git +Repository-Browse: https://github.com/RIPE-NCC/ripe-atlas-cousteau +Bug-Submit: https://github.com/RIPE-NCC/ripe-atlas-cousteau/issues +Contact: The RIPE Atlas Team +Security-Contact: The RIPE Atlas Team diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc new file mode 100644 index 0000000..4b16925 --- /dev/null +++ b/debian/upstream/signing-key.asc @@ -0,0 +1,405 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQGiBDr2cOgRBAC71Xhy1yzNTBxnousyxwtZ+zxRQJIfkDUQ8Yry5/rdoRkUldnE +VQUNX9owxKKwA40DsKMX5lfPIgfPpefqnSOx1/XOtjpffkF8+FY8ncU/LKvHPPw3 +oNXzFAr8F6NqpJAIbp8eW6DlfraXiJFZk0D6sZyIk9XDqTY01+Dn5WmAewCg4Szj +r52geHYk+6n83yfVqw8+c3MD/A9d4ylhJikTHzbL83HTO7WozqlGtZq0rwGY+JIq +wPAaRAdBnu0brQz7xtfTZrvxA6v3sYb73bpuosaQNtg1K5Z0l0fbJQxls7wCdSC4 +GmkXyl64c1bPiGMHu7WVE85mwdm4KyD7qELnnNKZoagFgK1HNYFJtuUDYQ3ihBQq +k0VnBACaqJ4k/VJYPQvuWy0fppX+Ultyqz2rrHqqVvaSotjc8muxwM0OL42ZCjL1 +scuFb1TonojymUFa1nqe6uYU5Owjh2CRfs5+TnMUO7S7vXQRQgWPffIE7kJqL46G +S79MmHXVWwmO1WMpJooTlsCUv+J+pAWpYu5nJY4X/s+1DXSA9LQoVGhvbWFzIERy +ZWliaG9seiA8ZHJlaWJoQGllbS51bmktZHVlLmRlPoheBBMRAgAeBQJCWjEIAhsD +BgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEN9gW7B2Dy1lSRAAnj/KX959nDkAh9Af +RYaLHkz7+60/AKDWAxDnQxnNnB32zjxJvtLKxK0uY7QvVGhvbWFzIERyZWliaG9s +eiA8ZHJlaWJoQGV4cC1tYXRoLnVuaS1lc3Nlbi5kZT6IVwQTEQIAFwUCOvZw6AUL +BwoDBAMVAwIDFgIBAheAAAoJEN9gW7B2Dy1l6BcAnRhM7hgy3qOLDKpsqIY88XZa +MjMqAKDHqpiM/8CFpti9TKeIP/mRbva/3tH/AABE5v8AAEThARAAAQEAAAAAAAAA +AAAAAAD/2P/gABBKRklGAAEBAgAcABwAAP/bAEMABgQFBgUEBgYFBgcHBggKEAoK +CQkKFA4PDBAXFBgYFxQWFhodJR8aGyMcFhYgLCAjJicpKikZHy0wLSgwJSgpKP/b +AEMBBwcHCggKEwoKEygaFhooKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo +KCgoKCgoKCgoKCgoKCgoKCgoKP/CABEIARgA2wMBIgACEQEDEQH/xAAbAAACAwEB +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 +lFUAoMJrt3ofCGhrsOs9pMA//3rkg/Js +=0dBa +-----END PGP PUBLIC KEY BLOCK----- diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..3bc36a9 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +version=3 +opts=pgpsigurlmangle=s/$/.asc/ \ +https://packages.nntb.no/software/ripe.atlas.cousteau ripe.atlas.cousteau-(.*)\.tar\.bz2 diff --git a/fetch-debian-changelog b/fetch-debian-changelog new file mode 100755 index 0000000..c202ffb --- /dev/null +++ b/fetch-debian-changelog @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Packaging Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: dreibh@simula.no +# + +import glob +import os +import re +import shutil +import subprocess +import sys +import tempfile +import time +import urllib.error +import urllib.request + + +# ====== Handle arguments ================================================== +if len(sys.argv) < 2: + sys.stderr.write('Usage: ' + sys.argv[0] + ' package [distribution]\n') + sys.exit(1) + +debianPackage = sys.argv[1] +if len(sys.argv) == 2: + debianDistribution = 'unstable' +else: + debianDistribution = sys.argv[2] +if debianDistribution in [ 'unstable', 'testing', 'stable', 'oldstable' ]: + # Debian + statusPageURL = 'https://packages.debian.org/source/' + debianDistribution + '/' + debianPackage +else: + # Ubuntu + statusPageURL = 'https://packages.ubuntu.com/source/' + debianDistribution + '/' + debianPackage + +debianVersion = None +debianLocation = None +debianArchive = None +debianArchiveFormat = None + + +# ====== Get package status ================================================= +statusPageContents = None +sys.stderr.write('Looking for package status on ' + statusPageURL + ' ... ') +sys.stderr.flush() +try: + statusPage = urllib.request.urlopen(statusPageURL) + statusPageContents = statusPage.readlines() + statusPage.close() + + re_debian_package = re.compile(r'.*Source Package: ' + debianPackage + ' \(([0-9-+~\.a-z]+)\)') + re_debian_archive = re.compile(r'.*href="((http|https)://[a-zA-Z0-9\./+-]+/' + \ + debianPackage[0:1] + '/' + \ + debianPackage + '/' + \ + r')(' + debianPackage + r'_[0-9-+~\.a-z]+\.debian\.tar\.[a-zA-Z]+)"') + for line in statusPageContents: + line = line.decode('utf-8') + match = re_debian_package.match(line) + if match != None: + debianVersion = match.group(1) + else: + match = re_debian_archive.match(line) + if match != None: + debianLocation = match.group(1) + debianArchive = match.group(3) + +except urllib.error.HTTPError as e: + sys.stderr.write('not found (HTTP ' + str(e.code) + ')!\n') + sys.exit(1) + +if (debianVersion == None) or (debianArchive == None): + sys.stderr.write('not found!\n') + sys.exit(1) + +sys.stderr.write('Version in ' + debianDistribution + ' is ' + debianVersion + '\n') + + +# ====== Determine necessary compression option ============================= +debianArchiveFormat = debianArchive[len(debianArchive) - 2 : len(debianArchive)] +tarCompressionOption = '' +if debianArchiveFormat == 'gz': + tarCompressionOption = 'z' +elif debianArchiveFormat == 'bz2': + tarCompressionOption = 'j' +elif debianArchiveFormat == 'xz': + tarCompressionOption = 'J' + + +# ====== Fetch debian archive =============================================== +archiveFileURL = debianLocation + debianArchive +sys.stderr.write('Looking for \"debian\" archive at ' + archiveFileURL + ' ... ') +sys.stderr.flush() +try: + archiveFile = urllib.request.urlopen(archiveFileURL) + debianArchiveFile = tempfile.NamedTemporaryFile(delete=False) + shutil.copyfileobj(archiveFile, debianArchiveFile) + debianArchiveFile.close() + archiveFile.close() + sys.stderr.write('found!\n') + + try: + + process = subprocess.run([ 'tar', 'x' + tarCompressionOption + 'fO', debianArchiveFile.name, 'debian/changelog'], + stderr=subprocess.PIPE, check=True, universal_newlines=True) + + os.unlink(debianArchiveFile.name) + + except Exception as e: + sys.stderr.write('ERROR: Failed to extract debian/changelog from ' + debianArchiveFile.name + ': ' + str(e) + '\n') + sys.exit(1) + +except urllib.error.HTTPError as e: + sys.stderr.write('not found (HTTP ' + str(e.code) + ')!\n') + sys.exit(1) diff --git a/filter-debian-changelog b/filter-debian-changelog new file mode 100755 index 0000000..88ecd1e --- /dev/null +++ b/filter-debian-changelog @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Debian/Ubuntu Packaging Scripts +# Copyright (C) 2002-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + + +# This script filters debian/changelog entries: +# Usage: filter-debian-changelog [regexp_for_last_entry|FIRST] +# * Empty entries get dropped. +# * Stop, if entry matches regexp_for_last_entry argument. +# * Stop after first entry, if regexp_for_last_entry = FIRST. +# Example: filter-debian-changelog "Mon, 31 Oct 2016 08:08:08 \+0200" +# Note the \+, otherwise '+' is interpreted as regexp! + + +import glob +import os +import re +import sys +import time + + +# ====== Handle arguments ================================================== +if len(sys.argv) < 2: + sys.stderr.write('Usage: ' + sys.argv[0] + ' regexp_for_last_entry|FIRST\n') + sys.exit(1) + +if sys.argv[1] == '': + re_last_entry = None +elif sys.argv[1] == 'FIRST': + re_last_entry = re.compile(r'^.*$') +else: + re_last_entry = re.compile(r'^.*' + sys.argv[1]) + +re_begin_of_entry = re.compile(r'^[a-zA-Z].*$') +re_end_of_entry = re.compile(r'^ --.*$') +re_empty = re.compile(r'^$') +re_item = re.compile(r'^ *') +re_item_is_itp = re.compile(r'^(.*Closes:.*ITP.*|.*ITP.*Closes:.*)$') + +entries = 0 +entryContentLines = 0 +entryContent = '' +entryIsITP = False + +contents = sys.stdin.readlines() +for line in contents: + + # ====== Begin of entry ================================================== + if entryContentLines == 0: + if re_begin_of_entry.match(line): + entryContent = line + entryContentLines = 1 + + # ====== Within entry ==================================================== + else: + # ------ End of entry ------------------------------------------------- + if re_end_of_entry.match(line): + entryContent = entryContent + line + '\n' + if entryContentLines > 1: + entries = entries + 1 + + # ------ Print entry -------------------------------------------- + if not entryIsITP: + sys.stdout.write(entryContent) + # ------ Print entry with ITP ----------------------------------- + # Special case: The ITP package for Debian must only contain the + # ITP entry with ITP item and nothing else! + else: + splittedITPEntry = entryContent.splitlines() + i = 0 + for itpLine in splittedITPEntry: + i = i + 1 + if (i <= 2) or (i >= len(splittedITPEntry) - 2): + sys.stdout.write(itpLine + '\n') + elif re_item_is_itp.match(itpLine) != None: + sys.stdout.write(itpLine + '\n') + break # ITP -> done! + + entryContent = '' + entryIsITP = False + + # ------ Check for match with last entry regexp in argument -------- + if re_last_entry != None: + if re_last_entry.match(line) != None: + break + + entryContentLines = 0 + + # ------ Part of entry ------------------------------------------------ + else: + if re_item.match(line): + entryContent = entryContent + line + entryContentLines = entryContentLines + 1 + if re_item_is_itp.match(line): + entryIsITP = True diff --git a/make-deb b/make-deb new file mode 100755 index 0000000..3566af5 --- /dev/null +++ b/make-deb @@ -0,0 +1,369 @@ +#!/usr/bin/env bash +# +# Debian/Ubuntu Packaging Scripts +# Copyright (C) 2002-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +# --------------------------------------------------------------------------- +# USAGE: +# ./make-deb default => for Ubuntu REVU +# Note: Replaces "Maintainer" by Ubuntu Developers and +# writes original maintainer entry to "XSBC-Original-Maintainer" +# ./make-deb unstable => for Debian Mentors +# ./make-deb bionic|disco|... => for Launchpad PPA +# --------------------------------------------------------------------------- + + +# Set current Debian debhelper version here +# for building unstable/testing/stable packages +# (See https://packages.qa.debian.org/d/debhelper.html for latest version!) +DEBHELPER_LATEST_VERSION="13" + + +# ====== Obtain package and version information ============================= +DISTRIBUTIONS=`\ +( \ +while [ x$1 != "x" ] ; do \ + echo $1 + shift +done \ +) | sort -u` +if [ "${DISTRIBUTIONS}" == "" ] ; then + DISTRIBUTIONS="default" +fi + + +CHANGELOG_HEADER="`head -n1 debian/changelog`" + +# The package name, e.g. MyApplication +PACKAGE=`echo ${CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"` +# The package distribution, e.g. precise, raring, ... +PACKAGE_DISTRIBUTION=`echo ${CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"` +# The package's version, e.g. 1.2.3-1ubuntu1 +PACKAGE_VERSION=`echo ${CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"` +# The package's output version, e.g. 1.2.3-1ubuntu +OUTPUT_VERSION=`echo ${PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"` +# The package's Debian version, e.g. 1.2.3-1 +DEBIAN_VERSION=`echo ${OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"` +# The package's upstream version, e.g. 1.2.3 +UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"` +# The package's plain upstream version, e.g. 1.2.3 (without e.g. ~svn) +PLAIN_VERSION=`echo ${UPSTREAM_VERSION} | sed -e "s/\([0-9\.]*\)[-+~].*$/\1/"` + + +echo -e "\x1b[34m######################################################################\x1b[0m" +echo -e "\x1b[34mCHANGELOG_HEADER: ${CHANGELOG_HEADER}\x1b[0m" +echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m" +echo -e "\x1b[34mPACKAGE_DISTRIBUTION: ${PACKAGE_DISTRIBUTION}\x1b[0m" +echo -e "\x1b[34mPACKAGE_VERSION ${PACKAGE_VERSION}\x1b[0m" +echo -e "\x1b[34mOUTPUT_VERSION: ${OUTPUT_VERSION}\x1b[0m" +echo -e "\x1b[34mDEBIAN_VERSION: ${DEBIAN_VERSION}\x1b[0m" +echo -e "\x1b[34mUPSTREAM_VERSION: ${UPSTREAM_VERSION}\x1b[0m" +echo -e "\x1b[34mPLAIN_VERSION: ${PLAIN_VERSION}\x1b[0m" +echo -e "\x1b[34m######################################################################\x1b[0m" + +if [ ! -e ./packaging.conf ] ; then + echo >&2 "ERROR: packaging.conf does not exist -> no configuration for the new package!" + exit 1 +fi +. ./packaging.conf + + +# ====== Run warp-and-sort tool ============================================= +if [ -e /usr/bin/wrap-and-sort ] ; then + echo -e "" + echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Calling wrap-and-sort ==========================================\x1b[0m" + echo -e "" + wrap-and-sort -a -v +fi + + +# ====== Create upstream source package ===================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m" +echo -e "" +if [ "${SKIP_PACKAGE_SIGNING}" != "" -a ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then + ./make-upstream-package ${PACKAGE} ${UPSTREAM_VERSION} "${MAKE_DIST}" -skip-signing +else + ./make-upstream-package ${PACKAGE} ${UPSTREAM_VERSION} "${MAKE_DIST}" +fi + +for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do + UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-${UPSTREAM_VERSION}.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`" + if [ -e "${UPSTREAM_PACKAGE}" ] ; then + break + fi +done +if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then + echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-${UPSTREAM_VERSION}.tar.*) found!\x1b[0m" + exit 1 +fi + + +# ====== Build source packages ============================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Building source packages =======================================\x1b[0m" +for DISTRIBUTION in ${DISTRIBUTIONS} ; do + + updatedDebhelperVersion=0 + + echo -e "" + echo -e "\x1b[34m------ Creating package for ${DISTRIBUTION} ------\x1b[0m" + + cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE} + cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE} + cp ${UPSTREAM_PACKAGE} ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE} + if [ ! ${SKIP_PACKAGE_SIGNING} == "1" -a ! "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then + cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + cp ${UPSTREAM_PACKAGE}.asc ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + else + rm -f ${PACKAGE}_${UPSTREAM_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + rm -f ${PACKAGE}_${OUTPUT_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + rm -f ${PACKAGE}_${DEBIAN_VERSION}.orig.tar.${UPSTREAM_PACKAGE_TYPE}.asc + fi + rm -rf ${PACKAGE}-${UPSTREAM_VERSION} + rm -rf ${PACKAGE}-${UPSTREAM_VERSION}.orig + if [ "${UPSTREAM_PACKAGE_TYPE}" == "gz" ] ; then + tar xzf ${UPSTREAM_PACKAGE} + elif [ "${UPSTREAM_PACKAGE_TYPE}" == "bz2" ] ; then + tar xjf ${UPSTREAM_PACKAGE} + elif [ "${UPSTREAM_PACKAGE_TYPE}" == "xz" ] ; then + tar xJf ${UPSTREAM_PACKAGE} + else + echo 2>&1 "ERROR: Bad archive format: ${UPSTREAM_PACKAGE}" + exit 1 + fi + cp -r debian ${PACKAGE}-${UPSTREAM_VERSION} + find ${PACKAGE}-${UPSTREAM_VERSION} -name .svn | xargs --no-run-if-empty rm -rf + cd ${PACKAGE}-${UPSTREAM_VERSION} + + if [ "${DISTRIBUTION}" != "default" ] ; then + if [ "${DISTRIBUTION}" == "unstable" -o "${DISTRIBUTION}" == "testing" -o "${DISTRIBUTION}" == "stable" -o "${DISTRIBUTION}" == "oldstable" ] ; then + # Fetch debian/changelog from Debian, if available. + # If there is a Debian changelog, merge new entries. + if ../fetch-debian-changelog ${PACKAGE} ${DISTRIBUTION} >debian/changelog.dist ; then + ../merge-debian-changelogs debian/changelog debian/changelog.dist >debian/changelog.merged && \ + mv debian/changelog.merged debian/changelog + fi + rm -f debian/changelog.dist + + # Debian: Also remove Launchpad Bug IDs. + sed -e "s/${PACKAGE_DISTRIBUTION};/${DISTRIBUTION};/1" \ + -e "s/\(ubuntu\|ppa\)[0-9]//1" \ + -e "/(LP: #/D" \ + debian/changelog.new + else + # Ubuntu PPA + # Naming example: 2.7.7-1ubuntu~focal1 + # Ubuntu: Also remove Debian Bug IDs. + sed -e "s/${PACKAGE_DISTRIBUTION};/${DISTRIBUTION};/1" \ + -e "s/${PACKAGE_VERSION}/${OUTPUT_VERSION}~${DISTRIBUTION}1/1" \ + -e "/(Closes: #/D" \ + debian/changelog.new + + # ------ Old distributions not supporting c++/regex style symbols -- + if [ "${DISTRIBUTION}" == "dapper" -o \ + "${DISTRIBUTION}" == "edgy" -o \ + "${DISTRIBUTION}" == "feisty" -o \ + "${DISTRIBUTION}" == "hardy" -o \ + "${DISTRIBUTION}" == "intrepid" -o \ + "${DISTRIBUTION}" == "jaunty" -o \ + "${DISTRIBUTION}" == "karmic" -o \ + "${DISTRIBUTION}" == "lucid" ] ; then + # Just skip the symbols ... + find debian/ -maxdepth 1 -name "*.symbols" | xargs --no-run-if-empty rm -f + fi + fi + + # Remove additional newlines at the end of the file: + sed -i -e :a -e '/^\n*$/{$d;N;};/\n$/ba' debian/changelog.new + + mv debian/changelog.new debian/changelog + + # ------ Old distributions not supporting new Debian format ----------- + if [ "${DISTRIBUTION}" == "dapper" -o \ + "${DISTRIBUTION}" == "edgy" -o \ + "${DISTRIBUTION}" == "feisty" -o \ + "${DISTRIBUTION}" == "hardy" -o \ + "${DISTRIBUTION}" == "intrepid" -o \ + "${DISTRIBUTION}" == "jaunty" ] ; then + rm -rf debian/source + fi + + # ------ Use latest Debhelper for Debian ------------------------------ + if [ "${DISTRIBUTION}" == "unstable" -o "${DISTRIBUTION}" == "testing" -o "${DISTRIBUTION}" == "stable" -o "${DISTRIBUTION}" == "oldstable" ] ; then + # Update debhelper version: + # Also get rid of legacy cmake3 dependency alternative. + sed -e "s/debhelper (.* [0-9]*)/debhelper-compat (= ${DEBHELPER_LATEST_VERSION})/g" \ + -e "s/ | cmake3//g" \ + debian/control.new + # Newer debhelper does not need "--parallel" for building: + sed -e "s/\(.*dh .. .*--buildsystem=cmake.*\)\(--parallel\)\(.*\)/\1\3/g" -e 's@[[:space:]]*$@@g' \ + debian/rules.new + # There is no need for debian/compat any more: + rm -f debian/compat + mv debian/control.new debian/control + mv debian/rules.new debian/rules + updatedDebhelperVersion=1 + fi + + else + # Ubuntu: Remove Debian Bug IDs. + sed -e "/(Closes: #/D" \ + debian/changelog.new + mv debian/changelog.new debian/changelog + sed -e "s/^Maintainer:/Maintainer: Ubuntu Developers \nXSBC-Original-Maintainer:/g" debian/control.new + mv debian/control.new debian/control + fi + + echo -e "" + echo -e "\x1b[34m------ Creating diff file ${PACKAGE}-${PACKAGE_VERSION}.diff.gz ------\x1b[0m" + ( + cd .. + diff -urN "--exclude=*~" "--exclude=.svn" "--exclude=.git" \ + ${PACKAGE}-${UPSTREAM_VERSION}.orig ${PACKAGE}-${UPSTREAM_VERSION} \ + | gzip -c >${PACKAGE}-${PACKAGE_VERSION}.diff.gz + ) + + + echo -e "" + echo -e "\x1b[34m------ Building source package ------\x1b[0m" + + # Without signature: + # debuild -us -uc + # For sources: + # debuild -S + # For binaries: + # debuild -b + # Use -i to ignore .svn files! + + if [ "${SKIP_PACKAGE_SIGNING}" == "" ] ; then + SKIP_PACKAGE_SIGNING=0 + fi + if [ $updatedDebhelperVersion -eq 0 ] ; then + opt="" + else + opt="--no-check-builddeps" # Needed for increased debhelper version! + fi + if [ ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then + # Build source package without signature: + debuild ${opt} -us -uc -S -i || exit 1 + else + # Build source package including signature: + if [ "${MAINTAINER_KEY}" == "" ] ; then + echo >&2 "ERROR: MAINTAINER_KEY is not set!" + exit 1 + fi + debuild ${opt} -sa -S "-k${MAINTAINER_KEY}" -i || exit 1 + fi + + # Important: In /etc/pbuilderrc, set COMPONENTS="main universe"! + # Important: After that, update with option "--override-config"! + # sudo pbuilder update --override-config + + cd .. + + if [ "${DISTRIBUTION}" == "unstable" -o \ + "${DISTRIBUTION}" == "testing" -o \ + "${DISTRIBUTION}" == "stable" -o \ + "${DISTRIBUTION}" == "oldstable" -o \ + "${DISTRIBUTION}" == "default" ] ; then + if [ "${DISTRIBUTION}" == "default" ] ; then + version=${PACKAGE_VERSION} + else + version=${DEBIAN_VERSION} + fi + dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1` + else + dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9].dsc | tail -n1` + fi + if [ ! -e "${dscFile}" ] ; then + echo -e "\x1b[34mERROR: ${dscFile} has not been generated successfully -> Aborting!\x1b[0m" + exit 1 + fi + +done + + +# ====== Show results ======================================================= +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Results overview ============================================\x1b[0m" +echo -e "" + +echo -e "\x1b[34mUpload to PPA:\x1b[0m" +for DISTRIBUTION in ${DISTRIBUTIONS} ; do + if [ "${DISTRIBUTION}" == "unstable" -o \ + "${DISTRIBUTION}" == "testing" -o \ + "${DISTRIBUTION}" == "stable" -o \ + "${DISTRIBUTION}" == "oldstable" -o \ + "${DISTRIBUTION}" == "default" ] ; then + if [ "${DISTRIBUTION}" == "default" ] ; then + ppa="revu" + version=${PACKAGE_VERSION} + else + ppa="mentors" + version=${DEBIAN_VERSION} + fi + changesFile=`ls ${PACKAGE}_${version}_source.changes | tail -n1` + else + ppa="ppa" + changesFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9]_source.changes | tail -n1` + fi + echo -e "\x1b[34m dput ${ppa} $changesFile\x1b[0m" +done +echo -e "" + +if [ -e make-symbols ] ; then + echo -e "\x1b[34m################################################################\x1b[0m" + echo -e "\x1b[34mDo not forget to run make-symbols after library version changes!\x1b[0m" + echo -e "\x1b[34m################################################################\x1b[0m" + echo -e "" +fi + +echo -e "\x1b[34mBuild Test Commands:\x1b[0m" +for DISTRIBUTION in ${DISTRIBUTIONS} ; do + if [ "${DISTRIBUTION}" == "unstable" -o \ + "${DISTRIBUTION}" == "testing" -o \ + "${DISTRIBUTION}" == "stable" -o \ + "${DISTRIBUTION}" == "oldstable" -o \ + "${DISTRIBUTION}" == "default" ] ; then + if [ "${DISTRIBUTION}" == "default" ] ; then + version=${PACKAGE_VERSION} + else + version=${DEBIAN_VERSION} + fi + changesFilesPattern="${PACKAGE}_${version}_*.changes" + dscFile=`ls ${PACKAGE}_${version}.dsc | tail -n1` + else + changesFilesPattern="${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9]_*.changes" + dscFile=`ls ${PACKAGE}_${OUTPUT_VERSION}~${DISTRIBUTION}[0-9].dsc | tail -n1` + fi + profile="ubuntu" + if [ "${DISTRIBUTION}" == "unstable" -o \ + "${DISTRIBUTION}" == "testing" -o \ + "${DISTRIBUTION}" == "stable" -o \ + "${DISTRIBUTION}" == "oldstable" ] ; then + profile="debian" + fi + echo -e "\x1b[34m sudo pbuilder build ${dscFile} && lintian -iIEv --profile ${profile} --pedantic /var/cache/pbuilder/result/$changesFilesPattern\x1b[0m" +done +echo -e "" diff --git a/make-dist b/make-dist new file mode 100755 index 0000000..c883a39 --- /dev/null +++ b/make-dist @@ -0,0 +1,6 @@ +#!/bin/sh + +mkdir -p dist/ +rm -f dist/* +python3 setup.py sdist --formats=bztar +mv dist/*.bz2 . diff --git a/make-ppa b/make-ppa new file mode 100755 index 0000000..bd9a93f --- /dev/null +++ b/make-ppa @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +# +# Packaging Scripts +# Copyright (C) 2002-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + +COPR=0 +DPUT=0 + +# NOTE: These are the supported distributions by Ubuntu Launchpad and Debian: +DPUT_DISTRIBUTIONS="precise trusty xenial bionic focal jammy lunar mantic noble unstable" + +while [ $# -gt 0 ] ; do + if [ "$1" == "dput" ] ; then + DPUT=1 + elif [ "$1" == "copr" ] ; then + COPR=1 + elif [ "$1" == "all" ] ; then + DPUT=1 + COPR=1 + else + echo >&2 "Usage: $0 [dput] [copr] [all]" + exit 1 + fi + shift +done + +if [ ${DPUT} -eq 0 -a ${COPR} -eq 0 ] ; then + COPR=1 + DPUT=1 +fi + +if [ ! -e debian/ ] ; then + DPUT=0 +fi +if [ ! -e rpm/ ] ; then + COPR=0 +fi + + +# ====== Build source packages ============================================== +./clean-deb +if [ ${DPUT} -ne 0 ] ; then + . ./packaging.conf + if [ "${NOT_TARGET_DISTRIBUTIONS}" == "" ] ; then + echo >&2 "ERROR: Define NOT_TARGET_DISTRIBUTIONS in packaging.conf!" + exit 1 + fi + buildForDistribution="" + for dputDistribution in ${DPUT_DISTRIBUTIONS} ; do + notATarget=0 + for notTargetDistribution in ${NOT_TARGET_DISTRIBUTIONS} ; do + if [ "${notTargetDistribution}" == "${dputDistribution}" ] ; then + notATarget=1 + break + fi + done + if [ $notATarget -eq 0 ] ; then + buildForDistribution="${buildForDistribution} ${dputDistribution}" + fi + done + + echo "Building for distributions:${buildForDistribution}" + ./make-deb ${buildForDistribution} +fi + +if [ ${COPR} -ne 0 ] ; then + if [ -e rpm -o -e ./make-srpm ] ; then + ./make-srpm || exit 1 + else + echo >&2 "ERROR: RPM files not found!" + exit 1 + fi +fi + + +# ====== dput =============================================================== +if [ ${DPUT} -ne 0 ] ; then + changeFiles=`find . -mindepth 1 -maxdepth 1 -name "*.changes"` + for changeFile in ${changeFiles} ; do + if [[ ${changeFile} =~ -[0-9]_source.changes$ ]] ; then + dput mentors ${changeFile} + else + dput ppa ${changeFile} + fi + done +fi + + +# ====== COPR =============================================================== +if [ ${COPR} -ne 0 ] ; then + PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"` + SRPM=`find ${HOME}/rpmbuild/SRPMS -name "${PACKAGE}-*.src.rpm"` + if [ ! -e "${SRPM}" ] ; then + echo >&2 "ERROR: ${PACKAGE}-*.src.rpm not found!" + exit 1 + fi + + COPR_CLI="" + for directory in /usr/bin /usr/local/bin ~/.local/bin ; do + if [ -x "${directory}/copr-cli" ] ; then + COPR_CLI="${directory}/copr-cli" + break + fi + done + if [ "${COPR_CLI}" == "" ] ; then + echo >&2 "ERROR: copr-cli not found!" + exit 1 + fi + echo "Using ${COPR_CLI}" + + ${COPR_CLI} build --nowait ppa ${SRPM} +fi diff --git a/make-srpm b/make-srpm new file mode 100755 index 0000000..3e80c01 --- /dev/null +++ b/make-srpm @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# +# Packaging Scripts +# Copyright (C) 2017-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +# --------------------------------------------------------------------------- +# USAGE: +# ./make-srpm +# --------------------------------------------------------------------------- + + +# ====== Obtain package and version information ============================= +PACKAGE=`grep "^Name:" rpm/*.spec | head -n1 | sed -e "s/Name://g" -e "s/[ \t]*//g"` +PACKAGE_VERSION=`grep "^Version:" rpm/*.spec | head -n1 | sed -e "s/Version://g" -e "s/[ \t]*//g"` +PACKAGE_RELEASE=`grep "^Release:" rpm/*.spec | head -n1 | sed -e "s/Release://g" -e "s/[ \t]*//g"` + +echo -e "\x1b[34m###########################################\x1b[0m" +echo -e "\x1b[34mPACKAGE: ${PACKAGE}\x1b[0m" +echo -e "\x1b[34mPACKAGE_VERSION: ${PACKAGE_VERSION}\x1b[0m" +echo -e "\x1b[34mPACKAGE_RELEASE: ${PACKAGE}_RELEASE\x1b[0m" +echo -e "\x1b[34m###########################################\x1b[0m" + +# ====== Check with Debian package's version ================================ +if [ -e debian/changelog ] ; then + DEBIAN_CHANGELOG_HEADER="`head -n1 debian/changelog`" + + # The package name, e.g. MyApplication + DEBIAN_PACKAGE=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/(.*//" -e "s/ //g"` + # The package distribution, e.g. precise, raring, ... + DEBIAN_PACKAGE_DISTRIBUTION=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/[^)]*)//" -e "s/;.*//g" -e "s/ //g"` + # The package's version, e.g. 1.2.3-1ubuntu1 + DEBIAN_PACKAGE_VERSION=`echo ${DEBIAN_CHANGELOG_HEADER} | sed -e "s/.*(//" -e "s/).*//" -e "s/ //g" -e "s/ //g" -e "s/^[0-9]://g"` + # The package's output version, e.g. 1.2.3-1ubuntu + DEBIAN_OUTPUT_VERSION=`echo ${DEBIAN_PACKAGE_VERSION} | sed -e "s/\(ubuntu\|ppa\)[0-9]*$/\1/"` + # The package's Debian version, e.g. 1.2.3-1 + DEBIAN_VERSION=`echo ${DEBIAN_OUTPUT_VERSION} | sed -e "s/\(ubuntu\|ppa\)$//1"` + # The package's upstream version, e.g. 1.2.3 + DEBIAN_UPSTREAM_VERSION=`echo ${DEBIAN_VERSION} | sed -e "s/-[0-9]*$//"` + + if [ "${PACKAGE}-${PACKAGE_VERSION}" != "${DEBIAN_PACKAGE}-${DEBIAN_UPSTREAM_VERSION}" ] ; then + echo >&2 "ERROR: RPM version and Debian version do not match -> ${PACKAGE}-${PACKAGE_VERSION} vs. ${DEBIAN_PACKAGE}-${DEBIAN_UPSTREAM_VERSION}!" +# exit 1 + fi +fi + +if [ -e packaging.conf ] ; then + . ./packaging.conf +fi + + +# ====== Create upstream source package ===================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m" +echo -e "" +if [ "${SKIP_PACKAGE_SIGNING}" != "" -a ${SKIP_PACKAGE_SIGNING} -eq 1 -o "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then + ./make-upstream-package ${PACKAGE} ${PACKAGE_VERSION} "${MAKE_DIST}" -skip-signing +else + ./make-upstream-package ${PACKAGE} ${PACKAGE_VERSION} "${MAKE_DIST}" +fi + +for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do + UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`" + if [ -e "${UPSTREAM_PACKAGE}" ] ; then + break + fi +done +if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then + echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-*.tar.*) found!\x1b[0m" + exit 1 +fi + + +# ====== Create source RPM ================================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating source RPM ============================\x1b[0m" +echo -e "" + +# ------ Initialise RPM build directories ----------------------------------- +for subdir in BUILD BUILDROOT RPMS SOURCES SPECS SRPMS ; do + mkdir -p ${HOME}/rpmbuild/${subdir} +done +find ${HOME}/rpmbuild/SRPMS -name "${PACKAGE}*.rpm" | xargs --no-run-if-empty rm -f +find ${HOME}/rpmbuild/RPMS -name "${PACKAGE}*.rpm" | xargs --no-run-if-empty rm -f +# Copy upstream sources +cp ${UPSTREAM_PACKAGE} ${HOME}/rpmbuild/SOURCES/ +# Patches +if [ -e original ] ; then + find original -name "*" -type f | grep -v "~$" | grep -v ".spec$" | xargs -i§ -n1 cp "§" ${HOME}/rpmbuild/SOURCES/ +fi +# Further patches +find rpm -name "*" -type f | grep -v "~$" | grep -v ".spec$" | xargs -i§ -n1 cp "§" ${HOME}/rpmbuild/SOURCES/ +# The .spec file +cp rpm/${PACKAGE}.spec ${HOME}/rpmbuild/SPECS/ + +# ------ Create source RPM -------------------------------------------------- +rpmbuild -bs rpm/${PACKAGE}.spec +PACKAGE_SRPM=`find ${HOME}/rpmbuild/SRPMS/ -name "${PACKAGE}-*-*.src.rpm"` +if [ ! -e "${PACKAGE_SRPM}" ] ; then + echo >&2 "ERROR: Cannot find SRPM ${PACKAGE_SRPM}!" + exit 1 +fi diff --git a/make-upstream-package b/make-upstream-package new file mode 100755 index 0000000..56df24f --- /dev/null +++ b/make-upstream-package @@ -0,0 +1,103 @@ +#!/usr/bin/env bash +# +# Packaging Scripts +# Copyright (C) 2017-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: thomas.dreibholz@gmail.com + +# Bash options: +set -e + + +# --------------------------------------------------------------------------- +# USAGE: +# ./make-upstream-package package_name version [-skip-signing] +# --------------------------------------------------------------------------- + + +# ====== Check arguments ==================================================== +if [ $# -lt 3 ] ; then + echo >&2 "Usage: $0 package_name version make_dist [-skip-signing]" + exit 1 +fi +PACKAGE="$1" +UPSTREAM_VERSION="$2" +MAKE_DIST="$3" +SKIP_PACKAGE_SIGNING=0 +shift ; shift ; shift +while [ $# -gt 0 ] ; do + if [ "$1" == "-skip-signing" ] ; then + SKIP_PACKAGE_SIGNING=1 + else + echo >&2 "ERROR: Bad argument $0!" + exit 1 + fi + shift +done + + +# ====== Create upstream source package ===================================== +echo -e "" +echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Creating upstream package ======================================\x1b[0m" +echo -e "" +for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do + printf "Looking for ${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE} ... " + UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`" + if [ -e "${UPSTREAM_PACKAGE}" ] ; then + echo "found!" + break + else + echo "not found" + fi +done +if [ ! -e "${UPSTREAM_PACKAGE}" ]; then + rm -f ${PACKAGE}-*.gz ${PACKAGE}"_"*.gz ${PACKAGE}-*.bz2 ${PACKAGE}"_"*.bz2 ${PACKAGE}-*.xz ${PACKAGE}"_"*.xz + + echo -e "\x1b[34m------ Running MAKE_DIST ... ------\x1b[0m" + echo "\$ $MAKE_DIST" + eval "$MAKE_DIST" + + echo -e "\x1b[34m------ Looking for upstream package ... ------\x1b[0m" + for UPSTREAM_PACKAGE_TYPE in xz bz2 gz ; do + UPSTREAM_PACKAGE="`find . -maxdepth 1 -name "${PACKAGE}-*.tar.${UPSTREAM_PACKAGE_TYPE}" -printf '%f'`" + if [ -e "${UPSTREAM_PACKAGE}" ] ; then + break + fi + done + if [ ! -e "${UPSTREAM_PACKAGE}" ] ; then + echo -e "\x1b[34mERROR: No upstream package (${PACKAGE}-*.tar.*) found!\x1b[0m" + exit 1 + fi + + rm -f "${UPSTREAM_PACKAGE}.asc" # Ensure that old signature file is removed! + echo -e "" +fi +echo -e "\x1b[34m==> Upstream package is ${UPSTREAM_PACKAGE} (type is ${UPSTREAM_PACKAGE_TYPE})\x1b[0m" +echo -e "" + + +# ====== Sign upstream source package ======================================= +if [ ! -e "${UPSTREAM_PACKAGE}.asc" ] ; then + if [ ! ${SKIP_PACKAGE_SIGNING} == "1" -a ! "${OVERRIDE_SKIP_PACKAGE_SIGNING}" == "1" ] ; then + echo -e "" + echo -e "\x1b[34m`date +%FT%H:%M:%S`: ====== Sign upstream package ==========================================\x1b[0m" + echo -e "" + echo -e "\x1b[34mSigning upstream package ${UPSTREAM_PACKAGE} ...\x1b[0m" + gpg -sab "${UPSTREAM_PACKAGE}" + else + rm -f "${UPSTREAM_PACKAGE}.asc" + fi +fi diff --git a/merge-debian-changelogs b/merge-debian-changelogs new file mode 100755 index 0000000..c7f3334 --- /dev/null +++ b/merge-debian-changelogs @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Packaging Scripts +# Copyright (C) 2021-2024 by Thomas Dreibholz +# +# 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 . +# +# Contact: dreibh@simula.no +# + +import glob +import os +import re +import sys +import time + + +# ====== Handle arguments ================================================== +if len(sys.argv) < 3: + sys.stderr.write('Usage: ' + sys.argv[0] + ' ppa_changelog distribution_changelog\n') + sys.exit(1) + +changelogNamePPA = sys.argv[1] +changelogNameDistribution = sys.argv[2] + +changelogFilePPA = open(changelogNamePPA, 'r', encoding='utf-8') +changelogFileDistribution = open(changelogNameDistribution, 'r', encoding='utf-8') + +changelogContentsPPA = changelogFilePPA.readlines() +changelogContentsDistribution = changelogFileDistribution.readlines() + + +# ====== Merge changelogs =================================================== +re_entry_header = re.compile(r'^([a-zA-Z0-9-]+ \([0-9a-zA-Z\.~+]+-[0-9]*)') +re_entry_footer = re.compile(r'^ -- .*') +re_empty = re.compile(r'^\S*$') + +topics = [ + { 'regexp': re.compile(r'^ \* .*ew upstream (version|release).*$'), 'count': 0, 'max': 1 }, + { 'regexp': re.compile(r'^ \* .*standards version.*$'), 'count': 0, 'max': 1 }, + { 'regexp': re.compile(r'^ \* .*debian/compat:.*$'), 'count': 0, 'max': 0 } +] + +# ------ Get latest entry from distribution changelog ----------------------- +match = re_entry_header.match(changelogContentsDistribution[0]) +if match == None: + sys.stderr.write('ERROR: Bad header in ' + changelogNameDistribution + '!\n') + sys.exit(1) +latestDistributionEntry = match.group(1) + +# ------ Join all new entries from PPA changelog ---------------------------- +result = [] + +entries = 0 +insideEntry = False +foundLatestDistributionEntryInPPA = False +firstFooter = None +for line in changelogContentsPPA: + # ------ Begin of an entry ----------------------------------------------- + match = re_entry_header.match(line) + if match != None: + + entries = entries + 1 + if entries == 1: + result.append(line) + result.append('\n') + + # ------ Done? -------------------------------------------------------- + elif line[0:len(latestDistributionEntry)] == latestDistributionEntry: + foundLatestDistributionEntryInPPA = True + break + + continue + + # ------ Empty line ------------------------------------------------------ + match = re_empty.match(line) + if match != None: + continue + + # ------ End of an entry ------------------------------------------------- + match = re_entry_footer.match(line) + if match != None: + if entries == 1: + firstFooter = line + continue + + # ------ Topics ---------------------------------------------------------- + skip = False + for topic in topics: + match = topic['regexp'].match(line) + if match != None: + topic['count'] = topic['count'] + 1 + if topic['count'] > topic['max']: + skip = True + break + if skip == True: + continue + + # ------ Add line to output ---------------------------------------------- + if line[0] == ' ': + result.append(line) + continue + + # ------ Something is wrong ---------------------------------------------- + sys.stderr.write('ERROR: Unexpected line: ' + line + '!\n') + sys.exit(1) + + +result.append('\n') +result.append(firstFooter) + + +if foundLatestDistributionEntryInPPA == False: + sys.stderr.write('ERROR: Did not found the latest distribution entry in the PPA changelog!\n') + sys.exit(1) + + +# ------ Print results ------------------------------------------------------ +for line in result: + sys.stdout.write(line) +sys.stdout.write('\n') +for line in changelogContentsDistribution: + sys.stdout.write(line) diff --git a/packaging.conf b/packaging.conf new file mode 100644 index 0000000..a32a731 --- /dev/null +++ b/packaging.conf @@ -0,0 +1,11 @@ +#!/bin/bash + +# --------------------------------------------------------- +MAKE_DIST="./make-dist" +NOT_TARGET_DISTRIBUTIONS="unstable lucid precise trusty xenial" # <<-- Distrubutions which are *not* supported! +MAINTAINER="Thomas Dreibholz " +MAINTAINER_KEY="21412672518D8B2D1862EFEF5CD5D12AA0877B49" +DEBIAN_LAST_ENTRY="" +UBUNTU_LAST_ENTRY="" +SKIP_PACKAGE_SIGNING=0 # <<-- Must be set to 0 (=off) for PPA upload! +# --------------------------------------------------------- diff --git a/rpm/ripe.atlas.cousteau.spec b/rpm/ripe.atlas.cousteau.spec new file mode 100644 index 0000000..4e91c73 --- /dev/null +++ b/rpm/ripe.atlas.cousteau.spec @@ -0,0 +1,51 @@ +Name: ripe.atlas.cousteau +Version: 1.5.0a2.td1 +Release: 1 +Summary: RIPE Atlas Cousteau +Group: Applications/Internet +License: GPLv3 +URL: https://github.com/dreibh/ripe-atlas-cousteau +Source: https://packages.nntb.no/software/ripe.atlas.cousteau/%{name}-%{version}.tar.bz2 + +AutoReqProv: on +BuildRequires: gcc +BuildRequires: python3 +BuildRequires: python3-coverage +BuildRequires: python3-dateutil +BuildRequires: python3-funcsigs +BuildRequires: python3-jsonschema +BuildRequires: python3-mock +BuildRequires: python3-nose +BuildRequires: python3-pip +BuildRequires: python3-requests +BuildRequires: python3-setuptools +BuildRequires: python3-socketio+client +BuildRequires: python3-websocket-client +BuildRoot: %{_tmppath}/%{name}-%{version}-build + + +# This package does not generate debug information (no executables): +%global debug_package %{nil} + +# TEST ONLY: +# define _unpackaged_files_terminate_build 0 + + +%description +A python wrapper around the RIPE ATLAS API. +See https://ripe-atlas-cousteau.readthedocs.io/en/latest/ for details! + +%prep +%setup -n %{name}-%{version} -n %{name}-%{version} + +%build +python3 setup.py build + +%install +python3 setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES + +%clean +rm -rf $RPM_BUILD_ROOT + +%files -f INSTALLED_FILES +%defattr(-,root,root) diff --git a/setup.py b/setup.py index 2bedaa8..6fff8d4 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,9 @@ # import manually __version__ variable __version__ = None -exec(open("ripe/atlas/cousteau/version.py").read()) +exec(open('ripe/atlas/cousteau/version.py').read()) +__version_extra = '.td1' +__version__ = __version__ + __version_extra install_requires = [ "python-dateutil",